C++游戏开发《天天酷跑》

 总代码:其中包含了自制的头文件和cpp文件tool用来实现特定的功能

/*	
* 天天酷跑开发日志
* 1.创建项目
* 2.导入素材
* 3.游戏界面
*  实际的开发流程
*  选择图形库或基于其他引擎
*  本项目基于EASY X
* 1)创建游戏窗口
* 2)设计游戏背景
*  a.3重背景不同的速度同时移动
*  b.循环滚动背景的实现
* 3)实现游戏背景
*   a.加载背景资源
*   b.渲染
* 4.实现玩家奔跑
* 5.实现玩家跳跃
* 6.实现随机小乌龟
* 7.创建障碍物结构体数据类型
* 8.使用障碍物结构体后的重新初始化
* 9.封装后多个障碍物的显示
* 10.实现下蹲
* 11.实现悬挂障碍物
* 
* 
*/
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include"tools.h"
#include<vector>
using namespace std;
#define SCREEN_LONG   1012
#define SCREEN_WIDTH  396
#define OBSTACLE_COUNT 10
#define WIN_SCORE 10
IMAGE images[3];
int bgX[3];
int bgSpeed[3] = { 1,3,19 };
IMAGE heroImg[12];
int heroIndex;
int heroX;
int heroY;
bool herojump;     //表示玩家正在跳跃
bool heroDown;     //玩家下蹲
int jumpMaxHeight;
int heroJumpOff;
int updata;        //表示是否需要马上刷新画面
int heroBlood;
int score;
typedef enum {
	TORTOISE,
	LION,
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
}obstacle_type;

//int data[3][5]
vector<vector<IMAGE>> obstacleImgs;     //特殊的二维数组



typedef struct obstacle {
	int type;          //障碍物类型
	int imgIndex;                //当前显示的图片的序号
	int x, y;                    //障碍物的坐标
	int speed;
	int power;                   //杀伤力
	bool exist;  //障碍物是否存在
	bool hited;                  //表示是否已经发生碰撞 
	bool passed;                 //表示是否已经被通过
}obstacle_t;
obstacle_t obstacles[OBSTACLE_COUNT];
IMAGE imgDOWN[2];
IMAGE imgSZ[10];
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);
	char name[64];
	for (int i = 0; i < 3; i++) {
		
		sprintf_s(name, "res/bg%03d.png", i + 1);
		loadimage(&images[i], name);
		bgX[i] = 0;
	}
	//加载玩家奔跑素材
	for (int i = 0; i < 12; i++) {
		char name[64];
		sprintf_s(name, "res/hero%d.png", i + 1);
		loadimage(&heroImg[i], name);
	}

	//设置玩家初始位置
	heroIndex = 0;
	heroX = SCREEN_LONG / 2 - heroImg[heroIndex].getwidth();
	heroY = 345 - heroImg[heroIndex].getheight();
	herojump = false;
	jumpMaxHeight= 345 - heroImg[heroIndex].getheight()-120;
	heroJumpOff = -12;
	updata = true;
	//wuguiExist = false;
	//wuguiIndex = 0;
	//wuguiY = 345 - wuguiImg[wuguiIndex].getheight()-50;
	加载小乌龟
	//for (int i = 0; i < 7; i++) {
	//	char name[64];
	//	sprintf_s(name,"res/t%d.png", i + 1);
	//	loadimage(&wuguiImg[i], name);
	//}
	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_s(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(&imgDOWN[0], "res/d1.png");
	loadimage(&imgDOWN[1], "res/d2.png");
	heroDown = false;

	IMAGE imgH;
		
	for (int i = 0; i < 4; i++) {
		vector<IMAGE> imgHookArray;
		sprintf(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name, 63, 260, true);
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);
	}

	heroBlood = 100;
	//预加载音效
	preLoadSound("res/hit.mp3");
	mciSendString("play res/bg.mp3", 0, 0, 0);
	score = 0;

	for (int i = 0; i < 10; i++) {
		sprintf_s(name, "res/sz/%d.png", i);
		loadimage(&imgSZ[i], name);
	}
}

