Reputation: 167
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
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