天天酷跑项目的开发
项目前言
项目是基于Windows,easyX图形库进行开发的,
开发环境:Visual Studio 2022
项目技术最低要求:
常量,变量,数组,循环,函数。
文章目录
- 天天酷跑项目的开发
- 项目前言
- 游戏背景的实现
- 实现玩家的奔跑
- 实现人物的跳跃
- 获取玩家的输入
- 优化帧等待
- 随机出现小乌龟障碍
- 使用结构体优化障碍
- 使用结构体后,重新初始化游戏
- 实现下蹲技能
- 添加柱子障碍物
- 碰撞检测
- 实现血条
- 判断游戏结束 添加背景音乐 添加初始界面
- 优化死亡BUG
- 跨越障碍后计算得分
- 判断游戏胜利
- 源代码
游戏背景的实现
- 使用initgraph()初始化界面;
- 加载背景资源
写好游戏的图像化界面的框架
由于easyX不支持透明图片的的贴图,所以我们要自己写一个透明贴图的函数这里给出3个
// 适用于 y <0 以及y>0的任何情况
void putimagePNG2(int x, int y, IMAGE* picture);
void putimagePNG2(int x, int y, int winWidth, IMAGE* picture);
void putimagePNG(int picture_x, int picture_y, IMAGE* picture);
// 适用于 y <0 以及x<0的任何情况
void putimagePNG2(int x, int y, IMAGE* picture) {
IMAGE imgTmp;
if (y < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, -y,
picture->getwidth(), picture->getheight() + y);
SetWorkingImage();
y = 0;
picture = &imgTmp;
}
if (x < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());
SetWorkingImage();
x = 0;
picture = &imgTmp;
}
putimagePNG(x, y, picture);
}
// 适用于 y <0 以及y>0的任何情况
void putimagePNG2(int x, int y, int winWidth, IMAGE* picture) {
IMAGE imgTmp;
if (y < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, -y,
picture->getwidth(), picture->getheight() + y);
SetWorkingImage();
y = 0;
picture = &imgTmp;
}
if (x < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());
SetWorkingImage();
x = 0;
picture = &imgTmp;
}
else if (x >= winWidth) {
return;
}
else if (x > winWidth - picture->getwidth()) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, 0, winWidth - x, picture->getheight());
SetWorkingImage();
picture = &imgTmp;
}
putimagePNG(x, y, picture);
}
// 载入PNG图并去透明部分
void putimagePNG(int picture_x, int picture_y, IMAGE* picture) //x为载入图片的X坐标,y为Y坐标
{
DWORD* dst = GetImageBuffer(); // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
DWORD* draw = GetImageBuffer();
DWORD* src = GetImageBuffer(picture); //获取picture的显存指针
int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带
int picture_height = picture->getheight(); //获取picture的高度,EASYX自带
int graphWidth = getwidth(); //获取绘图区的宽度,EASYX自带
int graphHeight = getheight(); //获取绘图区的高度,EASYX自带
int dstX = 0; //在显存里像素的角标
// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
for (int iy = 0; iy < picture_height; iy++)
{
for (int ix = 0; ix < picture_width; ix++)
{
int srcX = ix + iy * picture_width; //在显存里像素的角标
int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
int sg = ((src[srcX] & 0xff00) >> 8); //G
int sb = src[srcX] & 0xff; //B
if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
{
dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标
int dr = ((dst[dstX] & 0xff0000) >> 16);
int dg = ((dst[dstX] & 0xff00) >> 8);
int db = dst[dstX] & 0xff;
draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr
| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg
| (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db
}
}
}
}
//定义相关的变量
IMAGE imgBgs[3]; // 背景图片
int bgX[3]; //背景图片的x坐标
int bgSpeed[3] = { 1, 2, 4 };//三重背景以不同速度行驶
三张背景图片需要载入
//直接在初始化中加载到内存
char name[64];
for (int i = 0; i < 3; i++) {
// "res/bg001.png" "res/bg002.png" "res/bg003.png"
sprintf(name, "res/bg%03d.png", i + 1);
loadimage(&imgBgs[i], name);
bgX[i] = 0;
}
注:这里的图片在main.cpp文件夹中的res文件夹下。
再在updateBg的函数中进行渲染;
putimagePNG2(bgX[0], 0, &imgBgs[0]);
putimagePNG2(bgX[1], 119, &imgBgs[1]);
putimagePNG2(bgX[2], 330, &imgBgs[2]);
编译如果遇到C4996错误只需要在项目属性c/c++中关掉SDL检查即可。
如果出现loadimage()的错误,可能是字符集的问题;只需要在项目属性-高级-字符集-使用多字节字符集即可
看一下执行结果。
如果不使用透明贴图函数
图片成功渲染,但是在实际的游戏中,背景是会移动的且遵守基本的物理。
接下来我们需要移动背景。远处的移动慢,中处更快,最近处看起来最快,所以速度可以取int bgSpeed[3] = { 1, 2, 4 };
void moveBg() {
for (int i = 0; i < 3; i++) {
bgX[i] -= bgSpeed[i];
if (bgX[i] < -WIN_WIDTH) {
bgX[i] = 0;
}
}
在main函数中载入死循环 这样背景就可以无休止的移动了
int main(void) {
init();
while (1) {
BeginBatchDraw();
updateBg();
EndBatchDraw();
moveBg();
Sleep(30);
}
//使用beginbatchdraw 和endbatchdraw进行优化渲染。
}
实现玩家的奔跑
IMAGE imgHeros[12];//玩家的帧图片
int heroX; //玩家的x坐标
int heroY; //玩家的y坐标
int heroIndex; //玩家奔跑的图片帧序号
初始化的时候也初始化玩家
// 加载Hero奔跑的图片帧素材
for (int i = 0; i < 12; i++) {
// "res/hero1.png" ... "res/hero12.png"
sprintf(name, "res/hero%d.png", i + 1);
loadimage(&imgHeros[i], name);
}
// 设置玩家的初始位置
heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;
heroY = 345 - imgHeros[0].getheight();
heroIndex = 0;
在Main函数中给hero贴图
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
更改人物帧图片,让人物看起来会动
heroIndex = (heroIndex + 1) % 12;
RUN:
实现人物的跳跃
初始化函数中
heroJump = false;
jumpHeightMax = 345 - imgHeros[0].getheight() - 120;
heroJumpOff = -4;
bool heroJump; //表示玩家正在跳跃
int jumpHeightMax;
int heroJumpOff;
int jump()
{
// 实现跳跃
if (heroJump) {
if (heroY < jumpHeightMax) {
heroJumpOff = 4;
}
heroY += heroJumpOff;
if (heroY > 345 - imgHeros[0].getheight()) {
heroJump = false;
heroJumpOff = -4;
}
}
else { //不跳跃
heroIndex = (heroIndex + 1) % 12;
}
}
void jump() {
heroJump = true;
}
获取玩家的输入
// 处理用户按键的输入
void keyEvent() {
char ch;
if (_kbhit()) { //如果有按键按下,_kbhit()返回 true
ch = _getch(); // _getch()不需要按下回车即可直接读取
if (ch == ' ') {
jump();
}
}
}
main()
int main(void) {
init();
while (1) {
keyEvent();
BeginBatchDraw();
updateBg();
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
EndBatchDraw();
moveBg();
HeroIndex();
jump(heroJump);
Sleep(15);
}
}
优化帧等待
bool update; //表示是否需要马上刷新画面
init()尾部
update = true;
void jump() {
heroJump = true;
update = true;
}
int getDelay() {
static unsigned long long lastTime = 0;
unsigned long long currentTime = GetTickCount();
if (lastTime == 0) {
lastTime = currentTime;
return 0;
}
else {
int ret = currentTime - lastTime;
lastTime = currentTime;
return ret;
}
}
main函数主体
int main(void) {
int timer = 0;
init();
while (1) {
keyEvent();
timer += getDelay();//10
if (timer > 30) {
timer = 0;
update = true;
}
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
EndBatchDraw();
moveBg();
HeroIndex();
jump(heroJump);
}
}
return 0;
}
随机出现小乌龟障碍
定义乌龟相关的变量
IMAGE imgTortoise; //小乌龟
int torToiseX; //小乌龟的水平坐标
int torToiseY; //小乌龟的垂直坐标
bool torToiseExist; //当前窗口是否有小乌龟
在init()函数中,初始化乌龟
// 加载小乌龟素材
loadimage(&imgTortoise, "res/t1.png");
torToiseExist = false;
torToiseY = 345 - imgTortoise.getheight() + 5;
定义一个函数创建小乌龟
void creatTortoise() {
// 创建小乌龟
static int frameCount = 0;
static int torToiseFre = 100;
frameCount++;
if (frameCount > torToiseFre) {
frameCount = 0;
if (!torToiseExist) {
torToiseExist = true;
torToiseX = WIN_WIDTH;
torToiseFre = 200 + rand() % 300;
}
}
if (torToiseExist) {
torToiseX -= bgSpeed[2];
if (torToiseX < -imgTortoise.getwidth()) {
torToiseExist = false;
}
}
}
创建函数对乌龟进行渲染
void updateEnemy() {
// 渲染小乌龟
if (torToiseExist) {
putimagePNG2(torToiseX, torToiseY, WIN_WIDTH, &imgTortoise);
}
}
再把creattortorise
在main函数中调用if语句中
update = false;
BeginBatchDraw();
updateBg();
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
updateEnemy();
EndBatchDraw();
moveBg();
HeroIndex();
creatTortoise();
jump(heroJump);
使用结构体优化障碍
添加头文件\#include <vector>
#define OBSTACLE_COUNT 10
typedef enum {
TORTOISE, //乌龟 0
LION, //狮子 1
OBSTACLE_TYPE_COUNT // 2
} obstacle_type;
vector<vector<IMAGE>>obstacleImgs; //存放所有障碍物的各个图片
typedef struct obstacle {
obstacle_type type; //障碍物的类型
int imgIndex; //当前显示的图片的序号
int x, y; //障碍物的坐标
int speed;
int power; //杀伤力
bool exist;
}obstacle_t;
使用结构体后,重新初始化游戏
obstacle_t obstacles[OBSTACLE_COUNT];
// 游戏的初始化
void init() {
// 创建游戏窗口
initgraph(WIN_WIDTH, WIN_HEIGHT);
// 加载背景资源
char name[64];
for (int i = 0; i < 3; i++) {
// "res/bg001.png" "res/bg002.png" "res/bg003.png"
sprintf(name, "res/bg%03d.png", i + 1);
loadimage(&imgBgs[i], name);
bgX[i] = 0;
}
// 加载Hero奔跑的图片帧素材
for (int i = 0; i < 12; i++) {
// "res/hero1.png" ... "res/hero12.png"
sprintf(name, "res/hero%d.png", i + 1);
loadimage(&imgHeros[i], name);
}
// 设置玩家的初始位置
heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;
heroY = 345 - imgHeros[0].getheight();
heroIndex = 0;
heroJump = false;
jumpHeightMax = 345 - imgHeros[0].getheight() - 120;
heroJumpOff = -4;
update = true;
IMAGE imgTort;
loadimage(&imgTort, "res/t1.png");
vector<IMAGE> imgTortArray;
imgTortArray.push_back(imgTort);
obstacleImgs.push_back(imgTortArray);
IMAGE imgLion;
vector<IMAGE> imgLionArray;
for (int i = 0; i < 6; i++) {
sprintf(name, "res/p%d.png", i + 1);
loadimage(&imgLion, name);
imgLionArray.push_back(imgLion);
}
obstacleImgs.push_back(imgLionArray);
// 初始化障碍物池
for (int i = 0; i < OBSTACLE_COUNT; i++) {
obstacles[i].exist = false;
}
}
创建函数初始化障碍物(我们将用此函数创建所有的障碍物)
void createObstacle() {
int i;
for (i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist == false) {
break;
}
}
if (i >= OBSTACLE_COUNT) {
return;
}
obstacles[i].exist = true;
obstacles[i].imgIndex = 0;
obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);
obstacles[i].x = WIN_WIDTH;
obstacles[i].y = 345 + 5 - obstacleImgs[obstacles[i].type][0].getheight();
if (obstacles[i].type == TORTOISE) {
obstacles[i].speed = 0;
obstacles[i].power = 5; //自己修改
}
else if (obstacles[i].type == LION) {
obstacles[i].speed = 4;
obstacles[i].power = 20;
}
}
再写一个函数进行创建障碍物的数据计算
void createObstacleData() {
static int frameCount = 0;
static int enemyFre = 50;
frameCount++;
if (frameCount > enemyFre) {
frameCount = 0;
enemyFre = 50 + rand() % 50; // 50..99
createObstacle();
}
// 更新所有障碍物的坐标
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
obstacles[i].x -= obstacles[i].speed + bgSpeed[2];
if (obstacles[i].x < -obstacleImgs[obstacles[i].type][0].getwidth() * 2) {
obstacles[i].exist = false;
}
int len = obstacleImgs[obstacles[i].type].size();
obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
}
}
}
在对敌人初始化
void updateEnemy() {
// 渲染小乌龟
//if (torToiseExist) {
// putimagePNG2(torToiseX, torToiseY, WIN_WIDTH, &imgTortoise);
//}
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
putimagePNG2(obstacles[i].x, obstacles[i].y, WIN_WIDTH,
&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
}
}
}
一下是main函数的主体
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
updateEnemy();
EndBatchDraw();
updateEnemy();
moveBg();
HeroIndex();
createObstacleData();
jump(heroJump);
}
实现下蹲技能
IMAGE imgHeroDown[2];
bool heroDown; //表示玩家是否处于下蹲状态
init()中对其初始化
// 初始化障碍物池
for (int i = 0; i < OBSTACLE_COUNT; i++) {
obstacles[i].exist = false;
}
// 加载下蹲素材
loadimage(&imgHeroDown[0], "res/d1.png");
loadimage(&imgHeroDown[1], "res/d2.png");
heroDown = false;
我们写一个heroupdown函数集成up和down方便进行管理
void heroupdown()
{
// 实现跳跃
if (heroJump) {
if (heroY < jumpHeightMax) {
heroJumpOff = 4;
}
heroY += heroJumpOff;
if (heroY > 345 - imgHeros[0].getheight()) {
heroJump = false;
heroJumpOff = -4;
}
}
else if (heroDown) {
static int count = 0;
int delays[2] = { 4, 10 };
count++;
if (count >= delays[heroIndex]) {
count = 0;
heroIndex++;
if (heroIndex >= 2) {
heroIndex = 0;
heroDown = false;
}
}
}
else { //不跳跃
heroIndex = (heroIndex + 1) % 12;
}
}
void down() {
update = true;
heroDown = true;
heroIndex = 0;
}
在接受键盘进行响应
void keyEvent() {
char ch;
if (_kbhit()) { //如果有按键按下,_kbhit()返回 true
ch = _getch(); // _getch()不需要按下回车即可直接读取
if (ch == ' ') {
jump();
}
else if (ch == 'a') {
down();
}
}
}
void updateHero() {
if (!heroDown) {
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
}
else {
int y = 345 - imgHeroDown[heroIndex].getheight();
putimagePNG2(heroX, y, &imgHeroDown[heroIndex]);
}
}
main函数主体
int main(void) {
int timer = 0;
init();
while (1) {
keyEvent();
timer += getDelay();//10
if (timer > 20) {
timer = 0;
update = true;
}
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
//putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
updateHero();
updateEnemy();
EndBatchDraw();
moveBg();
heroupdown();
createObstacleData();
}
}
return 0;
}
添加柱子障碍物
老规矩 加载-初始化
typedef enum {
TORTOISE, //乌龟 0
LION, //狮子 1
OBSTACLE_TYPE_COUNT // 2
HOOK1, //勾子
HOOK2,
HOOK3,
HOOK4,
} obstacle_type;
void createObstacle() {
srand((unsigned)time(NULL));
int i;
for (i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist == false) {
break;
}
}
if (i >= OBSTACLE_COUNT) {
return;
}
obstacles[i].exist = true;
obstacles[i].imgIndex = 0;
//obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);
obstacles[i].type = (obstacle_type)(rand() % 3);
obstacles[i].x = WIN_WIDTH;
obstacles[i].y = 345 + 5 - obstacleImgs[obstacles[i].type][0].getheight();
if (obstacles[i].type == HOOK1) {
obstacles[i].type = (obstacle_type)((int)(obstacles[i].type) + rand() % 4);
}
if (obstacles[i].type == TORTOISE) {
obstacles[i].speed = 0;
obstacles[i].power = 5; //自己修改
}
else if (obstacles[i].type == LION) {
obstacles[i].speed = 4;
obstacles[i].power = 20;
}
else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
obstacles[i].speed = 0;
obstacles[i].power = 20;
obstacles[i].y = 0;
}
}
碰撞检测
typedef struct obstacle {
obstacle_type type; //障碍物的类型
int imgIndex; //当前显示的图片的序号
int x, y; //障碍物的坐标
int speed;
int power; //杀伤力
bool exist;
bool hited;//是否撞击
}obstacle_t;
void preLoadSound(const char* name) {
char cmd[512];
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);
mciSendString(cmd, 0, 0, 0);
}
bool rectIntersect(int x01, int y01, int x02, int y02,
int x11, int y11, int x12, int y12)
{
int zx = abs(x01 + x02 - x11 - x12);
int x = abs(x01 - x02) + abs(x11 - x12);
int zy = abs(y01 + y02 - y11 - y12);
int y = abs(y01 - y02) + abs(y11 - y12);
return (zx <= x && zy <= y);
}
void playSound(const char* name) {
static int index = 1;
char cmd[512];
if (index == 1) {
sprintf_s(cmd, sizeof(cmd), "play %s-1", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "close %s-2", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);
mciSendString(cmd, 0, 0, 0);
index++;
}
else if (index == 2) {
sprintf_s(cmd, sizeof(cmd), "play %s-2", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "close %s-1", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);
mciSendString(cmd, 0, 0, 0);
index = 1;
}
}
void checkHit()
{
for (int i = 0; i < OBSTACLE_COUNT; i++)
{
if (obstacles[i].exist && obstacles[i].hited == false)
{
int a1x, a1y, a2x, a2y;
int off = 20;
if (!heroDown)//非下蹲 奔跑 跳跃
{
a1x = heroX + off;
a1y = heroY + off;
a2x = heroX + imgHeros[heroIndex].getwidth() - off;
a2y = heroY + imgHeros[heroIndex].getheight();
}
else { //下蹲状态
a1x = heroX + off;
a1y = 345 - imgHeroDown[heroIndex].getheight();
a2x = heroX + imgHeroDown[heroIndex].getwidth() - off;
a2y = 345;
}
IMAGE img = obstacleImgs[obstacles[i].type][obstacles[i].imgIndex];
int b1x = obstacles[i].x + off;
int b1y = obstacles[i].y + off;
int b2x = obstacles[i].x + img.getwidth() - off;
int b2y = obstacles[i].y + img.getheight() - 10;
if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
{
heroBlood -= obstacles[i].power;
playSound("res/hit.mp3");
obstacles[i].hited = true;
}
}
}
}
实现血条
优化下蹲:
int delays[2] = { 6, 10 };
改成
int delays[2] = { 8, 30 };
头文件
#include <mmsystem.h>
#pragma comment(lib, “winmm.lib”)
void updateBloodBar() {
drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}
void drawBloodBar(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent) {
LINESTYLE lineStyle;
getlinestyle(&lineStyle);
int lineColor = getlinecolor();
int fileColor = getfillcolor();
if (percent < 0) {
percent = 0;
}
setlinecolor(BLUE);
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);
setfillcolor(emptyColor);
fillrectangle(x, y, x + width, y + height);
setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);
setfillcolor(fillColor);
setlinecolor(fillColor);
if (percent > 0) {
fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);
}
setlinecolor(lineColor);
setfillcolor(fillColor);
setlinestyle(&lineStyle);
}
void init() {
// 创建游戏窗口
initgraph(WIN_WIDTH, WIN_HEIGHT);
// 加载背景资源
char name[64];
for (int i = 0; i < 3; i++) {
// "res/bg001.png" "res/bg002.png" "res/bg003.png"
sprintf(name, "res/bg%03d.png", i + 1);
loadimage(&imgBgs[i], name);
bgX[i] = 0;
}
// 加载Hero奔跑的图片帧素材
for (int i = 0; i < 12; i++) {
// "res/hero1.png" ... "res/hero12.png"
sprintf(name, "res/hero%d.png", i + 1);
loadimage(&imgHeros[i], name);
}
// 设置玩家的初始位置
heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;
heroY = 345 - imgHeros[0].getheight();
heroIndex = 0;
heroJump = false;
jumpHeightMax = 345 - imgHeros[0].getheight() - 120;
heroJumpOff = -4;
update = true;
IMAGE imgTort;
loadimage(&imgTort, "res/t1.png");
vector<IMAGE> imgTortArray;
imgTortArray.push_back(imgTort);
obstacleImgs.push_back(imgTortArray);
IMAGE imgLion;
vector<IMAGE> imgLionArray;
for (int i = 0; i < 6; i++) {
sprintf(name, "res/p%d.png", i + 1);
loadimage(&imgLion, name);
imgLionArray.push_back(imgLion);
}
obstacleImgs.push_back(imgLionArray);
// 初始化障碍物池
for (int i = 0; i < OBSTACLE_COUNT; i++) {
obstacles[i].exist = false;
}
// 加载下蹲素材
loadimage(&imgHeroDown[0], "res/d1.png");
loadimage(&imgHeroDown[1], "res/d2.png");
heroDown = false;
// 加载“柱子”障碍物
IMAGE imgH;
vector<IMAGE> imgHookArray;
for (int i = 0; i < 4; i++) {
sprintf_s(name, sizeof(name), "res/h%d.png", i + 1); //帧图片不够,补帧
loadimage(&imgH, name, 63, 260, true);
imgHookArray.push_back(imgH);
obstacleImgs.push_back(imgHookArray);
imgHookArray.pop_back();
}
heroBlood = 100;
// 预加载音效
preLoadSound("res/hit.mp3");
}
main : updateBloodBar();
判断游戏结束 添加背景音乐 添加初始界面
用屁股想 是初始化函数中
mciSendString("play res/bg.mp3", 0, 0, 0);
if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
heroBlood -= obstacles[i].power;
printf("血量剩余 %d\n", heroBlood);
playSound("res/hit.mp3");
obstacles[i].hited = true;
}
void checkOver() {
if (heroBlood <= 0) {
loadimage(0, "res/over.png");
FlushBatchDraw();
mciSendString("stop res/bg.mp3", 0, 0, 0);
system("pause");
// 暂停之后,充币复活,或者直接开始下一局
heroBlood = 100;
mciSendString("play res/bg.mp3", 0, 0, 0);
}
}
int main(void) {
int timer = 0;
init();
// 显示初始画面
loadimage(0, "res/over.png");
system("pause");
while (1) {
keyEvent();
timer += getDelay();//10
if (timer > 20) {
timer = 0;
update = true;
}
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
updateHero();
updateEnemy();
updateBloodBar();
EndBatchDraw();
moveBg();
heroupdown();
createObstacleData();
checkHit();
checkOver();
}
}
return 0;
}
优化死亡BUG
int lastObsIndex; //last obstacle index
void createObstacle() {
srand((unsigned)time(NULL));
int i;
for (i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist == false) {
break;
}
}
if (i >= OBSTACLE_COUNT) {
return;
}
obstacles[i].exist = true;
obstacles[i].imgIndex = 0;
//obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);
obstacles[i].type = (obstacle_type)(rand() % 3);
obstacles[i].x = WIN_WIDTH;
obstacles[i].y = 345 + 5 - obstacleImgs[obstacles[i].type][0].getheight();
if (lastObsIndex >= HOOK1 && lastObsIndex <= HOOK4 &&
obstacles[i].type == LION &&
obstacles[lastObsIndex].x > (WIN_WIDTH - 500)) {
obstacles[i].type = TORTOISE;
}
lastObsIndex = i;
if (obstacles[i].type == HOOK1) {
obstacles[i].type = (obstacle_type)((int)(obstacles[i].type) + rand() % 4);
}
if (obstacles[i].type == TORTOISE) {
obstacles[i].speed = 0;
obstacles[i].power = 5; //自己修改
}
else if (obstacles[i].type == LION) {
obstacles[i].speed = 4;
obstacles[i].power = 20;
}
else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
obstacles[i].speed = 0;
obstacles[i].power = 20;
obstacles[i].y = 0;
}
}
跨越障碍后计算得分
int score; //分数
lastObsIndex = -1;
score = 0;
void checkScore() {
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist &&
obstacles[i].passed == false &&
obstacles[i].x + obstacleImgs[obstacles[i].type][0].getwidth() < heroX) {
score++;
obstacles[i].passed = true;
printf("score: %d\n", score);
}
}
}
typedef struct obstacle {
obstacle_type type; //障碍物的类型
int imgIndex; //当前显示的图片的序号
int x, y; //障碍物的坐标
int speed;
int power; //杀伤力
bool exist;
bool hited;
bool passed;
}obstacle_t;
int main(void) {
int timer = 0;
init();
// 显示初始画面
loadimage(0, "res/over.png");
system("pause");
while (1) {
keyEvent();
timer += getDelay();//10
if (timer > 20) {
timer = 0;
update = true;
}
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
updateHero();
updateEnemy();
updateBloodBar();
EndBatchDraw();
moveBg();
heroupdown();
createObstacleData();
checkHit();
checkOver();
checkScore();
}
}
return 0;
}
void updateScore() {
// 50 => "50" '5' '5'-'0' == 5
char str[8];
sprintf(str, "%d", score);
int x = 20;
int y = 25;
for (int i = 0; str[i]; i++) {
int sz = str[i] - '0';
putimagePNG(x, y, &imgSZ[sz]);
x += imgSZ[sz].getwidth() + 5;
}
}
updateBloodBar();
updateScore();
EndBatchDraw();
checkOver();
checkScore();
判断游戏胜利
写main函数中的位置 这里不再赘述
#define WIN_SCORE 100
void checkWin() {
if (score >= WIN_SCORE) {
FlushBatchDraw();
mciSendString("play res/win.mp3", 0, 0, 0);
Sleep(2000);
loadimage(0, "res/win.png");
FlushBatchDraw();
mciSendString("stop res/bg.mp3", 0, 0, 0);
system("pause");
heroBlood = 100;
score = 0;
mciSendString("play res/bg.mp3 repeat", 0, 0, 0);
}
}
源代码
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <vector>
#include <time.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#define WIN_SCORE 100
#define WIN_WIDTH 1012
#define WIN_HEIGHT 396
#define OBSTACLE_COUNT 10
using namespace std;
IMAGE imgHeros[12];
IMAGE imgBgs[3];
IMAGE imgHeroDown[2];
int bgX[3];
int bgSpeed[3] = { 1, 2, 4 };
int heroX;
int heroY;
int heroIndex;
bool heroJump;
int jumpHeightMax;
int heroJumpOff;
bool update;
bool heroDown;
int heroBlood;
int score;
int lastObsIndex;
typedef enum {
TORTOISE, //乌龟 0
LION, //狮子 1
HOOK1, //勾子
HOOK2,
HOOK3,
HOOK4,
OBSTACLE_TYPE_COUNT ,
} obstacle_type;
vector<vector<IMAGE>>obstacleImgs; //存放所有障碍物的各个图片
typedef struct obstacle {
obstacle_type type; //障碍物的类型
int imgIndex; //当前显示的图片的序号
int x, y; //障碍物的坐标
int speed;
int power; //杀伤力
bool exist;
bool hited;
bool passed;
}obstacle_t;
obstacle_t obstacles[OBSTACLE_COUNT];
void preLoadSound(const char* name);
void drawBloodBar(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent);
void init();
void moveBg();
void jump();
void heroupdown();
int getDelay();
void keyEvent();
void updateBg();
void updateEnemy();
void jump(bool herJump);
bool rectIntersect(int a1X, int a1Y, int a2X, int a2Y,
int b1X, int b1Y, int b2X, int b2Y);
void updateEnemy();
void updateBloodBar();
void createObstacleData();
void createObstacle();
void putimagePNG2(int x, int y, IMAGE* picture);
void putimagePNG2(int x, int y, int winWidth, IMAGE* picture);
void putimagePNG(int picture_x, int picture_y, IMAGE* picture);
void HeroIndex();
void playSound(const char* name);
void preLoadSound(const char* name) {
char cmd[512];
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);
mciSendString(cmd, 0, 0, 0);
}
void drawBloodBar(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent) {
LINESTYLE lineStyle;
getlinestyle(&lineStyle);
int lineColor = getlinecolor();
int fileColor = getfillcolor();
if (percent < 0) {
percent = 0;
}
setlinecolor(BLUE);
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);
setfillcolor(emptyColor);
fillrectangle(x, y, x + width, y + height);
setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);
setfillcolor(fillColor);
setlinecolor(fillColor);
if (percent > 0) {
fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);
}
setlinecolor(lineColor);
setfillcolor(fillColor);
setlinestyle(&lineStyle);
}
bool rectIntersect(int x01, int y01, int x02, int y02,
int x11, int y11, int x12, int y12)
{
int zx = abs(x01 + x02 - x11 - x12);
int x = abs(x01 - x02) + abs(x11 - x12);
int zy = abs(y01 + y02 - y11 - y12);
int y = abs(y01 - y02) + abs(y11 - y12);
return (zx <= x && zy <= y);
}
void playSound(const char* name) {
static int index = 1;
char cmd[512];
if (index == 1) {
sprintf_s(cmd, sizeof(cmd), "play %s-1", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "close %s-2", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);
mciSendString(cmd, 0, 0, 0);
index++;
}
else if (index == 2) {
sprintf_s(cmd, sizeof(cmd), "play %s-2", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "close %s-1", name);
mciSendString(cmd, 0, 0, 0);
sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);
mciSendString(cmd, 0, 0, 0);
index = 1;
}
}
void putimagePNG(int picture_x, int picture_y, IMAGE* picture) //x为载入图片的X坐标,y为Y坐标
{
DWORD* dst = GetImageBuffer(); // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
DWORD* draw = GetImageBuffer();
DWORD* src = GetImageBuffer(picture); //获取picture的显存指针
int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带
int picture_height = picture->getheight(); //获取picture的高度,EASYX自带
int graphWidth = getwidth(); //获取绘图区的宽度,EASYX自带
int graphHeight = getheight(); //获取绘图区的高度,EASYX自带
int dstX = 0; //在显存里像素的角标
// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
for (int iy = 0; iy < picture_height; iy++)
{
for (int ix = 0; ix < picture_width; ix++)
{
int srcX = ix + iy * picture_width; //在显存里像素的角标
int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
int sg = ((src[srcX] & 0xff00) >> 8); //G
int sb = src[srcX] & 0xff; //B
if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
{
dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标
int dr = ((dst[dstX] & 0xff0000) >> 16);
int dg = ((dst[dstX] & 0xff00) >> 8);
int db = dst[dstX] & 0xff;
draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr
| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg
| (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db
}
}
}
}
// 适用于 y <0 以及x<0的任何情况
void putimagePNG2(int x, int y, IMAGE* picture) {
IMAGE imgTmp;
if (y < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, -y,
picture->getwidth(), picture->getheight() + y);
SetWorkingImage();
y = 0;
picture = &imgTmp;
}
if (x < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());
SetWorkingImage();
x = 0;
picture = &imgTmp;
}
putimagePNG(x, y, picture);
}
// 适用于 y <0 以及y>0的任何情况
void putimagePNG2(int x, int y, int winWidth, IMAGE* picture) {
IMAGE imgTmp;
if (y < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, -y,
picture->getwidth(), picture->getheight() + y);
SetWorkingImage();
y = 0;
picture = &imgTmp;
}
if (x < 0) {
SetWorkingImage(picture);
getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());
SetWorkingImage();
x = 0;
picture = &imgTmp;
}
else if (x >= winWidth) {
return;
}
else if (x > winWidth - picture->getwidth()) {
SetWorkingImage(picture);
getimage(&imgTmp, 0, 0, winWidth - x, picture->getheight());
SetWorkingImage();
picture = &imgTmp;
}
putimagePNG(x, y, picture);
}
void jump() {
heroJump = true;
update = true;
}
void down() {
update = true;
heroDown = true;
heroIndex = 0;
}
void heroupdown()
{
// 实现跳跃
if (heroJump) {
if (heroY < jumpHeightMax) {
heroJumpOff = 4;
}
heroY += heroJumpOff;
if (heroY > 345 - imgHeros[0].getheight()) {
heroJump = false;
heroJumpOff = -4;
}
}
else if (heroDown) {
static int count = 0;
int delays[2] = { 8, 30 };
count++;
if (count >= delays[heroIndex]) {
count = 0;
heroIndex++;
if (heroIndex >= 2) {
heroIndex = 0;
heroDown = false;
}
}
}
else { //不跳跃
heroIndex = (heroIndex + 1) % 12;
}
}
void updateBloodBar() {
drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}
void moveBg() {
for (int i = 0; i < 3; i++) {
bgX[i] -= bgSpeed[i];
if (bgX[i] < -WIN_WIDTH) {
bgX[i] = 0;
}
}
}
void createObstacleData() {
static int frameCount = 0;
static int enemyFre = 50;
frameCount++;
if (frameCount > enemyFre) {
frameCount = 0;
enemyFre = 50 + rand() % 50; // 50..99
createObstacle();
}
// 更新所有障碍物的坐标
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
obstacles[i].x -= obstacles[i].speed + bgSpeed[2];
if (obstacles[i].x < -obstacleImgs[obstacles[i].type][0].getwidth() * 2) {
obstacles[i].exist = false;
}
int len = obstacleImgs[obstacles[i].type].size();
obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
}
}
}
void checkHit()
{
for (int i = 0; i < OBSTACLE_COUNT; i++)
{
if (obstacles[i].exist && obstacles[i].hited == false)
{
int a1x, a1y, a2x, a2y;
int off = 20;
if (!heroDown)//非下蹲 奔跑 跳跃
{
a1x = heroX + off;
a1y = heroY + off;
a2x = heroX + imgHeros[heroIndex].getwidth() - off;
a2y = heroY + imgHeros[heroIndex].getheight();
}
else { //下蹲状态
a1x = heroX + off;
a1y = 345 - imgHeroDown[heroIndex].getheight();
a2x = heroX + imgHeroDown[heroIndex].getwidth() - off;
a2y = 345;
}
IMAGE img = obstacleImgs[obstacles[i].type][obstacles[i].imgIndex];
int b1x = obstacles[i].x + off;
int b1y = obstacles[i].y + off;
int b2x = obstacles[i].x + img.getwidth() - off;
int b2y = obstacles[i].y + img.getheight() - 10;
if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
heroBlood -= obstacles[i].power;
printf("血量剩余 %d\n", heroBlood);
playSound("res/hit.mp3");
obstacles[i].hited = true;
}
}
}
}
void checkOver() {
if (heroBlood <= 0) {
loadimage(0, "res/over.png");
FlushBatchDraw();
mciSendString("stop res/bg.mp3", 0, 0, 0);
system("pause");
// 暂停之后,充币复活,或者直接开始下一局
heroBlood = 100;
mciSendString("play res/bg.mp3", 0, 0, 0);
}
}
void createObstacle() {
srand((unsigned)time(NULL));
int i;
for (i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist == false) {
break;
}
}
if (i >= OBSTACLE_COUNT) {
return;
}
obstacles[i].exist = true;
obstacles[i].imgIndex = 0;
//obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);
obstacles[i].type = (obstacle_type)(rand() % 3);
obstacles[i].x = WIN_WIDTH;
obstacles[i].y = 345 + 5 - obstacleImgs[obstacles[i].type][0].getheight();
if (lastObsIndex >= HOOK1 && lastObsIndex <= HOOK4 &&
obstacles[i].type == LION &&
obstacles[lastObsIndex].x > (WIN_WIDTH - 500)) {
obstacles[i].type = TORTOISE;
}
lastObsIndex = i;
if (obstacles[i].type == HOOK1) {
obstacles[i].type = (obstacle_type)((int)(obstacles[i].type) + rand() % 4);
}
if (obstacles[i].type == TORTOISE) {
obstacles[i].speed = 0;
obstacles[i].power = 5; //自己修改
}
else if (obstacles[i].type == LION) {
obstacles[i].speed = 4;
obstacles[i].power = 20;
}
else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
obstacles[i].speed = 0;
obstacles[i].power = 20;
obstacles[i].y = 0;
}
}
//渲染游戏背景
void updateBg()
{
putimagePNG2(bgX[0], 0, &imgBgs[0]);
putimagePNG2(bgX[1], 119, &imgBgs[1]);
putimagePNG2(bgX[2], 330, &imgBgs[2]);
}
//
处理用户按键的输入
//void keyEvent() {
// char ch;
//
// if (_kbhit()) { //如果有按键按下,_kbhit()返回 true
// ch = _getch(); // _getch()不需要按下回车即可直接读取
// if (ch == ' ') {
// jump();
// }
// }
//}
// 处理用户按键的输入
void keyEvent() {
char ch;
if (_kbhit()) { //如果有按键按下,_kbhit()返回 true
ch = _getch(); // _getch()不需要按下回车即可直接读取
if (ch == ' ') {
jump();
}
else if (ch == 's') {
down();
}
}
}
void jump(bool heroJump)
{
// 实现跳跃
if (heroJump) {
if (heroY < jumpHeightMax) {
heroJumpOff = 4;
}
heroY += heroJumpOff;
if (heroY > 345 - imgHeros[0].getheight()) {
heroJump = false;
heroJumpOff = -4;
}
}
else { //不跳跃
heroIndex = (heroIndex + 1) % 12;
}
update = true;
}
void updateEnemy() {
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
putimagePNG2(obstacles[i].x, obstacles[i].y, WIN_WIDTH,
&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
}
}
}
// 游戏的初始化
void init() {
// 创建游戏窗口
initgraph(WIN_WIDTH, WIN_HEIGHT);
// 加载背景资源
char name[64];
for (int i = 0; i < 3; i++) {
// "res/bg001.png" "res/bg002.png" "res/bg003.png"
sprintf(name, "res/bg%03d.png", i + 1);
loadimage(&imgBgs[i], name);
bgX[i] = 0;
}
// 加载Hero奔跑的图片帧素材
for (int i = 0; i < 12; i++) {
// "res/hero1.png" ... "res/hero12.png"
sprintf(name, "res/hero%d.png", i + 1);
loadimage(&imgHeros[i], name);
}
// 设置玩家的初始位置
heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;
heroY = 345 - imgHeros[0].getheight();
heroIndex = 0;
heroJump = false;
jumpHeightMax = 345 - imgHeros[0].getheight() - 120;
heroJumpOff = -4;
update = true;
IMAGE imgTort;
loadimage(&imgTort, "res/t1.png");
vector<IMAGE> imgTortArray;
imgTortArray.push_back(imgTort);
obstacleImgs.push_back(imgTortArray);
IMAGE imgLion;
vector<IMAGE> imgLionArray;
for (int i = 0; i < 6; i++) {
sprintf(name, "res/p%d.png", i + 1);
loadimage(&imgLion, name);
imgLionArray.push_back(imgLion);
}
obstacleImgs.push_back(imgLionArray);
// 初始化障碍物池
for (int i = 0; i < OBSTACLE_COUNT; i++) {
obstacles[i].exist = false;
}
// 加载下蹲素材
loadimage(&imgHeroDown[0], "res/d1.png");
loadimage(&imgHeroDown[1], "res/d2.png");
heroDown = false;
// 加载“柱子”障碍物
IMAGE imgH;
vector<IMAGE> imgHookArray;
for (int i = 0; i < 4; i++) {
sprintf_s(name, sizeof(name), "res/h%d.png", i + 1); //帧图片不够,补帧
loadimage(&imgH, name, 63, 260, true);
imgHookArray.push_back(imgH);
obstacleImgs.push_back(imgHookArray);
imgHookArray.pop_back();
}
heroBlood = 100;
// 预加载音效
preLoadSound("res/hit.mp3");
lastObsIndex = -1;
score = 0;
}
void checkScore() {
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist &&
obstacles[i].passed == false &&
obstacles[i].x + obstacleImgs[obstacles[i].type][0].getwidth() < heroX) {
score++;
obstacles[i].passed = true;
printf("score: %d\n", score);
}
}
}
void updateHero() {
if (!heroDown) {
putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
}
else {
int y = 345 - imgHeroDown[heroIndex].getheight();
putimagePNG2(heroX, y, &imgHeroDown[heroIndex]);
}
}
void HeroIndex()
{
heroIndex = (heroIndex + 1) % 12;
}
void checkWin() {
if (score >= WIN_SCORE) {
FlushBatchDraw();
mciSendString("play res/win.mp3", 0, 0, 0);
Sleep(2000);
loadimage(0, "res/win.png");
FlushBatchDraw();
mciSendString("stop res/bg.mp3", 0, 0, 0);
system("pause");
heroBlood = 100;
score = 0;
mciSendString("play res/bg.mp3 repeat", 0, 0, 0);
}
}
int getDelay() {
static unsigned long long lastTime = 0;
unsigned long long currentTime = GetTickCount();
if (lastTime == 0) {
lastTime = currentTime;
return 0;
}
else {
int ret = currentTime - lastTime;
lastTime = currentTime;
return ret;
}
}
int main(void) {
int timer = 0;
init();
// 显示初始画面
loadimage(0, "res/over.png");
system("pause");
while (1) {
keyEvent();
timer += getDelay();//10
if (timer > 20) {
timer = 0;
update = true;
}
if (update)
{
update = false;
BeginBatchDraw();
updateBg();
updateHero();
updateEnemy();
updateBloodBar();
checkWin();
EndBatchDraw();
moveBg();
heroupdown();
createObstacleData();
checkHit();
checkOver();
checkScore();
}
}
return 0;
}