void updateBg() {
	putimagePNG2(bgX[0], 0, &images[0]);
	putimagePNG2(bgX[1], 119, &images[1]);
	putimagePNG2(bgX[2], 330, &images[2]);

}
void jump() {
	herojump = true;
	updata = true;
} 
void down() {
	updata = true;
	heroDown = true;
	heroIndex = 0;
}
// 处理用户按键
void keyEvent() {
	if (_kbhit()) {
		char ch = _getch();
		if (ch == ' ') {
			jump();
		}
		if (ch=='a') {
			down();
		}
	}
}
void updataEnemy() {
	//渲染小乌龟
	/*if (wuguiExist) {
		putimagePNG2(wuguiX, wuguiY, SCREEN_LONG,&wuguiImg[wuguiIndex]);
	}*/
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			putimagePNG2(obstacles[i].x, obstacles[i].y, SCREEN_LONG,
				&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}
void creatObstacle() {
	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].hited = false;
	obstacles[i].passed = false;
	obstacles[i].type =(obstacle_type)( rand() % 3);
	if (obstacles[i].type == HOOK1) {
		obstacles[i].type += rand() % 4;
	}
	obstacles[i].x = SCREEN_LONG;
	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;
	}
	else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
}
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 = 30;
			if (!heroDown) {
				a1x = heroX + off;
				a1y = heroY + off;
				a2x = heroX + heroImg[heroIndex].getwidth() - off;
				a2y = heroY + heroImg[heroIndex].getheight();
			}
			else {
				a1x = heroX + off;
				a1y = 345 - imgDOWN[heroIndex].getheight();
				a2x = heroX + imgDOWN[heroIndex].getwidth() - off;
				a2y = 345;
			}
			int b1x = obstacles[i].x + off;
			int b1y = obstacles[i].y + off;
			int b2x = obstacles[i].x + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getwidth()-off;
			int b2y = obstacles[i].y + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getheight() - 10;
			if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
				heroBlood -= obstacles[i].power;
				cout << "剩下" << heroBlood<<" 血量"<<endl;
				playSound("res/hit.mp3");
				obstacles[i].hited = true;
			}
		}
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bgSpeed[i];
		if(bgX[i]<= -SCREEN_LONG){
			bgX[i] = 0;
		}
	}
	//实现跳跃
	if (herojump == true) {
		
		if (heroY < jumpMaxHeight) {
			heroJumpOff = 12;
		}
		heroY += heroJumpOff;
		if (heroY > 345 - heroImg[heroIndex].getheight()) {
			herojump = false;
			heroJumpOff = -12;
		}
	}
	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;
	}
	//创建小乌龟
	static int frameCount = 0;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre =25 + rand() % 25;
		creatObstacle();
		
	}
	//更新障碍物的坐标
	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()-100) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}
	checkHit();
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDOWN[heroIndex].getheight();
		putimagePNG2(heroX,y,&imgDOWN[heroIndex]);
	}
}
void updataBloodBar() {
	drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}
void cheakOver() {
	if (heroBlood <= 0) {
		loadimage(0, "res/over.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3",0,0,0);
		system("pause");
		system("cls");
		cout << "按q退出,按其他键继续游戏";
		char ch = _getch();
		if (ch == 'q') {
			exit(-1);
		}
		heroBlood = 100;
		score = 0;
		mciSendString("play res/bg.mp3", 0, 0, 0);

	}
}
void cheakScore() {
	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&&obstacles[i].hited==false) {
			score++;
			obstacles[i].passed = true;
			cout << "现在是" << score << "分";
		}
	}
}
void updataScore() {
	char str[8];
	sprintf_s(str, "%d", score);
	int x = 20;
	int y = 25;
	for (int i = 0; i < str[i]; i++) {
		int sz = str[i] - '0';
		putimagePNG(x, y, &imgSZ[sz]);
		x += imgSZ->getwidth() + 5;
	}
}
void cheakWin() {
	if (score >= WIN_SCORE) {
		mciSendString("play res/win.mp3", 0, 0, 0);
		Sleep(1000);
		loadimage(0, "res/win.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3", 0, 0, 0);
		system("pause");
	}
}
int main() {
	init();
	loadimage(0, "res/over.png");
	system("pause");


	int timer = 0;
	while (1) {
		keyEvent();
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;	
		}
		if (updata) {
			updata = false;
			BeginBatchDraw();
			updateBg();
			updataHero();
			updataEnemy();
			updataBloodBar();
			updataScore();
			EndBatchDraw();
			cheakOver();
			cheakScore();
			cheakWin();
			fly();
		}

	}
	
	system("pause");
	return 0;
}

