admin管理员组文章数量:1637229
参考
- 《C和C++游戏趣味编程》 童晶
火柴人跑酷
游戏的思路是,玩家通过键盘控制火柴人的奔跑和跳跃,躲避蝙蝠到达终点。游戏地图随机生成,随着关卡数增加,游戏难度越来越大
定义Player类
class Player
{
public:
IMAGE im_show; // 当前时刻要显示的图像
float x_left, y_bottom; // 左下角位置
float vx, vy; // 速度
float width, height; // 图片的宽度、高度
void draw()
{
putimagePng(x_left, y_bottom - height, &im_show);
}
void initialize()
{
loadimage(&im_show, _T("standright.png"));
width = im_show.getwidth();
height = im_show.getheight();
updateXY(WIDTH / 2, HEIGHT / 2);
vx = 10;
vy = 10;
}
void updateXY(float mx, float my)
{
x_left = mx;
y_bottom = my;
}
};
定义全局变量,初始化并显示:
IMAGE im_land;
IMAGE im_bk;
Player player;
void startup()
{
player.initialize();
loadimage(&im_land, _T("land.png"));
loadimage(&im_bk, _T("landscape1.png"));
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
putimage(-100, -100, &im_bk);
putimage(WIDTH / 2, HEIGHT / 2, &im_land);
player.draw();
FlushBatchDraw();
}
通过按键控制角色移动:
void updateWithInput()
{
if (_kbhit())
{
char input = getch();
if (input == 'A')
{
player.x_left -= player.vx;
}
if (input == 'D')
{
player.x_left += player.vx;
}
if (input == 'W')
{
player.y_bottom -= player.vy;
}
if (input == 'S')
{
player.y_bottom += player.vy;
}
}
}
异步输入
利用异步输入函数GetAsyncKeyState(),可以同时识别两个按键被按下的情况,玩家可以用A、S、D、W或左、右、上、下方向键控制火柴人移动:
void updateWithInput()
{
if (_kbhit())
{
if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
{
player.x_left -= player.vx;
}
if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
{
player.x_left += player.vx;
}
if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
{
player.y_bottom -= player.vy;
}
if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S'))
{
player.y_bottom += player.vy;
}
}
}
枚举类型状态切换
火柴人会有向左站立、向右站立、向左奔跑、向右奔跑、向左跳跃、向右跳跃、死亡这7种状态:
在Player类中新增成员变量存储向右站立图像、向左站立图像和角色状态:
IMAGE im_standright;
IMAGE im_standleft;
PlayerStatus playerStatus; // 当前状态
在initialize()中对新增成员变量初始化:
loadimage(&im_standright, _T("standright.png"));
loadimage(&im_standleft, _T("standleft.png"));
playerStatus = standright;
im_show = im_standright;
在updateWithInput()中,当键盘控制角色移动时,角色站立方向也应变化:
if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
{
player.x_left -= player.vx;
player.playerStatus = standleft;
}
if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
{
player.x_left += player.vx;
player.playerStatus = standright;
}
添加奔跑动画
在Player类中添加成员变量ims_runright存储向右奔跑的8张图片,并初始化:
vector<IMAGE> ims_runright;
int animId;
void initialize()
{
loadimage(&im_standright, _T("standright.png"));
loadimage(&im_standleft, _T("standleft.png"));
playerStatus = standright;
im_show = im_standright;
width = im_standright.getwidth();
height = im_standright.getheight();
TCHAR filename[80];
for (int i = 0; i <= 7; i++)
{
swprintf_s(filename, _T("runright%d.png"), i);
IMAGE im;
loadimage(&im, filename);
ims_runright.push_back(im);
}
animId = 0;
updateXY(WIDTH / 2, HEIGHT / 2);
vx = 10;
vy = 10;
}
新增成员函数runRight(),把角色向右奔跑涉及的坐标更新,状态切换和动画效果实现:
void runRight()
{
x_left += vx;
if (playerStatus != runright)
{
playerStatus = runright;
animId = 0;
}
else
{
animId++;
if (animId >= ims_runright.size())
{
animId = 0;
}
}
im_show = ims_runright[animId];
}
实现跳跃
在Player类中添加成员变量存储向右、向左跳跃的图片和重力加速度,并初始化:
IMAGE im_jumpright;
IMAGE im_jumpleft;
float gravity;
void initialize()
{
loadimage(&im_jumpright, _T("jumpright.png"));
loadimage(&im_jumpleft, _T("jumpleft.png"));
vx = 10;
vy = 0;
gravity = 3;
}
添加beginJump(),控制动画切换并给角色一个向上初速度:
void beginJump()
{
if (playerStatus != jumpleft && playerStatus != jumpright) // 已在空中不能起跳
{
if (playerStatus == runleft || playerStatus == standleft)
{
im_show = im_jumpleft;
playerStatus = jumpleft;
}
else if (playerStatus == runright || playerStatus == standright)
{
im_show = im_jumpright;
playerStatus = jumpright;
}
vy = -30;
}
}
新增成员函数updateYcoordinate(),自动完成自由落体运动:
void updateYcoordinate()
{
if (playerStatus == jumpleft || playerStatus == jumpright)
{
vy += gravity;
y_bottom += vy;
if (y_bottom > HEIGHT / 2)
{
y_bottom = HEIGHT / 2; // 保证正好落在地面上
if (playerStatus == jumpleft)
{
playerStatus = standleft;
}
if (playerStatus == jumpright)
{
playerStatus = standright;
}
}
}
}
地面类
class Land
{
public:
IMAGE im_land;
float left_x, right_x, top_y;
float land_width, land_height;
void initialize()
{
loadimage(&im_land, _T("land.png"));
land_width = im_land.getwidth();
land_height = im_land.getheight();
left_x = WIDTH / 2;
right_x = left_x + land_width;
top_y = HEIGHT / 2;
}
void draw()
{
putimage(left_x, top_y, &im_land);
}
};
场景类
场景类包括背景图片和多个地面对象
class Scene
{
public:
IMAGE im_bk;
vector<Land> lands;
void draw()
{
putimage(-100, -100, &im_bk);
for (int i = 0; i < lands.size(); i++)
{
lands[i].draw();
}
}
void initialize()
{
loadimage(&im_bk, _T("landscape1.png"));
for (int i = 1; i <= 6; i++)
{
Land land;
land.initialize();
land.left_x = i * land.land_width;
land.top_y = (i - 1) / 6.0 * HEIGHT;
lands.push_back(land);
}
}
};
碰撞检测
产生一些随机地面:
void initialize()
{
loadimage(&im_bk, _T("landscape1.png"));
lands.clear();
for (int i = 1; i < 10; i++)
{
Land land;
land.initialize();
land.left_x = i * land.land_width;
land.right_x = land.left_x + land.land_width;
land.top_y = HEIGHT / 2 + rand() % 2 * HEIGHT / 10;
lands.push_back(land);
}
}
为Player类添加成员函数isOnLand(),判断角色是否在地面上:
int isOnLand(Land& land, float ySpeed)
{
float x_right = x_left + width;
if (ySpeed <= 0)
{
ySpeed = 0;
}
if (land.left_x - x_left <= width * 0.6 && x_right - land.right_x <= width * 0.6 && abs(y_bottom - land.top_y) <= 5 + ySpeed)
{
return 1;
}
else
{
return 0;
}
}
添加成员函数isNotAllLands(),判断角色是否不在所有地面上:
int isNotOnAllLands(vector<Land>& lands, float speed)
{
for (int i = 0; i < lands.size(); i++)
{
if (isOnLand(lands[i], speed))
{
return 0;
}
}
return 1;
}
修改runRight()和runLeft(),如果角色不在任何地面上,进入跳跃状态:
void runRight(Scene& scene)
{
x_left += vx;
if (isNotOnAllLands(scene.lands, vy))
{
im_show = im_jumpright;
playerStatus = jumpright;
return;
}
}
void runLeft(Scene& scene)
{
x_left -= vx;
if (isNotOnAllLands(scene.lands, vy))
{
im_show = im_jumpleft;
playerStatus = jumpright;
return;
}
}
修改updateYcoordinate(),使角色碰到地面再停止下落:
void updateYcoordinate(Scene& scene)
{
if (playerStatus == jumpleft || playerStatus == jumpright)
{
vy += gravity;
y_bottom += vy;
for (int i = 0; i < scene.lands.size(); i++)
{
if (isOnLand(scene.lands[i], vy))
{
y_bottom = scene.lands[i].top_y;
if (playerStatus == jumpleft)
{
playerStatus = standleft;
}
if (playerStatus == jumpright)
{
playerStatus = standright;
}
break;
}
}
}
}
实现相对运动
让角色位置不变,而背景、地面做相对运动:
class Land
{
void draw(float px, float py)
{
putimage(left_x - px, top_y - py, &im_land); // 绘制地面有一个偏移量
}
};
class Scene
{
void draw(float px, float py)
{
putimage(-px / 20, -100 - py / 20, &im_bk); // 绘制背景有一个偏移量,实现前后景
for (int i = 0; i < lands.size(); i++)
{
lands[i].draw(px, py);
}
}
}
class Player
{
void draw()
{
putimagePng(WIDTH / 2, HEIGHT / 2 - height, &im_show); // 角色位置不动
}
}
无尽关卡与胜负判断
在updateWithoutInput()中,角色跑到最后一个地面上,这一关游戏胜利,level加1,进入下一关;角色掉落画面底部,游戏失败,重新开始这一关:
void updateWithoutInput()
{
player.updateYcoordinate(scene);
int landSize = scene.lands.size();
if (player.x_left > scene.lands[landSize - 1].left_x && abs(player.y_bottom - scene.lands[landSize - 1].top_y) <= 2) // 游戏胜利
{
scene.lastlevel = scene.level;
scene.level++;
scene.initialize();
player.initialize();
}
else if (player.y_bottom > 1.5 * HEIGHT) // 角色落到画面底部,游戏失败
{
scene.lastlevel = scene.level;
scene.initialize();
player.initialize();
}
}
随着level增加,生成的地图更大、地面之间更不连续:
void initialize()
{
loadimage(&im_bk, _T("landscape1.png"));
if (lands.size() == 0) // 默认从第一关开始
{
level = 1;
lastlevel = 1;
}
if (lands.size() == 0 || level > lastlevel) // 如果不升级,则不重新生成场景
{
lands.clear();
Land land1; // 第一关land要在游戏角色下方
land1.initialize();
lands.push_back(land1);
for (int i = 1; i < 10 + level * 2; i++)
{
Land land2;
land2.initialize();
int r1 = randBetweenMinMax(1, 30);
if (r1 > level)
{
land2.left_x = land1.left_x + land2.land_width;
}
else
{
land2.left_x = land1.left_x + 2 * land2.land_width;
}
int r3 = randBetweenMinMax(1, 20);
if (r1 > level)
{
land2.top_y = land1.top_y;
}
else
{
int r3 = randBetweenMinMax(-1, 1);
land2.top_y = WIDTH / 2 + HEIGHT / 10 * r3;
}
land2.right_x = land2.left_x + land2.land_width;
lands.push_back(land2);
land1 = land2;
}
}
}
敌人类
class Enemy
{
public:
IMAGE im_enemy;
float x, y;
float enemy_width, enemy_height;
float x_min, x_max; // 敌人移动的x坐标最大值、最小值
float vx; // x方向速度
void initialize()
{
loadimage(&im_enemy, _T("bat.png"));
enemy_width = im_enemy.getwidth();
enemy_height = im_enemy.getheight();
}
void draw(float px, float py)
{
putimagePng(x - enemy_width / 2 - px, y - enemy_height / 2 - py, &im_enemy);
}
void update()
{
x += vx;
if (x > x_max || x < x_min)
{
vx = -vx;
}
}
};
在场景中添加Enemy变量,并初始化:
vector<Enemy> enemies;
void draw(float px, float py)
{
putimage(-px / 20, -100 - py / 20, &im_bk); // 绘制背景有一个偏移量,实现前后景
for (int i = 0; i < lands.size(); i++)
{
lands[i].draw(px, py);
}
for (int i = 0; i < enemies.size(); i++)
{
enemies[i].draw(px, py);
}
}
void initialize()
{
if (lands.size() == 0 || level > lastlevel) // 如果不升级,则不重新生成场景
{
enemies.clear();
int numEnemy = (level + 3) / 5;
int idStep = lands.size() / (numEnemy + 1); // 敌人在scene中均匀分布
for (int j = 1; j <= numEnemy; j++)
{
Enemy enemy;
enemy.initialize();
int landId = j * idStep;
enemy.x = lands[landId].left_x + lands[landId].land_width / 2;
enemy.y = lands[landId].top_y - enemy.enemy_height;
float movingRange = enemy.enemy_width * (3 + level / 15.0);
enemy.x_min = enemy.x - movingRange;
enemy.x_max = enemy.x + movingRange;
enemy.vx = 2 + level / 10.0;
enemies.push_back(enemy);
}
}
}
在Player类中,添加成员函数isCollideEnemy()判断角色是否和蝙蝠发生碰撞:
int isCollideEnemy(Enemy& enemy)
{
float x_center = x_left + width / 2;
float y_center = y_bottom - height / 2;
if (abs(enemy.x - x_center) <= enemy.enemy_width * 0.5 && abs(enemy.y - y_center) <= enemy.enemy_height * 0.5)
{
return 1;
}
else
{
return 0;
}
}
在updateWithoutInput()中,让所有敌人水平移动,如果与角色碰撞,游戏失败:
for (int i = 0; i < scene.enemies.size(); i++)
{
scene.enemies[i].update(); // 敌人自动更新位置
if (player.isCollideEnemy(scene.enemies[i]))
{
scene.lastlevel = scene.level;
scene.initialize();
player.initialize();
}
}
添加音效
在startup()中添加背景音乐:
mciSendString(_T("open game_music.mp3 alias bkmusic"), NULL, 0, NULL);
mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);
添加胜利音效:
PlayMusicOnce(_T("success.mp3"));
添加失败音效:
PlayMusicOnce(_T("warning.mp3"));
添加五角星
在每一关的终点处放置五角星:
IMAGE im_star;
void draw(float px, float py)
{
// 在最后一个地面上方,放置五角星
putimagePng(lands[lands.size() - 1].left_x + im_star.getwidth() - px, lands[lands.size() - 1].top_y - im_star.getheight() - py, &im_star);
}
完整代码
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include "EasyXPng.h"
#include "Timer.h"
#include <vector>
using namespace std;
#pragma comment(lib,"Winmm.lib")
#define WIDTH 800
#define HEIGHT 600
enum PlayerStatus
{
standleft, standright, runleft, runright, jumpleft, jumpright, die
};
int randBetweenMinMax(int min, int max)
{
int r = rand() % (max - min + 1) + min;
return r;
}
void PlayMusicOnce(TCHAR fileName[80]) // 播放一次音乐函数
{
TCHAR cmdString1[50];
swprintf_s(cmdString1, _T("open %s alias tmpmusic"), fileName); // 生成命令字符串
mciSendString(_T("close tmpmusic"), NULL, 0, NULL); // 先把前面一次的音乐关闭
mciSendString(cmdString1, NULL, 0, NULL); // 打开音乐
mciSendString(_T("play tmpmusic"), NULL, 0, NULL); // 仅播放一次
}
class Land
{
public:
IMAGE im_land;
float left_x, right_x, top_y;
float land_width, land_height;
void initialize()
{
loadimage(&im_land, _T("land.png"));
land_width = im_land.getwidth();
land_height = im_land.getheight();
left_x = WIDTH / 2;
right_x = left_x + land_width;
top_y = HEIGHT / 2;
}
void draw(float px, float py)
{
putimage(left_x - px, top_y - py, &im_land); // 绘制地面有一个偏移量
}
};
class Enemy
{
public:
IMAGE im_enemy;
float x, y;
float enemy_width, enemy_height;
float x_min, x_max; // 敌人移动的x坐标最大值、最小值
float vx; // x方向速度
void initialize()
{
loadimage(&im_enemy, _T("bat.png"));
enemy_width = im_enemy.getwidth();
enemy_height = im_enemy.getheight();
}
void draw(float px, float py)
{
putimagePng(x - enemy_width / 2 - px, y - enemy_height / 2 - py, &im_enemy);
}
void update()
{
x += vx;
if (x > x_max || x < x_min)
{
vx = -vx;
}
}
};
class Scene
{
public:
IMAGE im_bk;
IMAGE im_star;
vector<Land> lands;
vector<Enemy> enemies;
int level;
int lastlevel;
void draw(float px, float py)
{
putimage(-px / 20, -100 - py / 20, &im_bk); // 绘制背景有一个偏移量,实现前后景
for (int i = 0; i < lands.size(); i++)
{
lands[i].draw(px, py);
}
for (int i = 0; i < enemies.size(); i++)
{
enemies[i].draw(px, py);
}
// 在最后一个地面上方,放置五角星
putimagePng(lands[lands.size() - 1].left_x + im_star.getwidth() - px, lands[lands.size() - 1].top_y - im_star.getheight() - py, &im_star);
// 显示这是第几关
TCHAR s[20]; // 字符串
setbkmode(TRANSPARENT); // 文字透明显示
swprintf_s(s, _T("第 %d 关"), level); // 生成文字字符串
settextcolor(RGB(0, 50, 200)); // 设置文字颜色
settextstyle(30, 0, _T("黑体")); // 设置文字大小、字体
outtextxy(WIDTH * 0.45, 30, s); // 输出文字
}
void initialize()
{
TCHAR filename[80];
int i = level % 9 + 1;
swprintf_s(filename, _T("landscape%d.png"), i);
loadimage(&im_bk, filename);
loadimage(&im_star, _T("star.png"));
if (lands.size() == 0) // 默认从第一关开始
{
level = 1;
lastlevel = 1;
}
if (lands.size() == 0 || level > lastlevel) // 如果不升级,则不重新生成场景
{
lands.clear();
Land land1; // 第一关land要在游戏角色下方
land1.initialize();
lands.push_back(land1);
for (int i = 1; i < 10 + level * 2; i++)
{
Land land2;
land2.initialize();
int r1 = randBetweenMinMax(1, 30);
if (r1 > level)
{
land2.left_x = land1.left_x + land2.land_width;
}
else
{
land2.left_x = land1.left_x + 2 * land2.land_width;
}
int r3 = randBetweenMinMax(1, 20);
if (r1 > level)
{
land2.top_y = land1.top_y;
}
else
{
int r3 = randBetweenMinMax(-1, 1);
land2.top_y = WIDTH / 2 + HEIGHT / 10 * r3;
}
land2.right_x = land2.left_x + land2.land_width;
lands.push_back(land2);
land1 = land2;
}
enemies.clear();
int numEnemy = (level + 3) / 5;
int idStep = lands.size() / (numEnemy + 1); // 敌人在scene中均匀分布
for (int j = 1; j <= numEnemy; j++)
{
Enemy enemy;
enemy.initialize();
int landId = j * idStep;
enemy.x = lands[landId].left_x + lands[landId].land_width / 2;
enemy.y = lands[landId].top_y - enemy.enemy_height;
float movingRange = enemy.enemy_width * (3 + level / 15.0);
enemy.x_min = enemy.x - movingRange;
enemy.x_max = enemy.x + movingRange;
enemy.vx = 2 + level / 10.0;
enemies.push_back(enemy);
}
}
}
};
class Player
{
public:
IMAGE im_show; // 当前时刻要显示的图像
IMAGE im_standright;
IMAGE im_standleft;
IMAGE im_jumpright;
IMAGE im_jumpleft;
vector<IMAGE> ims_runright;
vector<IMAGE> ims_runleft;
int animId;
PlayerStatus playerStatus; // 当前状态
float x_left, y_bottom; // 左下角位置
float vx, vy; // 速度
float gravity;
float width, height; // 图片的宽度、高度
void draw()
{
putimagePng(WIDTH / 2, HEIGHT / 2 - height, &im_show); // 角色位置不动
}
void initialize()
{
ims_runleft.clear();
ims_runright.clear();
loadimage(&im_standright, _T("standright.png"));
loadimage(&im_standleft, _T("standleft.png"));
loadimage(&im_jumpright, _T("jumpright.png"));
loadimage(&im_jumpleft, _T("jumpleft.png"));
playerStatus = standright;
im_show = im_standright;
width = im_standright.getwidth();
height = im_standright.getheight();
TCHAR filename[80];
for (int i = 0; i <= 7; i++)
{
swprintf_s(filename, _T("runright%d.png"), i);
IMAGE im;
loadimage(&im, filename);
ims_runright.push_back(im);
}
for (int i = 0; i <= 7; i++)
{
swprintf_s(filename, _T("runleft%d.png"), i);
IMAGE im;
loadimage(&im, filename);
ims_runleft.push_back(im);
}
animId = 0;
updateXY(WIDTH / 2, HEIGHT / 2);
vx = 10;
vy = 0;
gravity = 3;
}
void updateXY(float mx, float my)
{
x_left = mx;
y_bottom = my;
}
void runRight(Scene& scene)
{
x_left += vx;
if (isNotOnAllLands(scene.lands, vy))
{
im_show = im_jumpright;
playerStatus = jumpright;
return;
}
if (playerStatus == jumpleft || playerStatus == jumpright) // 如果是起跳状态
{
im_show = im_jumpright;
}
else
{
if (playerStatus != runright)
{
playerStatus = runright;
animId = 0;
}
else
{
animId++;
if (animId >= ims_runright.size())
{
animId = 0;
}
}
im_show = ims_runright[animId];
}
}
void runLeft(Scene& scene)
{
x_left -= vx;
if (isNotOnAllLands(scene.lands, vy))
{
im_show = im_jumpleft;
playerStatus = jumpright;
return;
}
if (playerStatus == jumpleft || playerStatus == jumpright) // 如果是起跳状态
{
im_show = im_jumpleft;
}
else
{
if (playerStatus != runleft)
{
playerStatus = runleft;
animId = 0;
}
else
{
animId++;
if (animId >= ims_runleft.size())
{
animId = 0;
}
}
im_show = ims_runleft[animId];
}
}
void standStill()
{
if (playerStatus == runleft || playerStatus == standleft)
{
im_show = im_standleft;
}
else if (playerStatus == runright || playerStatus == standright)
{
im_show = im_standright;
}
}
void beginJump()
{
if (playerStatus != jumpleft && playerStatus != jumpright) // 已在空中不能起跳
{
if (playerStatus == runleft || playerStatus == standleft)
{
im_show = im_jumpleft;
playerStatus = jumpleft;
}
else if (playerStatus == runright || playerStatus == standright)
{
im_show = im_jumpright;
playerStatus = jumpright;
}
vy = -30;
}
}
int isCollideEnemy(Enemy& enemy)
{
float x_center = x_left + width / 2;
float y_center = y_bottom - height / 2;
if (abs(enemy.x - x_center) <= enemy.enemy_width * 0.5 && abs(enemy.y - y_center) <= enemy.enemy_height * 0.5)
{
return 1;
}
else
{
return 0;
}
}
int isOnLand(Land& land, float ySpeed)
{
float x_right = x_left + width;
if (ySpeed <= 0)
{
ySpeed = 0;
}
if (land.left_x - x_left <= width * 0.6 && x_right - land.right_x <= width * 0.6 && abs(y_bottom - land.top_y) <= 5 + ySpeed)
{
return 1;
}
else
{
return 0;
}
}
int isNotOnAllLands(vector<Land>& lands, float speed)
{
for (int i = 0; i < lands.size(); i++)
{
if (isOnLand(lands[i], speed))
{
return 0;
}
}
return 1;
}
void updateYcoordinate(Scene& scene)
{
if (playerStatus == jumpleft || playerStatus == jumpright)
{
vy += gravity;
y_bottom += vy;
for (int i = 0; i < scene.lands.size(); i++)
{
if (isOnLand(scene.lands[i], vy))
{
y_bottom = scene.lands[i].top_y;
if (playerStatus == jumpleft)
{
playerStatus = standleft;
}
if (playerStatus == jumpright)
{
playerStatus = standright;
}
break;
}
}
}
}
};
Player player;
Scene scene;
Timer timer;
void startup()
{
mciSendString(_T("open game_music.mp3 alias bkmusic"), NULL, 0, NULL);
mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);
srand(time(0));
scene.initialize();
player.initialize();
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
scene.draw(player.x_left - WIDTH / 2, player.y_bottom - HEIGHT / 2);
player.draw();
FlushBatchDraw();
timer.Sleep(50);
}
void updateWithoutInput()
{
player.updateYcoordinate(scene);
int landSize = scene.lands.size();
if (player.x_left > scene.lands[landSize - 1].left_x && abs(player.y_bottom - scene.lands[landSize - 1].top_y) <= 2) // 游戏胜利
{
PlayMusicOnce((TCHAR*)_T("success.mp3"));
scene.lastlevel = scene.level;
scene.level++;
scene.initialize();
player.initialize();
}
else if (player.y_bottom > 1.5 * HEIGHT) // 角色落到画面底部,游戏失败
{
PlayMusicOnce((TCHAR*)_T("warning.mp3"));
scene.lastlevel = scene.level;
scene.initialize();
player.initialize();
}
for (int i = 0; i < scene.enemies.size(); i++)
{
scene.enemies[i].update(); // 敌人自动更新位置
if (player.isCollideEnemy(scene.enemies[i]))
{
PlayMusicOnce((TCHAR*)_T("warning.mp3"));
scene.lastlevel = scene.level;
scene.initialize();
player.initialize();
}
}
}
void updateWithInput()
{
player.standStill(); // 游戏角色默认为向左或向右静止站立
if (_kbhit())
{
if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
{
player.runRight(scene);
}
else if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
{
player.runLeft(scene);
}
if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
{
player.beginJump();
}
}
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
return 0;
}
版权声明:本文标题:C++入门——实现“火柴人跑酷”游戏 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1729247321a1192290.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论