【问题标题】:moving sprite in SDL c++在 SDL c++ 中移动精灵
【发布时间】:2017-06-06 15:56:18
【问题描述】:

我想用箭头按钮在屏幕上移动精灵。但是当旧的精灵还在屏幕上时,精灵就会被渲染。所以我最终得到了很多点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 的引用,但它们并不重要

ma​​in.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。我怎样才能移动现有的精灵而不是创建一个新的?还是删除旧的精灵?

【问题讨论】:

  • 在渲染点之前尝试在游戏循环中清除屏幕表面(例如将其全部涂黑)。

标签: c++ sdl sdl-2 motion


【解决方案1】:

简而言之,您需要在绘制每一帧之前清除屏幕。

我建议使用 SDL_Renderer 将图形绘制到后台缓冲区,而不是直接写入窗口表面,这是一个隐藏表面。

在绘制到后台缓冲区之前,使用SDL_RenderClear() 函数清除后台缓冲区。或者,如果您知道您将全部覆盖,只需保存此函数调用即可。

一旦你的后台缓冲区准备好显示,用后台缓冲区切换当前帧缓冲区,即调用SDL_RenderPresent()

【讨论】:

  • 感谢您的反馈。但是,如果我调用该函数,我会收到一个错误:error: 'SDL_UpdateRect' was not declared in this scope。它使用与 SDL2 相同的库还是需要下载一个新库?
  • 刚刚更新了答案。使用 SDL2 时,SDL_UpdateRect() 已替换为 SDL_RenderPresent()。
  • 感谢更新,我将SDL_CreateTextureFromSurface(SDL::renderer, this-&gt;dot); SDL_RenderClear(SDL::renderer); SDL_RenderCopy(SDL::renderer, this-&gt;dotTexture, NULL, &amp;dstrect); SDL_RenderPresent(SDL::renderer); 添加到dot::render(),并在SDL::window 初始化后声明SDL::renderer。但是我的窗户现在只显示黑暗?我做错了什么?
  • 你的 dstrect 没有 .h.w 设置,它们被设置为 0。用 SDL_Rect dstrect = { mPosX, mPosY, DOT_WIDTH, DOT_HEIGHT}; 初始化它们修复它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2015-05-20
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多