实现效果

 下面来带大家一步步实现。

一.游戏界面开发

#include"tools.h";
#include<iostream>
#include<graphics.h>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,6}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			updata = false;
            BeginBatchDraw();
			updataBg();
            EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

实现效果

可以滚动的背景图片

 要点详解

1.让背景图片滚动起来

扫描二维码关注公众号,回复: 17025934 查看本文章

定义数字bgX[3]用来存放三张图片的X坐标,bg_Speed[3]存放三张图片的速度。

只要让背景图片的X坐标不断的减少,背景图片就会不断的向左移动,所以我们需要写一个循环让背景图片的左边持续的减小,直到减小到和我们显示窗口的长度一样时,将bgX重新赋值为0,这样就可以做到无缝链接。

2.帧等待

定义bool updata判断现在是否需要刷新页面。初始值设为true(刚开始肯定要刷新一下嘛),定义timer用来判断多久刷新一次图片,getDelay是返回距离上一次调用间隔的时间,当时间累加到30ms的时候我们刷新一次图片,当timer>30的时候,updata=true,刷新页面。

二.实现人物奔跑

#include"tools.h";
#include<iostream>
#include<graphics.h>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,6}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();

}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void updataHero() {
	putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	heroIndex = (heroIndex + 1) % 12;
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

实现效果

要点详解

无难点,只需要循环播放人物背景图片即可。

三.实现人物跳跃下蹲

#include"tools.h";
#include<iostream>
#include<graphics.h>
#include<conio.h>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,6}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
bool heroJump;
bool heroDown;
int heroJumpOff;			//人物跳跃速度
int heroJumpMax;			//人物跳跃高度
IMAGE imgDown[2];
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();
	

	
	heroJump = false;
	heroDown = false;
	heroJumpOff = -12;
	heroJumpMax = 345 - heroImg[heroIndex].getheight() - 120;
	//加载下蹲素材
	loadimage(&imgDown[0], "res/d1.png");
	loadimage(&imgDown[1], "res/d2.png");

}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDown[heroIndex].getheight();
		putimagePNG2(heroX, y, &imgDown[heroIndex]);
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	
	//跳跃
	if (heroJump == true) {
		if (heroY < heroJumpMax) {
			heroJumpOff = 12;
		}	
		heroY += heroJumpOff;
		if (heroY >= 345-heroImg[heroIndex].getheight()){
			heroJumpOff = -12;
			heroJump = false;
		}
	}
	else if (heroDown == true) {
		static int count = 0;
		int delay[2] = { 4,10 };
		count++;
		if (count >= delay[heroIndex]) {
			count = 0;
			heroIndex++;
			if (heroIndex >= 2) {
				heroIndex = 0;
				heroDown = false;
			}
		}

	}
	 else {//不跳越不下蹲
		heroIndex = (heroIndex + 1) % 12;
	}


}
void Jump() {
	heroJump = true;
	updata = true;
}
void Down() {
	heroDown = true;
	updata = true;
	heroIndex = 0;
}
void keyEvent() {
	if (_kbhit())
	{
		char ch = _getch();
		if (ch == ' ') {
			Jump();
		}
		if (ch == 'a') {
			Down();
		}

	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			keyEvent();
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

 实现效果

 

 要点详解

跳跃实现机制,我们设定跳跃幅度heroJumpOff和跳跃高度heroJumpMax,当按下跳跃键空格时,如果heroY小于最大高度,heroJumpOff=-12,heroY-12就可以实现向上移动,通过while循环一直跳到最大高度,当heroY小于最大高度时,让heroJumpOff=12实现下降,当下降到一定位置时,让heroJumpOff=-12,heroJump=false,以供下次跳跃使用。

 下蹲实现机制,通过延迟播放两张下蹲图片实现。delay[2]存放的两个数字就是第一张和第二章图片延长的时间。

四.障碍物结构体初始化

#include"tools.h";
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<vector>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,6}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
bool heroJump;
bool heroDown;
int heroJumpOff;			//人物跳跃速度
int heroJumpMax;			//人物跳跃高度
IMAGE imgDown[2];
enum obstacle_type {
	TORTOISE,
	LION,
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
};
struct obstacle_t {
	int type;				//障碍物类型
	int imgIndex;			//障碍物图片序号
	int x, y;				//障碍物坐标
	int speed;				//障碍物速度
	int power;				//障碍物攻击力
	bool exist;				//障碍物当前是否存在
	bool hit;				//障碍物和人物是否发生碰撞
	bool passed;			//障碍物是否被通过
};
obstacle_t obstacles[OBSTACLE_TYPE_COUNT];    //储存障碍物信息的一维数组
vector<vector<IMAGE>> obstacleImgs;			//特殊的二维数组
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();
	

	
	heroJump = false;
	heroDown = false;
	heroJumpOff = -12;
	heroJumpMax = 345 - heroImg[heroIndex].getheight() - 120;
	//加载下蹲素材
	loadimage(&imgDown[0], "res/d1.png");
	loadimage(&imgDown[1], "res/d2.png");

	//加载各种障碍物的信息
	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_s(name, "res/p%d.png", i + 1);
		loadimage(&imgLion, name);
		imgLionArray.push_back(imgLion);
	}
	obstacleImgs.push_back(imgLionArray);

	IMAGE imgH;
	
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgHookArray;
		sprintf_s(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name,63,260,true);
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);
	}
	//初始化障碍物
	for (int i = 0; i < OBSTACLE_TYPE_COUNT; i++) {
		obstacles[i].exist = false;
	}

}
void updataObstacle() {
	for (int i = 0; i < OBSTACLE_TYPE_COUNT; i++) {
		if (obstacles[i].exist) {
			putimagePNG2(obstacles[i].x, obstacles[i].y, SCREEN_LONG,
				&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}
void creatObstacle() {
	int i;
	for (i = 0; i < OBSTACLE_TYPE_COUNT; i++) {
		if (obstacles[i].exist == false) {
			break;
		}
	}
	if (i >= OBSTACLE_TYPE_COUNT) {
		return;
	}
	obstacles[i].exist = true;
	obstacles[i].imgIndex = 0;
	obstacles[i].hit = false;
	obstacles[i].passed = false;
	obstacles[i].type = rand() % 3;
	if (obstacles[i].type == HOOK1) {
		obstacles[i].type += rand() % 4;
	}
	obstacles[i].x = SCREEN_LONG;
	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;
	}
	else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDown[heroIndex].getheight();
		putimagePNG2(heroX, y, &imgDown[heroIndex]);
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	
	//跳跃
	if (heroJump == true) {
		if (heroY < heroJumpMax) {
			heroJumpOff = 12;
		}	
		heroY += heroJumpOff;
		if (heroY >= 345-heroImg[heroIndex].getheight()){
			heroJumpOff = -12;
			heroJump = false;
		}
	}
	else if (heroDown == true) {
		static int count = 0;
		int delay[2] = { 4,30 };
		count++;
		if (count >= delay[heroIndex]) {
			count = 0;
			heroIndex++;
			if (heroIndex >= 2) {
				heroIndex = 0;
				heroDown = false;
			}
		}

	}
	 else {//不跳越不下蹲
		heroIndex = (heroIndex + 1) % 12;
	}

}
void Jump() {
	heroJump = true;
	updata = true;
}
void Down() {
	heroDown = true;
	updata = true;
	heroIndex = 0;
}
void keyEvent() {
	if (_kbhit())
	{
		char ch = _getch();
		if (ch == ' ') {
			Jump();
		}
		if (ch == 'a') {
			Down();
		}

	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			keyEvent();
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			updataObstacle();
			EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

 要点详解

定义枚举类型储存乌龟,狮子,以及四根柱子,定义障碍物结构体,一个结构体数组,一个vector类型的二位数组去储存障碍物的信息,在init函数里分别对乌龟,狮子,四根柱子进行初始化。这样二维数组obstacleImgs分别储存着乌龟图片数组,狮子图片数组以及四根柱子的图片。在updataObstacle中去渲染障碍物,在creatObstacle中去创建障碍物。(注意,HOOK的初始化中,必须多加三个参数,63,260,true去调整图片大小。否则会导致运行异常)

五.障碍物出现。

#include"tools.h";
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<vector>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
#define OBSTACLE_COUNT 10
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,12}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
bool heroJump;
bool heroDown;
int heroJumpOff;			//人物跳跃速度
int heroJumpMax;			//人物跳跃高度
IMAGE imgDown[2];
enum obstacle_type {
	TORTOISE,
	LION,
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
};
struct obstacle_t {
	int type;				//障碍物类型
	int imgIndex;			//障碍物图片序号
	int x, y;				//障碍物坐标
	int speed;				//障碍物速度
	int power;				//障碍物攻击力
	bool exist;				//障碍物当前是否存在
	bool hit;				//障碍物和人物是否发生碰撞
	bool passed;			//障碍物是否被通过
};
obstacle_t obstacles[OBSTACLE_COUNT];    //储存障碍物信息的一维数组
vector<vector<IMAGE>> obstacleImgs;			//特殊的二维数组
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();
	

	
	heroJump = false;
	heroDown = false;
	heroJumpOff = -12;
	heroJumpMax = 345 - heroImg[heroIndex].getheight() - 120;
	//加载下蹲素材
	loadimage(&imgDown[0], "res/d1.png");
	loadimage(&imgDown[1], "res/d2.png");

	//加载各种障碍物的信息
	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_s(name, "res/p%d.png", i + 1);
		loadimage(&imgLion, name);
		imgLionArray.push_back(imgLion);
	}
	obstacleImgs.push_back(imgLionArray);

	IMAGE imgH;
	
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgHookArray;
		sprintf_s(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name,63,260,true);
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);
	}
	//初始化障碍物
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}

}
void updataObstacle() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			putimagePNG2(obstacles[i].x, obstacles[i].y, SCREEN_LONG,
				&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}
