C ++如何处理所有可能的玩家移动输入?

时间:2018-09-11 00:14:07

标签: c++

我正在尝试清理从未完成的视频教程系列中遵循的运动代码。我的目的是使角色在任何给定时间只能在X或Y上移动(因此,没有对角线)。角色要牢记面对的方向。

我的问题是,玩家仍然可以按任意键,或者不小心同时按两个键。

例如如果您向上移动并向右转,则在松开向上键之前不小心按向右键。

或者,如果您按Up键,则在继续按Up的同时按放开Right键即可向右微动,放开Right键后,玩家应继续向上移动,而不必重新按Up键。等

只需确保直观地处理所有可能的输入用例即可。

编辑:到目前为止,这是代码,我遇到奇怪的错误,我不知道怎么了

#pragma once
#include "../game.h"
#include "ECS.h"
#include "Components.h"
#include <list>

using namespace std;




class KeyboardController : public Component
{
public:
    TransformComponent *transform;
    SpriteComponent *sprite;

    std::list<SDL_Event> keyDownList;
    SDL_Event lastDirection;

    void updateKeyState()
    {
        if (Game::event.type == SDLK_ESCAPE) {
            Game::isRunning = false;
        }
        else if (Game::event.type == SDL_KEYDOWN) {
            keyDownList.push_back(Game::event.key.keysym.sym);
        }
        else if (Game::event.type == SDL_KEYUP) {
            keyDownList.remove(Game::event.key.keysym.sym);
        }
    }

    void init() override
    {
        transform = &entity->getComponent<TransformComponent>();
        sprite = &entity->getComponent<SpriteComponent>();






    }




    void update() override
    {
        void updateKeyState();
        void updateMovement();

    }



};

严重性代码描述项目文件行抑制状态 错误(活动)E0304没有重载函数“ std :: list <_Ty,_Alloc> :: push_back [with _Ty = SDL_Event,_Alloc = std :: allocator]”的实例与参数列表沙箱C:\ file_path \ KeyboardController.h匹配31

严重性代码描述项目文件行抑制状态 错误(活动)E0415不存在合适的构造函数,无法从“ SDL_Keycode”转换为“ SDL_Event”沙箱C:\ file_path \ KeyboardController.h 34

1 个答案:

答案 0 :(得分:2)

基本上,您应该通过将按键事件和玩家移动之间的逻辑分开来清理代码。因此,您的update()方法可能如下所示:

void update() override
{
    updateKeyState();
    updateMovement();
}

由于您只希望播放器垂直或水平移动(绝不对角移动),因此必须将按键顺序存储在易于访问的数据结构中。我认为您可以使用doubly-linked list

std::list<SDL_Event> keyDownList;

我们还应该存储最后按下的键,以恢复播放器的空闲动画:

SDL_Event lastDirection;

updateKeyState() 方法应在链接列表中添加密钥或从中删除密钥。我们还应该通过按ESC来检查玩家是否想离开游戏:

void updateKeyState() {
    if (Game::event.type == SDLK_ESCAPE) {
        Game::isRunning = false;
    } else if (Game::event.type == SDL_KEYDOWN) {
        keyDownList.push_back(Game::event.key.keysym.sym);
    } else if (Game::event.type == SDL_KEYUP) {
        keyDownList.remove(Game::event.key.keysym.sym);
    }
}

updatePlayerMovement() 方法是发生魔术的地方。我们基本上应该检查首先按下哪个键,并相应地更新玩家位置。我们还将向下键保存在lastDirection字段中,以便在不按任何键时使用它。

void updateMovement() {
    // if any key is down
    if (keyDownList.size() > 0) {
        const SDL_Event downKey = keyDownList.front();
        switch (downKey) {
            case SDLK_w:
                transform->velocity.y = -1;
                transform->velocity.x = 0;
                sprite->Play("BackWalk");
                lastDirection = downKey;
                break;
            case SDLK_a:
                transform->velocity.x = -1;
                transform->velocity.y = 0;
                sprite->Play("SideWalk");
                sprite->spriteFlip = SDL_FLIP_HORIZONTAL;
                lastDirection = downKey;
                break;
            case SDLK_s:
                transform->velocity.y = 1;
                transform->velocity.x = 0;
                sprite->Play("FrontWalk");
                lastDirection = downKey;
                break;
            case SDLK_d:
                transform->velocity.x = 1;
                transform->velocity.y = 0;
                sprite->Play("SideWalk");
                sprite->spriteFlip = SDL_FLIP_NONE;
                lastDirection = downKey;
                break;
        }
    } else {
        // no key is down, handle idle situations
        transform->velocity.x= 0;
        transform->velocity.y = 0;

        switch (lastDirection) {
            case SDLK_w:
                sprite->Play("BackIdle");
                break;
            case SDLK_a:
                sprite->Play("SideIdle");
                break;
            case SDLK_s:
                sprite->Play("FrontIdle");
                break;
            case SDLK_d:
                sprite->Play("SideIdle");
                break;
        }
    }
}

注意:我没有测试此代码,因为我没有您游戏中的代码和结构。因此,您可能需要在此处和此处进行编辑,以使其适合您。