超级入门版本天天酷跑(5天成果)

学习了1个多星期的easyx图形库教程后,结合csdn上面飞机大战的相关思路,做了一些坐标题目。本人c语言学了大概有130多天,尝试了一下天天酷跑的小项目,素材图片太过简陋.并且程序终止于添加血条,音效以及按键长按问题(期中考试,应付其他科目)。
目前程序无bug,可以实现人物正常跑路,下蹲,以及与障碍物的碰撞检测。
有注释,可大致解释清楚部分代码用途
没有运用到指针,运用到了部分c++的数组vector代码
程序适合于小白临摹;需要使用c++以及easyx图形库实现。


 

 

​
#define _CRT_SECURE_NO_WARNINGS 1
//天天酷跑开发日志:4.11日程序猿:南林叶良辰
//1:创建项目
//2:导入素材
//3:开发游戏界面
//4:实际的开发流程
//b站老师说,对于初学者,最好的方式是从用户界面入手,也就是菜单什么的
//1:创建游戏窗口
//2:实现游戏背景,因为背景图片首先储存在硬盘,得需要进度条进行准备工作
//2(1):3种背景图,以不同的速度同时移动
//2(2):循环滚动背景的实现 
//3:实现游戏背景
//a.加载背景资源
//b.渲染
//背景知识:游戏窗口坐标
//定位图片素材坐标需要知道左上角坐标
//对于图片素材和窗口都是,所以窗口左上角为原点,向下为y
//4:实现玩家奔跑
//5:实现玩家的跳跃,按空格跳一下
//6:随机小乌龟
//7:障碍物封装用结构体
//8:初始化障碍物结构体
//9:封装多障碍物显示
//10:玩家下蹲
//11:实现柱子障碍物


#include
#include
#include
#include"tools.h"
#include
#include
using namespace std;//使用vector更加方便,是为了声明一个命名空间

#define WIN_WIDTH 1012
#define WIN_HEIGHT 396
#define OBSTACLE_COUNT 10
//背景图片,因为3个用全局变量的数组
IMAGE imgBgs[3];//背景图片
int bgX[3];//背景图片的x坐标
int bgSpeed[3] = { 1,2,4 };
IMAGE imgHeros[12];
int heroX;//玩家的x坐标
int heroY;//玩家的y坐标
int heroIndex;//玩家奔跑的图片的序号
bool heroJump;//表示玩家正在跳跃
int jumpHeightMax;
int heroJumpOff;//跳跃偏移量
int update;//表示马上要刷新画面
IMAGE imgTortoise;//小乌龟
int torToiseX;//乌龟的水平坐标
int torToiseY;//乌龟y坐标
bool torToiseExist;//当前窗口是否有小乌龟
int heroBlood;

typedef enum {
	TORTOISE,//乌龟 默认是0 特殊的整数
	LION,//狮子 1
	HOOK1,
    HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT //6  学到的开发小技巧,用来计数枚举常量的个数



	
} obstacle_type;
//IMAGE obstacleImgs[3][12];//内存消耗
//vector> data;//相当于c语言的二维数组,超纲了可以去cplusplus.com了解用法
vector > obstacleImgs;//存放障碍物图片

//相当于int n;int data[n]变长数组

typedef struct obstacle {
	int type;//障碍物的类型
	int imgIndex;//当前显示图片的序号
	int x, y;//障碍物坐标
	int speed;//速度
	int power;//伤害
	bool exist;//是否存在
	bool hited;//表示是否已经发生碰撞
}obstacle_t;
obstacle_t obstacles[OBSTACLE_COUNT];
IMAGE imgHeroDown[2];
bool heroDown;//表示玩家是否处于下蹲状态