void creatObstacle() {
	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].hit = false;
	obstacles[i].passed = false;
	obstacles[i].type = rand() % 3;
	if (obstacles[i].type == HOOK1) {
		obstacles[i].type += rand() % 4;
	}
	obstacles[i].x = SCREEN_LONG;
	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;
	}
	else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDown[heroIndex].getheight();
		putimagePNG2(heroX, y, &imgDown[heroIndex]);
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	
	//跳跃
	if (heroJump == true) {
		if (heroY < heroJumpMax) {
			heroJumpOff = 12;
		}	
		heroY += heroJumpOff;
		if (heroY >= 345-heroImg[heroIndex].getheight()){
			heroJumpOff = -12;
			heroJump = false;
		}
	}
	else if (heroDown == true) {
		static int count = 0;
		int delay[2] = { 4,10 };
		count++;
		if (count >= delay[heroIndex]) {
			count = 0;
			heroIndex++;
			if (heroIndex >= 2) {
				heroIndex = 0;
				heroDown = false;
			}
		}

	}
	 else {//不跳越不下蹲
		heroIndex = (heroIndex + 1) % 12;
	}
	static int frameCount = 0;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre = 25 + rand() % 25;
		creatObstacle();

	}
	//更新障碍物的坐标
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bg_Speed[2];
			if (obstacles[i].x < obstacleImgs[obstacles[i].type][0].getwidth() - 100) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}
}
void Jump() {
	heroJump = true;
	updata = true;
}
void Down() {
	heroDown = true;
	updata = true;
	heroIndex = 0;
}
void keyEvent() {
	if (_kbhit())
	{
		char ch = _getch();
		if (ch == ' ') {
			Jump();
		}
		if (ch == 'a') {
			Down();
		}

	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			keyEvent();
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			updataObstacle();
			EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

实现效果 

要点详解

在我们的fly函数中进行障碍物的显示

static int frameCount = 0;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre = 25 + rand() % 25;
		creatObstacle();

	}

这一段函数是障碍物产生的频率,可以自己调整增加难度。

for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bg_Speed[2];
			if (obstacles[i].x < 0) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}

