noe m
noe m

Reputation: 167

moving sprite in SDL c++

I want to move a sprite across the screen with the arrow buttons. But the sprite gets rendered while the old one is still on the screen. So I end up with a lot of dots screenshot (my sprite image is a dot).

dot.h

   //The dot that will move around on the screen
class Dot {
    public:
        //The dimensions of the dot
        SDL_Surface* dot;
        static const int DOT_WIDTH = 20;
        static const int DOT_HEIGHT = 20;
        int SCREEN_WIDTH;
        int SCREEN_HEIGHT;
    //Maximum axis velocity of the dot
    static const int DOT_VEL = 1;

    //Initializes the variables
    Dot(int SCREEN_WIDTH, int SCREEN_HEIGHT) {
        this->SCREEN_WIDTH = SCREEN_WIDTH;
        this->SCREEN_HEIGHT = SCREEN_HEIGHT;
        //Initialize the offsets
        mPosX = 0;
        mPosY = 0;

        //Initialize the velocity
        mVelX = 0;
        mVelY = 0;

        // render dot IMG
        this->dot = SDL::loadBMP("dot.bmp", false, false);

    }

    //Takes key presses and adjusts the dot's velocity
    void handleEvent( SDL_Event& e ) {
        //If a key was pressed
        if( e.type == SDL_KEYDOWN && e.key.repeat == 0 )
        {
            //Adjust the velocity
            switch( e.key.keysym.sym )
            {
                case SDLK_UP: mVelY -= DOT_VEL; break;
                case SDLK_DOWN: mVelY += DOT_VEL; break;
                case SDLK_LEFT: mVelX -= DOT_VEL; break;
                case SDLK_RIGHT: mVelX += DOT_VEL; break;
            }
        }
        //If a key was released
        else if( e.type == SDL_KEYUP && e.key.repeat == 0 )
        {
            //Adjust the velocity
            switch( e.key.keysym.sym )
            {
                case SDLK_UP: mVelY += DOT_VEL; break;
                case SDLK_DOWN: mVelY -= DOT_VEL; break;
                case SDLK_LEFT: mVelX += DOT_VEL; break;
                case SDLK_RIGHT: mVelX -= DOT_VEL; break;
            }
        }
    }

    //Moves the dot
    void move() {
        //Move the dot left or right
        mPosX += mVelX;

        //If the dot went too far to the left or right
        if( ( mPosX < 0 ) || ( mPosX + DOT_WIDTH > SCREEN_WIDTH ) )
        {
            //Move back
            mPosX -= mVelX;
        }

        //Move the dot up or down
        mPosY += mVelY;

        //If the dot went too far up or down
        if( ( mPosY < 0 ) || ( mPosY + DOT_HEIGHT > SCREEN_HEIGHT ) )
        {
            //Move back
            mPosY -= mVelY;
        }
    }

    //Shows the dot on the screen
    void render() {
        //Show the dot
        SDL_Rect dstrect = { mPosX, mPosY};
        SDL_BlitSurface(this->dot, NULL, SDL::screenSurface, &dstrect);

        // SDL_FreeSurface(this->dot);
    }

private:
    //The X and Y offsets of the dot
    int mPosX, mPosY;

    //The velocity of the dot
    int mVelX, mVelY;
};

my main.cpp file. It has some references to input.h and sdl.h but they dont really matter

main.cpp

    //Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
#include <iostream>

#include "Sdl.h"
#include "Dot.h"
#include "Input.h"
class Main {
public:
SDL_Event e;
Input* input;
Dot* dot;
//constructor
Main() {
    //Screen dimension constants
    int SCREEN_WIDTH = 640;
    int SCREEN_HEIGHT = 480;

    SDL::init("NHTV-Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    input = new Input();
    dot = new Dot(SCREEN_WIDTH, SCREEN_HEIGHT);
    this->loop();
}
loop() {
    //Main loop flag
    bool quit = false;

    //While application is running
    while( !input->quit ) {
        gameLoop();
    }
    // run when while loops ends
    this->quit();
}


gameLoop() {
    // SDL::blitSurface(this->dot);
    dot->move();
    if(input->movement) {
        dot->handleEvent(input->getEvent());
        dot->render();
    }
    input->loop();
}
quit() {
    // close sdl process
    SDL::close();
}
};
// arguments for cross-plafrom
int main( int argc, char* args[] ) {
    Main* main = new Main();

    return 0;
}

This is my result: screenshot. How can i move the existing sprite instead of creating a new one? Or delete the old sprite?

Upvotes: 0

Views: 2413

Answers (1)

Luca Cappa
Luca Cappa

Reputation: 1999

In short you need to clear the screen before drawing each frame.

Instead than writing directly to the window surface, I would suggest to use an SDL_Renderer to draw your graphic to a backbuffer, that is an hidden surface.

Before drawing to the backbuffer, use the SDL_RenderClear() function to clear the backbuffer. Or if you know you will overwrite it all, just save this function call.

Once your backbuffer is ready to be shown, switch the current framebuffer with the backbuffer, i.e. calling SDL_RenderPresent()

Upvotes: 2

Related Questions