admin 管理员组文章数量: 1086019
编写设定游戏按键的小程序
演示程序下载:
编写设定游戏按键的小程序
随着项目规模的扩大,要考虑的事情增多了。以前不用考虑的按键响应现在也觉得需要进行一番变革了。主要是看到市面上一些大中型的PC游戏都有配置程序,其中有一项功能就是设定游戏的按键。我这里挑选了一些日本C80和C81的有名游戏(《Grief Syndrome》(忧伤综合症,魔法少女小圆),《Fairy Bloom Freesia》(花精灵芙莉季娅),《妖妖剑戟梦想》)的游戏配置程序的截图。
这些小程序可以设置游戏的运行方式,以便让各种类型的显示屏、显卡、操作系统、游戏输入设备能够准确无误地工作,游戏按键的设定也是其一。配置程序将游戏的配置保存为一个文件,游戏中可以载入这些文件。其余的配置我们暂且不讨论,这里讨论的是按键的设置。
有时候我玩别人的游戏,一开始还是有些不适应的,因为游戏开发者的按键习惯不可能与用户的按键习惯完全一致,但是为了不破坏封装性,以及增添简便性,游戏开发者为用户指定了按键设定小程序,这样用户就能够很简单地设定自己喜欢的按键了。我接下来要做的就是游戏开发者做的事情。
为了减少开发的复杂度,我使用开发框架WTL来制作这个小程序。读者如果精通MFC,也可以使用MFC来制作。记得“Lion Heart”组织制作的《Sanae Challenge》(早苗的挑战)中的游戏配置就是用MFC制作的。随后要注意是否使用手柄等一些外设。如果是的话,制作这个程序就一定要用DirectInput,否则无法对游戏设备进行编程。最后
对保存的文件没有什么要求,我一般每一个键保存一个字节。
首先在主对话框CMainDlg类中添加一系列键值,以后用来保存。
BYTE m_Up_Key;BYTE m_Down_Key;BYTE m_Left_Key;BYTE m_Right_Key;BYTE m_Magic_Key;BYTE m_SwitchMagic_Key;BYTE m_Attack_Key;BYTE m_Jump_Key;BYTE m_Accept_Key;BYTE m_Refuse_Key;// 手柄的按键BYTE m_Up_JSKey;BYTE m_Down_JSKey;BYTE m_Left_JSKey;BYTE m_Right_JSKey;BYTE m_Magic_JSKey;BYTE m_SwitchMagic_JSKey;BYTE m_Attack_JSKey;BYTE m_Jump_JSKey;BYTE m_Accept_JSKey;BYTE m_Refuse_JSKey;BYTE m_nJoyStick; // 手柄的编号
键盘最多也不会超过256个键,手柄更不会了,所以使用BYTE类型足够了。如果游戏支持多个手柄,还要保存手柄的编号,以便知道是那个手柄的按键。
初始化这些键值使用-1就行了,像这样:
CMainDlg( void ){ m_Up_Key = -1;m_Down_Key = -1;m_Left_Key = -1;m_Right_Key = -1;m_Magic_Key = -1;m_SwitchMagic_Key = -1;m_Attack_Key = -1;m_Jump_Key = -1;m_Accept_Key = -1;m_Refuse_Key = -1;m_Up_JSKey = -1;m_Down_JSKey = -1;m_Left_JSKey = -1;m_Right_JSKey = -1;m_Magic_JSKey = -1;m_SwitchMagic_JSKey = -1;m_Attack_JSKey = -1;m_Jump_JSKey = -1;m_Accept_JSKey = -1;m_Refuse_JSKey = -1;}CMainDlg中的OnIdle( )函数是每次渲染对话框的时候会调用,而对按键的检测是在每帧中调用的,所以我们可以将按键检测的代码放在这里,下面是伪代码:virtual BOOL OnIdle(){if ( 需要记录按键 ){if ( 需要记录键盘的按键 ){记录键盘的按键}else if ( 需要记录手柄的按键 ){记录手柄的按键}}}
dinput.h 文件只是对按键使用了#define定义,其实是一些BYTE数字,要是让开发者看到了,他们肯定记不住,更别说用户了,他们更看不懂。所以我必须设置一个数组,它看起来像这样:
const tchar g_KeyMap[256][15] =
{tr( "无效" ),tr( "Esc" ),tr( "1" ),tr( "2" ),tr( "3" ),tr( "4" ),tr( "5" ),tr( "6" ),tr( "7" ),tr( "8" ),tr( "9" ),tr( "0" ),tr( "-" ), // 主键盘上tr( "=" ),tr( "Backspace" ),tr( "Tab" ),tr( "Q" ),tr( "W" ),tr( "E" ),tr( "R" ),tr( "T" ),tr( "Y" ),tr( "U" ),tr( "I" ),tr( "O" ),tr( "P" ),tr( "[" ),tr( "]" ),tr( "Enter" ),tr( "L-Ctrl" ),tr( "A" ),tr( "S" ),tr( "D" ),tr( "F" ),tr( "G" ),tr( "H" ),tr( "J" ),tr( "K" ),tr( "L" ),tr( ";" ),tr( "'" ),tr( "`" ),tr( "L-Shift" ),tr( "\\" ),tr( "Z" ),tr( "X" ),tr( "C" ),tr( "V" ),tr( "B" ),tr( "N" ),tr( "M" ),tr( "," ),tr( "." ),tr( "/" ),tr( "R-Shift" ),tr( "*" ),tr( "L-Alt" ),tr( "Space" ),tr( "Caps Lock" ),tr( "F1" ),tr( "F2" ),tr( "F3" ),tr( "F4" ),tr( "F5" ),tr( "F6" ),tr( "F7" ),tr( "F8" ),tr( "F9" ),tr( "F10" ),tr( "Num Lock" ),tr( "Scroll Lock" ),tr( "7" ),tr( "8" ),tr( "9" ),tr( "-" ),tr( "4" ),tr( "5" ),tr( "6" ),tr( "+" ),tr( "1" ),tr( "2" ),tr( "3" ),tr( "0" ),tr( "." ), // 0x53tr( "无效" ),tr( "无效" ),tr( "OEM-102" ),tr( "F11" ),tr( "F12" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "F13" ),tr( "F14" ),tr( "F15" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "Kana" ),tr( "无效" ),tr( "无效" ),tr( "Abnt-C1" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "Convert" ),tr( "无效" ),tr( "NoConvert" ),tr( "无效" ),tr( "Yen" ),tr( "Abnt-C2" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "=" ),tr( "无效" ),tr( "无效" ),tr( "PreTrack" ),tr( "At" ),tr( "Colon" ),tr( "_" ),tr( "Kanji" ),tr( "Stop" ),tr( "Ax" ),tr( "Unlabeled" ),tr( "无效" ),tr( "NextTrack" ),tr( "无效" ),tr( "无效" ),tr( "Enter" ),tr( "R-Control" ),tr( "无效" ),tr( "无效" ),tr( "Mute" ),tr( "Calculator" ),tr( "Play/Pause" ),tr( "无效" ),tr( "MediaStop" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "Vol-" ),tr( "无效" ),tr( "Vol+" ),tr( "无效" ),tr( "WebHome" ),tr( "," ),tr( "无效" ),tr( "/" ),tr( "无效" ),tr( "SysRq" ),tr( "R-Alt" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "Pause" ),tr( "无效" ),tr( "Home" ),tr( "↑" ),tr( "PageUp" ),tr( "无效" ),tr( "←" ),tr( "无效" ),tr( "→" ),tr( "无效" ),tr( "End" ),tr( "↓" ),tr( "PageDn" ),tr( "Delete" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "L-Windows" ),tr( "R-Windows" ),tr( "Apps" ),tr( "Power" ),tr( "Sleep" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "Wake" ),tr( "无效" ),tr( "WebSearch" ),tr( "WebFavorites" ),tr( "WebRefresh" ),tr( "WebStop" ),tr( "WebForward" ),tr( "WebBack" ),tr( "MyComputer" ),tr( "Mail" ),tr( "MediaSelect" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "?" ),
};const tchar g_JSKeyMap[256][15] =
{tr( "1" ),tr( "2" ),tr( "3" ),tr( "4" ),tr( "5" ),tr( "6" ),tr( "7" ),tr( "8" ),tr( "9" ),tr( "10" ),tr( "11" ),tr( "12" ),tr( "13" ),tr( "14" ),tr( "15" ),tr( "16" ),tr( "17" ),tr( "18" ),tr( "19" ),tr( "20" ),tr( "无效" ), // 现在无法用到tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "↑" ),tr( "↓" ),tr( "←" ),tr( "→" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "无效" ),tr( "?" ),
};
这样映射DIK_宏,显示出来的是一系列按键,用户就能够看得懂了。最后需要保存,可以在OnOK( )函数中进行设置。保存部分的代码如下所示:
bool SaveKeyConfigToFile( void ){FILE* pFile;pFile = fopen( m_ConfigFileName, "wb" );if ( pFile == 0 ) return false;// 写入数值fwrite( &m_Up_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Down_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Left_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Right_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Magic_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_SwitchMagic_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Attack_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Jump_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Accept_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_Refuse_Key, sizeof( BYTE ), 1, pFile );fwrite( &m_nJoyStick, sizeof( BYTE ), 1, pFile );fwrite( &m_Up_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Down_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Left_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Right_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Magic_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_SwitchMagic_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Attack_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Jump_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Accept_JSKey, sizeof( BYTE ), 1, pFile );fwrite( &m_Refuse_JSKey, sizeof( BYTE ), 1, pFile );fclose( pFile ); return true;}
读取配置文件的步骤与此类似,这里不再赘述。
既然对游戏的按键进行了设置,那么就应该在主程序中使用这些预定义的游戏的按键了。我认为一个游戏控制系统至少具备以下几个函数:
bool InitGameInput( void ); // 初始化游戏的输入bool DeleteGameInput( void ); // 删除游戏的输入void UpdateKeyState( void ); // 更新游戏的输入void ReadKeyConfigFromFile( const char* fileName ); // 读取游戏输入的配置文件
同时为了对游戏中的按键是否按下进行判断,决定定义以下这些函数:
bool Up_KeyDown( void );bool Down_KeyDown( void );bool Left_KeyDown( void );bool Right_KeyDown( void );bool Magic_KeyDown( void );bool SwitchMagic_KeyDown( void );bool Attack_KeyDown( void );bool Jump_KeyDown( void );bool Accept_KeyDown( void );bool Refuse_KeyDown( void );
这些函数的实现就不再向大家介绍了。
本文标签: 编写设定游戏按键的小程序
版权声明:本文标题:编写设定游戏按键的小程序 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1693408416a220206.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论