这一段是更新障碍物的坐标。当障碍物的x坐标<0也就是到达屏幕最左边时,将这个障碍物删除.

六.加载音乐,检验碰撞。

#include"tools.h";
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<vector>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
#define OBSTACLE_COUNT 10
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,12}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
bool heroJump;
bool heroDown;
int heroJumpOff;			//人物跳跃速度
int heroJumpMax;			//人物跳跃高度
IMAGE imgDown[2];
int heroBlood;
enum obstacle_type {
	TORTOISE,
	LION,
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
};
struct obstacle_t {
	int type;				//障碍物类型
	int imgIndex;			//障碍物图片序号
	int x, y;				//障碍物坐标
	int speed;				//障碍物速度
	int power;				//障碍物攻击力
	bool exist;				//障碍物当前是否存在
	bool hit;				//障碍物和人物是否发生碰撞
	bool passed;			//障碍物是否被通过
};
obstacle_t obstacles[OBSTACLE_COUNT];    //储存障碍物信息的一维数组
vector<vector<IMAGE>> obstacleImgs;			//特殊的二维数组
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();
	

	
	heroJump = false;
	heroDown = false;
	heroJumpOff = -12;
	heroJumpMax = 345 - heroImg[heroIndex].getheight() - 120;
	//加载下蹲素材
	loadimage(&imgDown[0], "res/d1.png");
	loadimage(&imgDown[1], "res/d2.png");

	//加载各种障碍物的信息
	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_s(name, "res/p%d.png", i + 1);
		loadimage(&imgLion, name);
		imgLionArray.push_back(imgLion);
	}
	obstacleImgs.push_back(imgLionArray);

	IMAGE imgH;
	
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgHookArray;
		sprintf_s(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name,63,260,true);
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);
	}
	//初始化障碍物
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}
	heroBlood = 100;         //初始化血量
	preLoadSound("res/hit.mp3");   //预加载碰撞音效
	mciSendString("play res/bg.mp3", 0, 0, 0);   //加载背景音乐
}
void updataObstacle() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			putimagePNG2(obstacles[i].x, obstacles[i].y, SCREEN_LONG,
				&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}
