Ejemplo n.º 1
0
// Render the screen.
void render() {
	initAliveAliens();
	drawAliens(framePointer0);
	drawTank(false, 0, 0);
	drawBunkers(framePointer0);
	drawStats(framePointer0);
}
Ejemplo n.º 2
0
static void draw(void)
{
	drawBackground(background);
	
	drawStars();
	
	blit(earthTexture, earth.x, earth.y, 1);
	
	drawFighters();
	
	drawEffects();
	
	blit(logo, SCREEN_WIDTH / 2, 50, 1);
	
	blit(pandoranWar, SCREEN_WIDTH / 2, 110, 1);
	
	drawText(10, SCREEN_HEIGHT - 25, 14, TA_LEFT, colors.white, "Copyright Parallel Realities, 2015-2016");
	drawText(SCREEN_WIDTH - 10, SCREEN_HEIGHT - 25, 14, TA_RIGHT, colors.white, "Version %.2f.%d", VERSION, REVISION);
	
	switch (show)
	{
		case SHOW_TITLE:
			drawWidgets("title");
			break;
			
		case SHOW_STATS:
			drawStats();
			break;
			
		case SHOW_OPTIONS:
			drawOptions();
			break;
	}
}
Ejemplo n.º 3
0
void WI_Drawer(void)
{
    dgl_borderedprojectionstate_t bp;

    /// @todo Kludge: dj: Clearly a kludge but why?
    if(ILS_NONE == inState)
    {
        drawYouAreHere = true;
    }
    /// kludge end.

    GL_ConfigureBorderedProjection(&bp, BPF_OVERDRAW_MASK|BPF_OVERDRAW_CLIP,
        SCREENWIDTH, SCREENHEIGHT, Get(DD_WINDOW_WIDTH), Get(DD_WINDOW_HEIGHT), cfg.inludeScaleMode);
    GL_BeginBorderedProjection(&bp);

    drawBackground();

    if(ILS_SHOW_STATS != inState)
    {
        drawLocationMarks();
        drawEnteringTitle();
    }
    else
    {
        drawFinishedTitle();
        drawStats();
    }

    GL_EndBorderedProjection(&bp);
}
Ejemplo n.º 4
0
void Entity::draw(sf::RenderWindow* graphics){


	drawStats(graphics);
	drawMessages(graphics);
	graphics->draw(sprite);

}
Ejemplo n.º 5
0
void MainWindow::process()
{
    if (mProcessing && mVideoCapture->isOpened())
    {
        mTimer.restart();
        cv::Mat tFrame;
        *mVideoCapture >> tFrame;
        if (tFrame.data)
        {
            processFrame(tFrame);
            mFrameCounter++;
            drawStats();
            QTimer::singleShot(25, this, SLOT(process()));
        }
    }
Ejemplo n.º 6
0
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), mUI(new Ui::MainWindow)
{
    // Initialize application
    mSettings = new QSettings("Beeldverwerking", "Tram Collision Detection");
    mVideoCapture = 0;
#if WRITE_VIDEO
    mVideoWriter = 0;
#endif

    // Setup interface
    mUI->setupUi(this);
    mGLWidget = new GLWidget();
    mUI->lytVideo->addWidget(mGLWidget);
    mUI->btnStart->setEnabled(false);
    mUI->btnStop->setEnabled(false);

    // Exit action
    mActionExit = new QAction(tr("E&xit"), this);
    mActionExit->setShortcut(tr("Ctrl+Q"));
    mActionExit->setStatusTip(tr("Exit the application"));
    connect(mActionExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    // Recent file actions
    for (int i = 0; i < MaxRecentFiles; ++i) {
        mActionsRecentFiles[i] = new QAction(this);
        mActionsRecentFiles[i]->setVisible(false);
        connect(mActionsRecentFiles[i], SIGNAL(triggered()), this, SLOT(on_actRecentFile_triggered()));
    }

    // Build recent files
    QMenu* fileMenu = mUI->menuFile;
    mActionSeparator = fileMenu->addSeparator();
    for (int i = 0; i < MaxRecentFiles; ++i)
        fileMenu->addAction(mActionsRecentFiles[i]);
    fileMenu->addSeparator();
    fileMenu->addAction(mActionExit);
    updateRecentFileActions();

    // Print a message
#ifdef _OPENMP
    mUI->statusBar->showMessage("Application initialized (multithreaded execution, using up to " + QString::number(omp_get_max_threads()) + " core(s)");
#else
    mUI->statusBar->showMessage("Application initialized (singelthreaded execution)");
#endif
    mFrameCounter = 0; drawStats();
    setTitle();
}
Ejemplo n.º 7
0
static void draw(void)
{
	drawBackground(background);

	blit(planetTexture, planet.x, planet.y, 1);

	drawStars();
	
	drawText(SCREEN_WIDTH / 2, 40, 28, TA_CENTER, colors.white, CHALLENGES_TEXT);
	drawText(SCREEN_WIDTH / 2, 83, 16, TA_CENTER, colors.lightGrey, COMPLETED_TEXT, game.completedChallenges, game.totalChallenges);
	drawText(SCREEN_WIDTH / 2, 110, 16, TA_CENTER, colors.lightGrey, PAGE_TEXT, page + 1, (int)maxPages);

	drawChallenges();

	switch (show)
	{
		case SHOW_CHALLENGES:
			drawWidgets("challenges");
			break;

		case SHOW_MENU:
			drawMenu();
			break;

		case SHOW_STATS:
			drawStats();
			break;
			
		case SHOW_TROPHIES:
			drawTrophies();
			break;

		case SHOW_OPTIONS:
			drawOptions();
			break;
			
		case SHOW_FIGHTER_DB:
			drawFighterDatabase();
			break;
	}
}
Ejemplo n.º 8
0
bool MainWindow::openFile(QString iFilename)
{
    // Do we need to clean up a previous file?
    mProcessing = false;
    if (mVideoCapture != 0)
    {
        // Close and delete the capturer
        if (mVideoCapture->isOpened())
            mVideoCapture->release();
        delete mVideoCapture;
        mVideoCapture = 0;

        // Update the interface
        mUI->btnStart->setEnabled(false);
        mFrameCounter = 0; drawStats();
        setTitle();
    }

    // Check if we can open the file
    if (! QFileInfo(iFilename).isReadable())
    {
        statusBar()->showMessage("Error: could not read file");
        return false;
    }

    // Open input video
    mVideoCapture = new cv::VideoCapture(iFilename.toStdString());
    if(!mVideoCapture->isOpened())
    {
        statusBar()->showMessage("Error: could not open file");
        return false;
    }
    //mGLWidget->setMinimumSize(mVideoCapture->get(CV_CAP_PROP_FRAME_WIDTH), mVideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT));

    // Open output video
#if WRITE_VIDEO
    std::string oVideoFile = argv[2];
    mVideoWriter = new cv::VideoWriter(oVideoFile,
                                       CV_FOURCC('M', 'J', 'P', 'G'),
                                       mVideoCapture->get(CV_CAP_PROP_FPS),
                                       cv::Size(mVideoCapture->get(CV_CAP_PROP_FRAME_WIDTH), mVideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT)),
                                       true);
#endif

    // Reset time counters
    mFrameCounter = 0;
    mTimePreprocess = 0;
    mTimeTrack = 0;
    mTimeTram = 0;
    mTimeDistance = 0;
    mTimePedestrians = 0;
    mTimeVehicle = 0;
    mTimeDraw = 0;

    // Reset age trackers
    mAgeTrack = 0;
    mAgeTram = 0;
    mAgePedestrian = 0;
    mAgeVehicle = 0;

    statusBar()->showMessage("File opened and loaded");
    mUI->btnStart->setEnabled(true);
    mUI->btnStop->setEnabled(false);
    setCurrentFile(iFilename);
    return true;
}
Ejemplo n.º 9
0
int main()
{
    cursorY = 0;
    cursorX = 0;

    int deltaY = 0;
    int deltaX = 0;

    srand(time(0));

    initscr();

	raw();
	keypad(stdscr, TRUE);
	noecho();
	curs_set(0);
	start_color();

	resize_term(30, 80);

    init_pair(1, COLOR_GREEN, COLOR_BLACK);
    init_pair(2, COLOR_YELLOW, COLOR_BLACK);
    init_pair(3, COLOR_RED, COLOR_BLACK);
    init_pair(4, COLOR_CYAN, COLOR_BLACK);
    init_pair(5, COLOR_WHITE, COLOR_RED);
    init_pair(6, COLOR_WHITE, COLOR_GREEN);
    init_pair(7, COLOR_WHITE, COLOR_YELLOW);
    init_pair(8, COLOR_RED, COLOR_RED);
    init_pair(9, COLOR_RED, COLOR_GREEN);
    init_pair(10, COLOR_RED, COLOR_YELLOW);
    init_pair(11, COLOR_WHITE, COLOR_BLACK);
    init_pair(12, COLOR_MAGENTA, COLOR_BLACK);

    while(retry){

        Shop shop;
        SkillTree skillTree;

        breakLoop = false;
        int timeStart = time(0);

        clear();

        cursorY = mapHeight/2;
        cursorX = mapWidth/2+5;

        playerMovementSpeed = 50;
        playerMovementSpeedHelper = 0;

        playerHealth = 100;
        playerMaxHealth = 100;
        playerStamina = 10;
        playerMaxStamina = 10;
        playerStaminaRegen = 250;
        playerStaminaRegenHelper = 0;
        playerAmmo = 100;
        playerBulletSpeed = 30;
        playerDamage = 1;
        playerBulletRange = 20;
        playerFiringSpeed = 500;
        playerFiringSpeedHelper = 0;
        playerClip = 10;
        playerClipLimit = 10;
        playerHiddenClip = 0;
        playerReloading = false;
        playerReloadingRate = 4000;
        playerReloadingHelper = 0;
        playerReloadingModifier = 0;
        playerSpecialWeaponTypes = {0,0,0,0,0,0,0,0,0,0};
        playerWeaponName = {'P','i','s','t','o','l'};
        playerCurrentWeapon = {0,0};
        playerBandages = 0;
        playerBandaging = false;
        playerBandagesHelper = 0;
        playerMeleeDamage = 0;
        playerMeleeDirecton = 0;
        playerMeleeHelper = 0;
        playerStaminaPills = 0;

        playerMoney = 0;
        killMoney = 1;
        playerXP = 0;
        playerXPNeeded = 10;
        playerXPGet = 1;
        playerSkillPoints = 0;
        playerLevel = 1;
        lastTiersUnlocked = false;

        round = 1;
        roundZombies = 5;
        roundZombiesFloat = 5;
        roundZombiesHelper = 0;
        zombieSpawnRate = 5000;
        zombieSpawnRateHelper = 0;
        betweenRoundPause = false;
        betweenRoundPauseHelper = 0;
        zombieForceSpawnHelper = 500;

        playerTimeSurvived = 0;
        playerZombiesKilled = 0;
        playerBulletsFired = 0;
        playerTotalMoneyEarned = 0;
        playerMoves = 0;
        playerTimesBandaged = 0;
        playerTimesReloaded = 0;
        playerAmountBought = 0;
        playerAmountEnteredShop = 0;
        playerAmountEnteredSkillTree = 0;
        playerPeakMoneyOwned = 0;
        playerTotalStaminaPillsUsed = 0;
        playerAmountMelee = 0;
        playerTotalAmountForce = 0;
        playerTimesHit = 0;
        playerTimesPaused = 0;

        timeout(0); //time before the getch passes with no input

        for(int i = 0; i < MAX_ACTORS; i++){
            actorList[i] = NULL;
        }

        for(int i = 0; i < MAX_BULLETS; i++){
            bulletList[i] = NULL;
        }

        for(int y = 0; y < mapHeight; y++){
            for(int x = 0; x < mapWidth; x++){
                if(mapArray[y][x] == 7){
                    mapArray[y][x] = 0;
                }
            }
        }

        int z = 25 + rand() % 125;

        for(int i = 0; i < z; i++){
            int y = rand() % mapHeight;
            int x = rand() % mapWidth;

            if(mapArray[y][x] == 0 && isPassable(y, x) && (cursorY != y || cursorX != x) && mapArray[y-1][x] != 2){
                mapArray[y][x] = 7;
            }
        }

        //put stuff before the game loop here

        while(!breakLoop){
            drawMap();
            drawStats();

            playerTimeSurvived = time(0) - timeStart;

            if(playerMoney > playerPeakMoneyOwned)
                playerPeakMoneyOwned = playerMoney;

            if(playerHealth <= 0){
                if(gameOver()){
                    breakLoop = true;
                    retry = true;
                }else{
                    breakLoop = true;
                    retry = false;
                }
            }

            if(playerStaminaRegenHelper >= playerStaminaRegen){
                if(playerStamina < playerMaxStamina){
                    playerStamina++;
                }
                playerStaminaRegenHelper = 0;
            }

            if(playerClip == 0 && !playerReloading && playerAmmo > 0){
                reloadGun();
            }

            if(playerXP >= playerXPNeeded){
                playerSkillPoints++;
                playerLevel++;
                playerXPNeeded *= 1.1;
                playerXP = 0;
            }

            for(int i = 0; i < MAX_ACTORS; i++){
                if(actorList[i] != NULL && actorList[i]->checkActive()){
                    actorList[i]->update();
                    actorList[i]->draw();
                }
            }

            for(int i = 0; i < MAX_BULLETS; i++){
                if(bulletList[i] != NULL && bulletList[i]->checkActive()){
                    bulletList[i]->update();
                    bulletList[i]->draw();
                }
            }

            for(int i = 0; i < MAX_BULLETS; i++){
                if(specialBulletList[i] != NULL && specialBulletList[i]->checkActive()){
                    specialBulletList[i]->update();
                    specialBulletList[i]->draw();
                }
            }

            if(roundZombiesHelper >= roundZombies){
                betweenRoundPause = true;
            }

            if(betweenRoundPause){
                betweenRoundPauseHelper++;
                if(betweenRoundPauseHelper >= 100000){
                    roundStart();
                }
            }

            if(zombieSpawnRateHelper >= zombieSpawnRate && !betweenRoundPause){
                int y, x;
                int side = rand() % 4;
                switch(side){
                    case 0:
                        y = 0;
                        x = rand() % mapWidth;
                        break;

                    case 1:
                        y = mapHeight - 1;
                        x = rand() % mapWidth;
                        break;

                    case 2:
                        y = rand() % mapHeight;
                        x = 0;
                        break;

                    case 3:
                        y = rand() % mapHeight;
                        x = mapWidth - 1;
                        break;

                }
                if(isPassable(y, x)){
                    Actor *newActor = new Actor();

                    newActor->setAppearance('@', 1);
                    newActor->setPos(y, x);
                    newActor->setSpeed(600-round*3);
                    newActor->setHealth(10);
                    newActor->setMaxRange(20);
                    addActorToList(newActor);
                    zombieSpawnRateHelper = 0;
                    roundZombiesHelper++;
                }
            }

            attron(COLOR_PAIR(0));
            move(cursorY, cursorX);
            addch('@');
            attroff(COLOR_PAIR(0));

            bool donePause = false;

            int input = getch();

            switch(input){
                case KEY_UP:
                    deltaY = -1;
                    playerMeleeDirecton = 0;
                    break;

                case KEY_DOWN:
                    deltaY = 1;
                    playerMeleeDirecton = 1;
                    break;

                case KEY_LEFT:
                    deltaX = -1;
                    playerMeleeDirecton = 2;
                    break;

                case KEY_RIGHT:
                    deltaX = 1;
                    playerMeleeDirecton = 3;
                    break;

                case 'w':
                    addBulletToList(0);
                    break;

                case 's':
                    addBulletToList(1);
                    break;

                case 'a':
                    addBulletToList(2);
                    break;

                case 'd':
                    addBulletToList(3);
                    break;

                case 'r':
                    reloadGun();
                    break;

                case 'n':
                    if(betweenRoundPause){
                        roundStart();
                        playerTotalAmountForce++;
                    }
                    break;

                case 'm':
                    if(!betweenRoundPause && zombieForceSpawnHelper >= 500){
                        int y, x;
                        int side = rand() % 4;
                        switch(side){
                            case 0:
                                y = 0;
                                x = rand() % mapWidth;
                                break;

                            case 1:
                                y = mapHeight - 1;
                                x = rand() % mapWidth;
                                break;

                            case 2:
                                y = rand() % mapHeight;
                                x = 0;
                                break;

                            case 3:
                                y = rand() % mapHeight;
                                x = mapWidth - 1;
                                break;

                        }
                        if(isPassable(y, x)){
                            Actor *newActor = new Actor();

                            newActor->setAppearance('@', 1);
                            newActor->setPos(y, x);
                            newActor->setSpeed(600-round*3);
                            newActor->setHealth(10);
                            newActor->setMaxRange(20);
                            addActorToList(newActor);
                            zombieSpawnRateHelper = 0;
                            roundZombiesHelper++;
                            zombieForceSpawnHelper = 0;
                        }
                        playerTotalAmountForce++;
                    }
                    break;

                case 't':
                    playerAmountEnteredSkillTree++;
                    skillTree.skillScreen();
                    break;

                case 'b':
                    if(playerHealth < playerMaxHealth && playerBandages > 0 && !playerReloading){
                        playerBandaging = true;
                    }
                    break;

                case 'v':
                    if(playerStaminaPills > 0 && playerStamina < playerMaxStamina){
                        if(playerStamina + playerStamina/2 <= playerMaxStamina){
                            playerStamina += playerStamina/2;
                        }else{
                            playerStamina = playerMaxStamina;
                        }
                        playerStaminaPills--;
                    }

                case 'e':
                    if(playerMeleeDamage > 0 && playerMeleeHelper >= 500){
                        for(int i = 0; i < MAX_BULLETS; i++){
                            if(bulletList[i] == NULL || !bulletList[i]->checkActive()){
                                int y, x;
                                Bullet *newBullet = new Bullet();
                                y = cursorY;
                                x = cursorX;
                                newBullet->setDirection(playerMeleeDirecton);
                                if(playerMeleeDamage < 4){
                                    if(playerMeleeDirecton == 0 || playerMeleeDirecton == 1){
                                        newBullet->setAppearance('|', 11);
                                    }else if(playerMeleeDirecton == 2 || playerMeleeDirecton == 3){
                                        newBullet->setAppearance('-', 11);
                                    }
                                }else if(playerMeleeDamage >= 4){
                                    if(playerMeleeDirecton == 0 || playerMeleeDirecton == 1){
                                        newBullet->setAppearance('|', 12);
                                    }else if(playerMeleeDirecton == 2 || playerMeleeDirecton == 3){
                                        newBullet->setAppearance('-', 12);
                                    }

                                }
                                newBullet->setPos(y, x);
                                newBullet->setSpeed(50);
                                if(playerMeleeDamage == 5){
                                    newBullet->setRange(3);
                                }else{
                                    newBullet->setRange(2);
                                }
                                newBullet->setDamage(playerMeleeDamage);
                                bulletList[i] = newBullet;
                                playerMeleeHelper = 0;
                                playerAmountMelee++;
                                break;
                            }
                        }
                    }
                    break;

                case 'p':
                    mvprintw(13, mapWidth+2, "GAME PAUSED - PRESS P TO UNPAUSE");
                    mvprintw(14, mapWidth+2, "PRESS R TO RESET THE GAME");
                    mvprintw(15, mapWidth+2, "WARNING: YOU WON'T SEE THE FINAL STATS");
                    playerTimesPaused++;
                    while(!donePause){
                        int input = getch();
                        if(input == 'p'){
                            donePause = true;
                        }else if(input == 'r'){
                            breakLoop = true;
                            donePause = true;
                        }
                    }
                    break;

                case ' ':
                    if(mapArray[cursorY][cursorX] == 5){
                        playerAmountEnteredShop++;
                        shop.shopScreen();
                    }
                    break;

                default:
                    break;

            }

            if(isPassable(cursorY + deltaY, cursorX + deltaX) && playerMovementSpeedHelper >= playerMovementSpeed && playerStamina > 0){
                cursorY += deltaY;
                cursorX += deltaX;
                if(input == KEY_UP || input == KEY_DOWN || input == KEY_LEFT || input == KEY_RIGHT){
                    playerMovementSpeedHelper = 0;
                    playerMoves++;
                    playerStamina--;
                    playerStaminaRegenHelper = 0;
                }
            }

            deltaX = 0;
            deltaY = 0;

            playerMovementSpeedHelper++;
            playerStaminaRegenHelper++;
            playerFiringSpeedHelper++;
            playerMeleeHelper++;
            zombieSpawnRateHelper++;
            zombieForceSpawnHelper++;

            if(playerReloading){
                playerReloadingHelper++;
                if(playerReloadingHelper >= playerReloadingRate){
                    playerReloading = false;
                    playerAmmo += playerHiddenClip;
                    if(playerAmmo - playerClipLimit > 0){
                        playerAmmo -= playerClipLimit;
                        playerClip = playerClipLimit;
                    }else{
                        playerAmmo -= playerClipLimit;
                        playerClip = playerClipLimit + playerAmmo;
                        playerAmmo = 0;
                    }
                    playerTimesReloaded++;
                    playerHiddenClip = 0;
                    playerReloadingHelper = 0;
                }
            }

            if(playerBandaging){
                playerBandagesHelper++;
                if(playerBandagesHelper >= 1500){
                    if(playerHealth + (playerMaxHealth/4) <= playerMaxHealth){
                        playerHealth += (playerMaxHealth/4);
                    }else{
                        playerHealth = playerMaxHealth;
                    }
                    playerBandaging = false;
                    playerBandages--;
                    playerTimesBandaged++;
                    playerBandagesHelper = 0;
                }
            }

            refresh();
        }
    }

	endwin();
}
Ejemplo n.º 10
0
void gameloop(int randTiles[])
{
	float frame = 0.0;
	int dir = 0;
	
	//game_input->clearKeys();
	
	while (gameIsRunning)
	{
		
		game_timer.start();

		/**
		game_input->readInput();

		if (game_input->windowClosed())
		{
			gameIsRunning = false;
		}
		**/


		while( SDL_PollEvent( &game_event ) )
        {
            //Handle events for the dot
            handleKeyboardInput();

            //If the user has Xed out the window
            if( game_event.type == SDL_QUIT )
            {
                //Quit the program
                gameIsRunning = false;
            }
        }
        
        p1.moveChar();


		

		dir = p1.getDir() * 32;

		if (p1.isWalk())
		{
			frame += 0.05;
			if (frame > 3.0)
			{
				frame = 0.0;
			}
		}
		else 
		{
			frame = 0.0;
		}
		

		game_graphics->beginScene();
		drawGrass(randTiles);

		drawOverlay();

		game_graphics->drawSprite(p1.playerBMP, (int)frame * 32, dir, p1.getX(), p1.getY(), 32, 32);

		//showXY();
		
		game_graphics->drawSprite(sepBar, 0, 0, 640, 0, 7, 480);
	    
	    drawStats();
	    
		game_graphics->endScene();

		if (inMenu)
		{
			gameMenu->displayMenu();
			
		}

		
		//Cap the frame rate
        if( game_timer.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - game_timer.get_ticks() );
        }
		
		
		
	}
}
Ejemplo n.º 11
0
FeatureTracker::feature_track_list FeatureTracker::processImage(feature_track_list& previous_tracks, cv::Mat& image) {
    FrameFeatures frame_features = FrameFeatures::fromImage(detector_, extractor_, image);
    frame_features.drawFeatures(image);
    if (previous_frame_features_.keypoints().size() == 0) {
        FeatureTracker::feature_track_list current_features;
        for (std::size_t i = 0; i < frame_features.keypoints().size(); ++i) {
            const cv::KeyPoint& keypoint = frame_features.keypoints()[i];
            current_features.emplace_back(new FeatureTrack);
            current_features.back()->addFeaturePosition(keypoint.pt.x, keypoint.pt.y);
        }

        previous_frame_features_ = frame_features;
        return current_features;
    }

    std::vector<cv::DMatch> matches = frame_features.match(matcher_, previous_frame_features_);

    std::vector<double> previous_feature_matched(previous_tracks.size(), INFINITY);
    std::vector<std::size_t> matched_feature_assigned(previous_tracks.size(), std::numeric_limits<std::size_t>::max());
    std::vector<bool> current_feature_matched(frame_features.keypoints().size(), false);
    feature_track_list current_tracks(frame_features.keypoints().size());

    double distance_limit = computeDistanceLimitForMatch(matches);

    for (std::size_t i = 0; i < matches.size(); ++i) {
        const cv::DMatch& match = matches[i];

        if (match.distance > distance_limit) {
            continue;
        }

        int query_idx = match.queryIdx;
        int train_idx = match.trainIdx;

        if (current_feature_matched[query_idx]) {
            throw ImpossibleException("Current feature should match only once.");
        }

        if (match.distance < previous_feature_matched[train_idx]) {
            if (!std::isinf(previous_feature_matched[train_idx])) {
                // Revert previous match
                previous_tracks[train_idx]->revertLastPosition();
                
                std::size_t previous_matched_idx = matched_feature_assigned[train_idx];
                current_tracks[previous_matched_idx].reset(new FeatureTrack);
                
                current_feature_matched[previous_matched_idx] = false;
            }

            // Track feature
            const cv::KeyPoint& current_keypoint = frame_features.keypoints()[query_idx];
            current_tracks[query_idx] = previous_tracks[train_idx];
            matched_feature_assigned[train_idx] = query_idx;
            current_tracks[query_idx]->addFeaturePosition(current_keypoint.pt.x, current_keypoint.pt.y);

            previous_feature_matched[train_idx] = match.distance;
            current_feature_matched[query_idx] = true;
        }
    }

    markOutOfViewFeatures(previous_feature_matched, previous_tracks);
    createNewFeatureTracks(current_feature_matched, current_tracks, frame_features);

    drawStats(image, previous_feature_matched, current_feature_matched, current_tracks, matches);

    previous_frame_features_ = frame_features;

    return current_tracks;
}