Cocos2d-x中实现键盘长按持续触发回调与精灵移动的问题
Cocos2d-x中实现键盘长按持续触发回调与精灵移动的问题
嗨,这个问题我之前做Cocos2d-x项目的时候也碰到过!你现在用的onKeyPressed回调本身就是只在按键按下的瞬间触发一次,不管你按住多久都不会重复调用,所以精灵只会动一下就停住了。咱们得换个思路来处理长按的情况,给你两个常用的靠谱解决办法:
方法一:维护按键状态 + 帧更新回调
这个方法的核心是用变量记录按键的按下/释放状态,然后在每一帧里检查这些状态,持续更新精灵位置:
- 先定义几个布尔变量来跟踪按键状态(可以放在你的场景类或者精灵类里):
bool isLeftPressed = false; bool isRightPressed = false; bool isUpPressed = false; bool isDownPressed = false;
- 修改原来的键盘监听回调,只负责更新这些状态变量,不用直接处理移动:
keyBoardListener->onKeyPressed = [this](EventKeyboard::KeyCode keyCode, Event* event) { switch (keyCode) { case EventKeyboard::KeyCode::KEY_LEFT_ARROW: case EventKeyboard::KeyCode::KEY_A: isLeftPressed = true; break; case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: case EventKeyboard::KeyCode::KEY_D: isRightPressed = true; break; case EventKeyboard::KeyCode::KEY_UP_ARROW: case EventKeyboard::KeyCode::KEY_W: isUpPressed = true; break; case EventKeyboard::KeyCode::KEY_DOWN_ARROW: case EventKeyboard::KeyCode::KEY_S: isDownPressed = true; break; } }; keyBoardListener->onKeyReleased = [this](EventKeyboard::KeyCode keyCode, Event* event) { switch (keyCode) { case EventKeyboard::KeyCode::KEY_LEFT_ARROW: case EventKeyboard::KeyCode::KEY_A: isLeftPressed = false; break; case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: case EventKeyboard::KeyCode::KEY_D: isRightPressed = false; break; case EventKeyboard::KeyCode::KEY_UP_ARROW: case EventKeyboard::KeyCode::KEY_W: isUpPressed = false; break; case EventKeyboard::KeyCode::KEY_DOWN_ARROW: case EventKeyboard::KeyCode::KEY_S: isDownPressed = false; break; } };
- 注册帧更新回调,在每一帧里检查状态并移动精灵:
// 在场景初始化的时候调用,注册update函数 this->scheduleUpdate(); // 实现update方法(放在你的场景类里) void YourScene::update(float delta) { const float moveSpeed = 200.0f; // 调整这个值控制移动速度 Vec2 currentPos = yourSprite->getPosition(); if (isLeftPressed) { currentPos.x -= moveSpeed * delta; } if (isRightPressed) { currentPos.x += moveSpeed * delta; } if (isUpPressed) { currentPos.y += moveSpeed * delta; } if (isDownPressed) { currentPos.y -= moveSpeed * delta; } yourSprite->setPosition(currentPos); }
这里的delta是两次帧更新之间的时间差,用它乘以速度可以保证精灵的移动速度不受设备帧率影响,不同设备上移动快慢一致。
方法二:直接获取当前按下的按键集合(更简洁)
Cocos2d-x提供了EventKeyboard::getPressedKeys()方法,可以直接获取当前所有处于按下状态的按键集合,这样就不用自己维护状态变量了:
只需要注册帧更新回调,然后在update里直接检查按键状态:
// 初始化时注册update this->scheduleUpdate(); void YourScene::update(float delta) { const float moveSpeed = 200.0f; Vec2 currentPos = yourSprite->getPosition(); auto pressedKeys = EventKeyboard::getPressedKeys(); // 检查左右键 if (pressedKeys.count(EventKeyboard::KeyCode::KEY_LEFT_ARROW) || pressedKeys.count(EventKeyboard::KeyCode::KEY_A)) { currentPos.x -= moveSpeed * delta; } if (pressedKeys.count(EventKeyboard::KeyCode::KEY_RIGHT_ARROW) || pressedKeys.count(EventKeyboard::KeyCode::KEY_D)) { currentPos.x += moveSpeed * delta; } // 检查上下键 if (pressedKeys.count(EventKeyboard::KeyCode::KEY_UP_ARROW) || pressedKeys.count(EventKeyboard::KeyCode::KEY_W)) { currentPos.y += moveSpeed * delta; } if (pressedKeys.count(EventKeyboard::KeyCode::KEY_DOWN_ARROW) || pressedKeys.count(EventKeyboard::KeyCode::KEY_S)) { currentPos.y -= moveSpeed * delta; } yourSprite->setPosition(currentPos); }
这个方法代码更简洁,不用额外维护状态变量,推荐优先使用。
两种方法都能完美解决你长按按键精灵不持续移动的问题,选哪个看你自己的习惯就行~
备注:内容来源于stack exchange,提问作者bouteffah touiki anas
相关产品推荐
相关产品推荐