void creatObstacle() {
	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].hit = false;
	obstacles[i].passed = false;
	obstacles[i].type = rand() % 3;
	if (obstacles[i].type == HOOK1) {
		obstacles[i].type += rand() % 4;
	}
	obstacles[i].x = SCREEN_LONG;
	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;
	}
	else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void checkHit() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist && obstacles[i].hit == false) {
			int a1x, a1y, a2x, a2y;
			int off = 30;
			if (!heroDown) {
				a1x = heroX + off;
				a1y = heroY + off;
				a2x = heroX + heroImg[heroIndex].getwidth() - off;
				a2y = heroY + heroImg[heroIndex].getheight();
			}
			else {
				a1x = heroX + off;
				a1y = 345 - imgDown[heroIndex].getheight();
				a2x = heroX + imgDown[heroIndex].getwidth() - off;
				a2y = 345;
			}
			int b1x = obstacles[i].x + off;
			int b1y = obstacles[i].y + off;
			int b2x = obstacles[i].x + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getwidth() - off;
			int b2y = obstacles[i].y + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getheight() - 10;
			if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
				heroBlood -= obstacles[i].power;
				cout << "剩下" << heroBlood << " 血量" << endl;
				playSound("res/hit.mp3");
				obstacles[i].hit = true;
			}
		}
	}
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDown[heroIndex].getheight();
		putimagePNG2(heroX, y, &imgDown[heroIndex]);
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	
	//跳跃
	if (heroJump == true) {
		if (heroY < heroJumpMax) {
			heroJumpOff = 12;
		}	
		heroY += heroJumpOff;
		if (heroY >= 345-heroImg[heroIndex].getheight()){
			heroJumpOff = -12;
			heroJump = false;
		}
	}
	else if (heroDown == true) {
		static int count = 0;
		int delay[2] = { 4,10 };
		count++;
		if (count >= delay[heroIndex]) {
			count = 0;
			heroIndex++;
			if (heroIndex >= 2) {
				heroIndex = 0;
				heroDown = false;
			}
		}

	}
	 else {//不跳越不下蹲
		heroIndex = (heroIndex + 1) % 12;
	}
	static int frameCount = 0;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre = 25 + rand() % 25;
		creatObstacle();

	}
	//更新障碍物的坐标
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bg_Speed[2];
			if (obstacles[i].x <0 ) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}
	checkHit();
}

