C++游戏开发2
图片渲染知识
加载图片
查看EasyX文档,以加载test.jpg为例
IMAGE img;
loadimage(&img, _T("test.jpg"));
渲染图片
putimage(100,200,&img);
//图片左上角坐标
动画基础
动画的数据逻辑
确保动画序列帧的能够间隔固定的时间进行切换,类比定时器的概念实现一个计数器
定义
idx_current_anim
来存储当前动画的帧索引定义
static int counter
变量用来记录当前动画帧一共播放了几个游戏帧
==使用static确保计数器只在第一个游戏帧被初始化为0==
通过if判断语句使得每五个游戏帧切换一个动画帧;随后考虑到动画帧序列播放结束后的行为,当动画的帧索引到达动画帧总数时,将索引重置为0,从而使得动画循环播放
定义
const int PLAYER_ANIM_NUM = 6;
- 使动画循环播放,可书写下列代码
1 | if (++counter % 5 == 0) |
动画的渲染
首先将每一张图片加载到程序中
定义IMAGE对象数组
IMAGE img_player_left[PLAYER_ANIM_NUM];
IMAGE img_player_right[PLAYER_ANIM_NUM];
图片命名十分有规律可使用循环来加载图片.在使用Unicode字符集的情况下,可以使用wstring来拼凑出文件的路径,再传递给loadimage函数,将图片传递到数组中
1
2
3
4
5
6
7
8
9
10
11
12
13void LoadAnimation()
{
for (size_t i = 0; i < PLAYER_ANIM_NUM; i++)
{
std::wstring path = L"img/paimon_left_" + std::to_wstring(i) + L".png";
loadimage(&img_paimon_left[i], path.c_str());
}
for (size_t i = 0; i < PLAYER_ANIM_NUM; i++)
{
std::wstring path = L"img/paimon_right_" + std::to_wstring(i) + L".png";
loadimage(&img_paimon_right[i], path.c_str());
}
}之前定义的动画帧索引此时边可以直接当做IMAGE数组的索引来使用
putimage(500, 500, &img_paimon_left[index_current_anim]);
处理带有透明度的图片素材
解决思路:类比putimage函数封装一个putimage_alpha函数,借助系统绘图函数比较轻巧的实现
1 |
|
将函数替换putimage_alpha(500, 500, &img_paimon_left[index_current_anim]);
键盘控制角色移动
常规思路
定义POINT player_pos = { 500, 500 };
用来存储玩家的位置,并将动画渲染的位置改为player_pos的坐标putimage_alpha(player_pos.x, player_pos.y, &img_paimon_left[index_current_anim]);
定义速度 int PLAYER_SPEED = 5;
在游戏主循环中通过函数判断键盘按下状态从而实现角色移动效果
1 | if (msg.message == WM_KEYDOWN) |
问题
- 断续:由于当我们按下方向键时,WM_KEYDOWN消息进入事件队列,当保持按键按下一定时间后才会有接连不断的消息被触发
- 卡顿:keydown消息的产生与游戏主循环异步进行,且触发的频率与操作系统和硬件设备相关,导致有些游戏帧中时间处理部分对多个WM_KEYDOWN消息进行了处理,其余游戏帧中KEY_DOWN较少或几乎没有,导致角色在某些游戏帧中走得远有些走得近
实际需求:按键按下时,保证角色在某一个游戏帧中都能连续的移动;即玩家按键按下时,KEYD_DOWN消息触发,标志着角色开始移动,玩家按键抬起时,KEYUP消息触发,标志着角色结束移动
解放方法
解决思路:定义布尔变量标识玩家运动状态,不直接对玩家的位置数据进行操作而是改变布尔变量的值
1 | //定义布尔变量用于表示玩家状态 |
优化动画数据逻辑
思路:由于代码相似,可使用类的思想进行封装,定义类用于封装动画相关的数据和逻辑
1 |