void init()
{
	//创建一个游戏窗口
	initgraph(WIN_WIDTH, WIN_HEIGHT,EW_SHOWCONSOLE); //第三个是打印控制台的
	//窗口有了,下一步是背景导入
	//加载游戏背景资源
	char name[64];
	for (int i = 0; i < 3; i++) {
		//"res/bg001.jpg res/bg002.jpg res/bg003.jpg
		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----12png
		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 = -5;
	update = true;
	//加载小乌龟
	//loadimage(&imgTortoise, "res/t1.png");
	//torToiseExist = false;
	//torToiseY = 350 - imgTortoise.getheight();
	IMAGE imgTort;
	//loadimage(&imgTortoise, "res/t1.png");
	loadimage(&imgTort, "res/t1.png");
	vectorimgTortArray;
	imgTortArray.push_back(imgTort);
	obstacleImgs.push_back(imgTortArray);
	IMAGE imgLion;
	vectorimgLionArray;
	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;
	vectorimgHookArray;
	for (int i = 0; i < 4; i++)
	{
		vectorimgHookArray;//表示一种柱子的数组,存放柱子的形态,但是只有一个
		sprintf(name,"res/h%d.png", i + 1);
		loadimage(&imgH, name,63,260,true);//可以自己美工
		imgHookArray.push_back(imgH);
		obstacleImgs.push_back(imgHookArray);


	}

	//加载4个柱子的图片

	heroBlood = 100;
}
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].hited = false;
	obstacles[i].imgIndex = 0;
	obstacles[i].type = (obstacle_type)(rand() % 3);
	if (obstacles[i].type == HOOK1)
	{
		obstacles[i].type += rand() % 4;
	}
	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;
	}
	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 off = 75;
			int a1x, a1y, a2x, a2y;
			if (!heroDown) {
				a1x = heroX + off;
				a1y = heroX + off;
				a2x = heroX + imgHeros[heroIndex].getwidth() - off;
				a2y = heroY + imgHeros[heroIndex].getheight();

			}
			else {

				a1x = heroX - 40;
				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() - 5;
			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 fly() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bgSpeed[i];
		if (bgX[i] < -WIN_WIDTH)
		{
			bgX[i] = 0;
		}
	}
	//实现跳跃
	if (heroJump) {
		if (heroY < jumpHeightMax) {
			heroJumpOff = 5;
		}
		heroY += heroJumpOff;
		if (heroY > 345 - imgHeros[0].getheight())
		{
			heroJump = false;
			heroJumpOff = -5;
		}
	}
	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 = 50 + rand() % 50;//50-99fps;
		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;
		}
	}
	//碰撞检测(最难部分)
	checkHit();
}



//渲染游戏背景
void updateBg()
{//防止屏幕闪烁,因此一次性打印比较好,用了b站大佬的工具库函数,可以防止y坐标<0;
	putimagePNG2(bgX[0], 0,&imgBgs[0]);
	putimagePNG2(bgX[1], 119, &imgBgs[1]);
	putimagePNG2(bgX[2],330, &imgBgs[2]);


}
//这是easyx图形库
//天天酷跑本程序是基于"easyx图形库的"

//实现跳跃
void jump()
{
	heroJump = true;
	update = true; 
}
void down() {
	update = true;
	heroDown = true;
	heroIndex = 0;
}


//处理用户的键盘输入情况
void keyEvent()
{
	if (_kbhit())
	{
		//kbhit引用conio库,如果有按键输入返回真
		//scanf("%c,&c);如果不用kbhit,这个是会阻塞程序
		//而且按一次需要按一次回车不方便
		char ch;
		ch = _getch();  //getch()不需要敲回车就可以直接读取,读取的是字符
		if (ch == ' ')
		{
			jump();
		}
		else if (ch == 's') {
			down();
		}
	}


	//应该是先判断是否有按键按下去
}
//渲染小乌龟
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]);//第几个障碍物显示第几章图片,太乱了写的
		}
	}



}

void updateHero() {
	if (!heroDown) {
		putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
	}
	else {
		int y = 345 - imgHeroDown[heroIndex].getheight();
			putimagePNG2(heroX, y, &imgHeroDown[heroIndex]);
	}
}
int main(void)
{
	init();//初始化
	int timer = 0;
	//距离上一次调用相隔多久
	while (1)
	{
		
		keyEvent();
		timer += getDelay();
		if (timer > 30) {
			timer = 0;//计数器清零
			update = true;
		
		
		}
		if (update)
		{
			update = false;
			BeginBatchDraw();
			updateBg();
			//putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
			updateHero();
			updateEnemy();
			EndBatchDraw();
			fly();//让他x坐标更改
			//Sleep(30);//帧等待 默认是毫秒,休眠作用但是对空格键有影响,延迟30ms
		}
	}

	system("pause");
	return 0;

}

​

 超级入门版本天天酷跑(5天成果)_第1张图片

 这是试运行的程序图。

以上是部分代码,具体的代码分析我会在期中考试结束后带来一篇详细的博客。
小白代码,大佬勿喷,谢谢。爆肝五天,头发狂掉。

 

你可能感兴趣的:(c#)