void Jump() {
	heroJump = true;
	updata = true;
}
void Down() {
	heroDown = true;
	updata = true;
	heroIndex = 0;
}
void keyEvent() {
	if (_kbhit())
	{
		char ch = _getch();
		if (ch == ' ') {
			Jump();
		}
		if (ch == 'a') {
			Down();
		}

	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			keyEvent();
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			updataObstacle();
			EndBatchDraw();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

 要点详解

检验碰撞我们采用了别人做好的工具rectIntersect()函数,我们只需要提供四个坐标

 当人物与障碍物的坐标相遇的时候,函数就会检测到碰撞。

七.显示血条分数以及游戏结束条件。

#include"tools.h";
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<vector>
using namespace std;
#define SCREEN_LONG 1012
#define SCREEN_WIDTH 396
#define OBSTACLE_COUNT 10
IMAGE bg_Img[3];			//存放游戏背景图片
int bgX[3];                 //背景图片的X坐标
int bg_Speed[3] = { 1,3,12}; //背景图片滚动的速度
bool updata;				//当前是否需要刷新
IMAGE heroImg[12];			//存放人物背景图片
int heroX;					//人物X坐标
int heroY;					//人物Y坐标
int heroIndex;
bool heroJump;
bool heroDown;
int heroJumpOff;			//人物跳跃速度
int heroJumpMax;			//人物跳跃高度
IMAGE imgDown[2];
int heroBlood;
int score;
IMAGE imgSZ[10];
#define WIN_SCORE 10
enum obstacle_type {
	TORTOISE,
	LION,
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
};
struct obstacle_t {
	int type;				//障碍物类型
	int imgIndex;			//障碍物图片序号
	int x, y;				//障碍物坐标
	int speed;				//障碍物速度
	int power;				//障碍物攻击力
	bool exist;				//障碍物当前是否存在
	bool hit;				//障碍物和人物是否发生碰撞
	bool passed;			//障碍物是否被通过
};
obstacle_t obstacles[OBSTACLE_COUNT];    //储存障碍物信息的一维数组
vector<vector<IMAGE>> obstacleImgs;			//特殊的二维数组
//游戏的初始化
void init() {
	initgraph(SCREEN_LONG, SCREEN_WIDTH);


	char name[64];
	//导入背景图片
	for (int i = 0; i < 3; i++) {
		sprintf_s(name, "res/bg%03d.png",i+1);
		loadimage(&bg_Img[i], name);
	}
	updata = true;
	//导入人物奔跑图片
	for (int i = 0; i < 12; i++) {
		sprintf_s(name, "res/hero%d.png",i+1);
		loadimage(&heroImg[i], name);
	}
	heroIndex = 0;
	heroX = SCREEN_LONG/2 - heroImg[heroIndex].getwidth();
	heroY = 345-heroImg[heroIndex].getheight();
	

	
	heroJump = false;
	heroDown = false;
	heroJumpOff = -12;
	heroJumpMax = 345 - heroImg[heroIndex].getheight() - 120;
	//加载下蹲素材
	loadimage(&imgDown[0], "res/d1.png");
	loadimage(&imgDown[1], "res/d2.png");

	//加载各种障碍物的信息
	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_s(name, "res/p%d.png", i + 1);
		loadimage(&imgLion, name);
		imgLionArray.push_back(imgLion);
	}
	obstacleImgs.push_back(imgLionArray);

	IMAGE imgH;
	
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgHookArray;
		sprintf_s(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name,63,260,true);
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);
	}
	//初始化障碍物
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}
	heroBlood = 100;
	preLoadSound("res/hit.mp3");
	mciSendString("play res/bg.mp3", 0, 0, 0);
	score = 0;
	for (int i = 0; i < 10; i++) {
		sprintf_s(name, "res/sz/%d.png", i);
		loadimage(&imgSZ[i], name);
	}
}
void updataObstacle() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			putimagePNG2(obstacles[i].x, obstacles[i].y, SCREEN_LONG,
				&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}
