在 SDL C++ 中移动精灵
moving sprite in SDL c++
我想用箭头按钮在屏幕上移动精灵。但是当旧的精灵还在屏幕上时,精灵就被渲染了。所以我最终得到了很多点screenshot(我的精灵图像是一个点)。
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;
};
我的 main.cpp 文件。它有一些对 input.h 和 sdl.h 的引用,但它们并不重要
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;
}
这是我的结果:screenshot。我怎样才能移动现有的精灵而不是创建一个新的?或者删除旧的精灵?
简而言之,您需要在绘制每一帧之前清屏。
与其直接写入 window 表面,我建议使用 SDL_Renderer 将图形绘制到后台缓冲区,即隐藏表面。
在绘制到后台缓冲区之前,使用 SDL_RenderClear() 函数清除后台缓冲区。或者如果你知道你会覆盖它,只保存这个函数调用。
一旦您的后备缓冲区准备好显示,将当前帧缓冲区与后备缓冲区切换,即调用 SDL_RenderPresent()
我想用箭头按钮在屏幕上移动精灵。但是当旧的精灵还在屏幕上时,精灵就被渲染了。所以我最终得到了很多点screenshot(我的精灵图像是一个点)。
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;
};
我的 main.cpp 文件。它有一些对 input.h 和 sdl.h 的引用,但它们并不重要
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;
}
这是我的结果:screenshot。我怎样才能移动现有的精灵而不是创建一个新的?或者删除旧的精灵?
简而言之,您需要在绘制每一帧之前清屏。
与其直接写入 window 表面,我建议使用 SDL_Renderer 将图形绘制到后台缓冲区,即隐藏表面。
在绘制到后台缓冲区之前,使用 SDL_RenderClear() 函数清除后台缓冲区。或者如果你知道你会覆盖它,只保存这个函数调用。
一旦您的后备缓冲区准备好显示,将当前帧缓冲区与后备缓冲区切换,即调用 SDL_RenderPresent()