使用SDL2获取所有输入后,如何显示精灵的运动?

时间:2014-03-22 23:25:41

标签: c++ sdl game-engine sdl-2

我是c ++和游戏编程的初学者,我正在尝试创建一个接受来自用户的一系列键盘输入的游戏,并且在按下回车时应该根据按下的键显示精灵中的精灵的动作。

我正在使用SDL 2并且每按一次键就可以移动我的精灵但是我想等待所有输入,然后在用户按下ENTER键后连续显示所有动作。到目前为止,我想出了如下所示的代码。

(我使用了一个计数器变量来保存按下任意箭头键的次数,以及一个用于在屏幕上存储其位置和速度的精灵类。)

SDL_Event e;
bool quit = false;
bool startSprite = false;
Sprite sprite1;
while (!quit)
{
    while (SDL_PollEvent(&e) && startSprite== false)
    {
        if (e.type == SDL_QUIT)
        {
            quit = true;
        }
        if (e.type == SDL_KEYDOWN || e.type == SDL_KEYUP)
        {
            //true if ENTER key is pressed
            if (e.key.keysym.sym == SDLK_RETURN)
            {
                startSprite = true;

            }
            //Handle input for the sprite
            sprite1.handleEvent(e);
        }

    }

    //if the ENTER key is pressed
    if(startSprite==true)
    {
        //Clear the window
        SDL_RenderClear(renderer);

        drawTiles(xTiles, yTiles, background, renderer);

           //if the counter > 0, loop through and display each movement until the 
           //total count number is reached

        if(count>0)
        {
            for(int i=0;i<count;i++)
            {
            sprite1.move();

            //display the image
            drawImages(image, image2, image3, sprite1, renderer);

            //Update the screen
            SDL_RenderPresent(renderer);
            }
            count=0;
        }
        //startSprite==false;
    }

处理精灵事件的代码

void Sprite::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 -= SPRITE_VEL; break;
          case SDLK_DOWN: mVelY += SPRITE_VEL; break;
          case SDLK_LEFT: mVelX -= SPRITE_VEL; break;
          case SDLK_RIGHT: mVelX += SPRITE_VEL; break;
      case SDLK_RETURN: startSprite=true; break;
       }
   count++; 
    }
    //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 += SPRITE_VEL; break;
           case SDLK_DOWN: mVelY -= SPRITE_VEL; break;
           case SDLK_LEFT: mVelX += SPRITE_VEL; break;
           case SDLK_RIGHT: mVelX -= SPRITE_VEL; break;
       case SDLK_RETURN: startSprite=true; break;
       }
   }
}

精灵类的移动功能

void Sprite::move()
{
  //Move the sprite left or right
  mPosX += mVelX;

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

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

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

然而这并不起作用,因为startSprite由于某种原因没有设置为true,我的代码永远不会离开while循环。

如果我从while循环语句中删除条件,则按顺序按箭头键然后按Enter键没有任何反应

然后如果我按箭头键移动精灵,精灵会随着每次按键移动。我完全糊涂了,整天都在这里。我似乎无法弄清楚我哪里出错了。

1 个答案:

答案 0 :(得分:0)

我打算在评论中写这个,但它变得太长了。它可能不是您正在寻找的答案......

如果你想到你的代码中的逻辑,当你按下一个未输入的键时会发生什么会发生handleEvent将运行并且速度将被调整,当你最后按下enter时,移动循环需要超过并开始移动精灵,但是......如果你按下一次又一次,速度将保持不变,因为这些动作相互抵消,并且移动将是两次没有。

您需要做的是推迟处理事件,直到您完全按下返回,这样您才能在输入后开始处理事件。

如果您将事件添加到std::queue<SDL_Event>(使用queue.push_back(e)),则可以在按Enter后循环检索它们,并且对于每个事件调用,handleEvent 移动函数,如果你真的想看到逐步执行的移动,可能会有一点延迟。

它看起来像这样:

while (!queue.empty())
{
    SDL_Event e = queue.front();
    sprite1.handleEvent(e);
    SDL_RenderClear(renderer);
    drawTiles(xTiles, yTiles, background, renderer);
    sprite1.move();
    drawImages(image, image2, image3, sprite1, renderer);

    SDL_Delay(200); // possible delay.

    SDL_RenderPresent(renderer);

    queue.pop();
}