void creatObstacle() {
	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].hit = false;
	obstacles[i].passed = false;
	obstacles[i].type = rand() % 3;
	if (obstacles[i].type == HOOK1) {
		obstacles[i].type += rand() % 4;
	}
	obstacles[i].x = SCREEN_LONG;
	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;
	}
	else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
}
//渲染背景图片
void updataBg() {
	putimagePNG2(bgX[0], 0, &bg_Img[0]);
	putimagePNG2(bgX[1], 119, &bg_Img[1]);
	putimagePNG2(bgX[2], 330, &bg_Img[2]);
}
void checkHit() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist && obstacles[i].hit == false) {
			int a1x, a1y, a2x, a2y;
			int off = 30;
			if (!heroDown) {
				a1x = heroX + off;
				a1y = heroY + off;
				a2x = heroX + heroImg[heroIndex].getwidth() - off;
				a2y = heroY + heroImg[heroIndex].getheight();
			}
			else {
				a1x = heroX + off;
				a1y = 345 - imgDown[heroIndex].getheight();
				a2x = heroX + imgDown[heroIndex].getwidth() - off;
				a2y = 345;
			}
			int b1x = obstacles[i].x + off;
			int b1y = obstacles[i].y + off;
			int b2x = obstacles[i].x + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getwidth() - off;
			int b2y = obstacles[i].y + obstacleImgs[obstacles[i].type][obstacles[i].imgIndex].getheight() - 10;
			if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
				heroBlood -= obstacles[i].power;
				cout << "剩下" << heroBlood << " 血量" << endl;
				playSound("res/hit.mp3");
				obstacles[i].hit = true;
			}
		}
	}
}
void updataBloodBar() {
	drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}
void updataHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &heroImg[heroIndex]);
	}
	else {
		int y = 345 - imgDown[heroIndex].getheight();
		putimagePNG2(heroX, y, &imgDown[heroIndex]);
	}
}
void fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bg_Speed[i];
		if (bgX[i] < -SCREEN_LONG) {
			bgX[i] = 0;
		}
	}
	
	//跳跃
	if (heroJump == true) {
		if (heroY < heroJumpMax) {
			heroJumpOff = 12;
		}	
		heroY += heroJumpOff;
		if (heroY >= 345-heroImg[heroIndex].getheight()){
			heroJumpOff = -12;
			heroJump = false;
		}
	}
	else if (heroDown == true) {
		static int count = 0;
		int delay[2] = { 4,10 };
		count++;
		if (count >= delay[heroIndex]) {
			count = 0;
			heroIndex++;
			if (heroIndex >= 2) {
				heroIndex = 0;
				heroDown = false;
			}
		}

	}
	 else {//不跳越不下蹲
		heroIndex = (heroIndex + 1) % 12;
	}
	static int frameCount = 0;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre = 25 + rand() % 25;
		creatObstacle();

	}
	//更新障碍物的坐标
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bg_Speed[2];
			if (obstacles[i].x <0 ) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}
	checkHit();
}

void Jump() {
	heroJump = true;
	updata = true;
}
void Down() {
	heroDown = true;
	updata = true;
	heroIndex = 0;
}
void keyEvent() {
	if (_kbhit())
	{
		char ch = _getch();
		if (ch == ' ') {
			Jump();
		}
		if (ch == 'a') {
			Down();
		}

	}
}
void cheakOver() {
	if (heroBlood <= 0) {
		loadimage(0, "res/over.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3", 0, 0, 0);
		system("pause");
		system("cls");
		cout << "按q退出,按其他键继续游戏";
		char ch = _getch();
		if (ch == 'q') {
			exit(-1);
		}
		heroBlood = 100;
		score = 0;
		mciSendString("play res/bg.mp3", 0, 0, 0);

	}
}
void cheakScore() {
	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 && obstacles[i].hit == false) {
			score++;
			obstacles[i].passed = true;
			cout << "现在是" << score << "分";
		}
	}
}
void updataScore() {
	char str[8];
	sprintf_s(str, "%d", score);
	int x = 20;
	int y = 25;
	for (int i = 0; i < str[i]; i++) {
		int sz = str[i] - '0';
		putimagePNG(x, y, &imgSZ[sz]);
		x += imgSZ->getwidth() + 5;
	}
}
void cheakWin() {
	if (score >= WIN_SCORE) {
		mciSendString("play res/win.mp3", 0, 0, 0);
		Sleep(1000);
		loadimage(0, "res/win.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3", 0, 0, 0);
		system("pause");
	}
}
int main() {
	init();
	int timer=0;
	while (1) {	
		timer += getDelay();
		if (timer > 30) {
			timer = 0;
			updata = true;
		}
		if (updata) {
			keyEvent();
			updata = false;
			BeginBatchDraw();
			updataBg();
			updataHero();
			updataObstacle();
			updataBloodBar();
			updataScore();
			EndBatchDraw();
			cheakOver();
			cheakScore();
			cheakWin();
			fly();
		}
		
	}
	
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lxyhhhhhcl/article/details/132148079