问题背景
Cocos2d-x 要跑在 Win32、Android、TV 盒子等多种平台上。不同平台的输入设备差异很大:Win32 用键盘,Android 用触屏和按键,TV 盒子用遥控器。这篇文章分享我在项目中实现的一套统一按键映射方案,让一套代码适配所有输入设备。
平台按键差异概览
1 | ┌─────────────────────────────────────────────────────────────────────┐ |
Cocos2d-x 按键系统架构
原始按键系统的问题
Cocos2d-x 2.x 版本的原始按键分发器(CCKeypadDispatcher)只支持两个按键:
1 | // 原始代码 (CCKeypadDispatcher.cpp) |
这显然无法满足复杂游戏的需求。我们需要扩展按键系统,支持所有按键类型。
扩展后的按键架构
1 | ┌─────────────────────────────────────────────────────────────┐ |
核心修改方案
步骤 1:扩展按键委托协议
1 | // CCKeypadDelegate.h |
步骤 2:修改按键分发器
1 | // CCKeypadDispatcher.cpp |
步骤 3:Win32 平台事件接入
1 | // CCEGLView.cpp (Win32) |
步骤 4:Android 平台事件接入
1 | // TouchesJni.cpp (Android JNI 层) |
步骤 5:Android Java 层修改
1 | // Cocos2dxGLSurfaceView.java |
统一按键编码系统
定义游戏按键枚举
1 | // GameKeyCode.h |
平台按键映射器
1 | // KeyCodeMapper.h |
1 | // KeyCodeMapper.cpp |
业务层使用示例
按键监听层
1 | // BaseLayer.h |
1 | // BaseLayer.cpp |
具体业务层实现
1 | // ShopLayer.h |
1 | // ShopLayer.cpp |
各平台键值参考表
Win32 虚拟键码
| 按键 | 键值 | 按键 | 键值 |
|---|---|---|---|
| VK_UP | 38 | VK_DOWN | 40 |
| VK_LEFT | 37 | VK_RIGHT | 39 |
| VK_RETURN | 13 | VK_ESCAPE | 27 |
| VK_SPACE | 32 | VK_TAB | 9 |
| VK_F1 | 112 | VK_F2 | 113 |
| ‘0’-‘9’ | 48-57 | ‘A’-‘Z’ | 65-90 |
Android 按键码
| 按键 | 键值 | 按键 | 键值 |
|---|---|---|---|
| KEYCODE_DPAD_UP | 19 | KEYCODE_DPAD_DOWN | 20 |
| KEYCODE_DPAD_LEFT | 21 | KEYCODE_DPAD_RIGHT | 22 |
| KEYCODE_DPAD_CENTER | 23 | KEYCODE_ENTER | 66 |
| KEYCODE_BACK | 4 | KEYCODE_MENU | 82 |
| KEYCODE_HOME | 3 | KEYCODE_VOLUME_UP | 24 |
| KEYCODE_0 | 7 | KEYCODE_1 | 8 |
遥控器按键码(基于 Android)
| 按键 | 键值 | 说明 |
|---|---|---|
| KEYCODE_DPAD_UP | 19 | 方向上 |
| KEYCODE_DPAD_DOWN | 20 | 方向下 |
| KEYCODE_DPAD_LEFT | 21 | 方向左 |
| KEYCODE_DPAD_RIGHT | 22 | 方向右 |
| KEYCODE_DPAD_CENTER | 23 | 确定/OK |
| KEYCODE_BACK | 4 | 返回 |
| KEYCODE_MENU | 82 | 菜单 |
| KEYCODE_HOME | 3 | 主页 |
| KEYCODE_VOLUME_UP | 24 | 音量+ |
| KEYCODE_VOLUME_DOWN | 25 | 音量- |
小结
Cocos2d-x 多平台按键映射的核心思路:
- 统一抽象:定义平台无关的游戏按键枚举(GameKeyCode)
- 映射层:建立平台按键码到游戏按键码的双向映射
- 分发器改造:扩展 CCKeypadDispatcher 支持所有按键类型
- 平台适配:在 Win32/Android 等平台层接入所有按键事件
- 业务隔离:业务层只处理统一的游戏按键码,不用关心平台差异
这套方案我在 TV 游戏项目中用过,一套代码同时支持 Win32 调试、Android 手机和遥控器操作。