基于C++的简单游戏开发——小恐龙跳跃游戏课程设计

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_mixer.h>

#define Width_Window 900
#define Height_Window 350
#define MinInterval_Half 100
#define mFPS 40
#define V 9
#define Tan 2

SDL_Window* Window = NULL;
SDL_Renderer* Renderer = NULL;
SDL_Event MainEvent;
Mix_Music* Bgm;
TTF_Font* Score_Font = NULL;
TTF_Font* Gameover_Font = NULL;
SDL_Color Score_Color = { 0,0,0,0 };
SDL_Color Gameover_Color = { 20,20,230,255 };

//Bird
SDL_Surface* Birds_Surface = NULL;
SDL_Texture* Birds_Texture = NULL;
SDL_Surface* Blinking_Surface = NULL;
SDL_Texture* Blinking_Texture = NULL;
SDL_Surface* Cloud_Surface = NULL;
SDL_Texture* Cloud_Texture = NULL;
SDL_Surface* Crouching_Surface = NULL;
SDL_Texture* Crouching_Texture = NULL;
SDL_Surface* Dino_menu_Surface = NULL;
SDL_Texture* Dino_menu_Texture = NULL;
SDL_Surface* Hit_Surface = NULL;
SDL_Texture* Hit_Texture = NULL;
SDL_Surface* Restart_Surface = NULL;
SDL_Texture* Restart_Texture = NULL;
SDL_Surface* Road_Surface = NULL;
SDL_Texture* Road_Texture = NULL;
SDL_Surface* Running_Surface = NULL;
SDL_Texture* Running_Texture = NULL;
SDL_Surface* Sun_Surface = NULL;
SDL_Texture* Sun_Texture = NULL;
SDL_Surface* Life_Surface[5];
SDL_Texture* Life_Texture[5];
SDL_Surface* Obstacle_Surface[14];
SDL_Texture* Obstacle_Texture[14];
SDL_Surface* Score_Surface = NULL;
SDL_Texture* Score_Texture = NULL;
SDL_Surface* HI_Surface = NULL;
SDL_Texture* HI_Texture = NULL;
SDL_Surface* Gameover_Surface = NULL;
SDL_Texture* Gameover_Texture = NULL;

SDL_Rect Dino_menu_Rect;
SDL_Rect Road_Rect[2];
SDL_Rect Cloud_Rect[4];
SDL_Rect Sun_Rect;
SDL_Rect Life_Rect;
SDL_Rect TheDINO_Rect[2];
SDL_Rect running_rect[2];
SDL_Rect crouching_rect[2];
SDL_Rect Obstacles_Rect[14];
SDL_Rect Birds_Rect[2];
SDL_Rect birds_rect[2];
SDL_Rect Hit_Rect;
SDL_Rect Restart_Rect;
SDL_Rect Score_Rect;
SDL_Rect HI_Rect;
SDL_Rect Gameover_Rect;

clock_t FDurTime;

bool jump;
bool down;
bool crouch;
bool collision;
bool detect[3];
int j;
int life;
unsigned long score_m;
unsigned long highestscore = 0;
unsigned int r;
unsigned long r_bird[3];
double std;
double rate;
char Score[7];
char HI[10] = "HI ";
struct use
{
	int Obstacle_i;
	int space;
	bool detect;
	SDL_Rect Rect[2];
}Obstacle_Use[3];

void Load();
void PrepareAll();
void QUIT();
void Jump();//First Jump (to start)
void Play();
void Set();
void CD();//Collision Detection
void RenderDino();
void RenderObstacle();
void RenderBackground();
void RenderScore(unsigned long score);
void ControlFPS(clock_t FStartTime);

#undef main
int main(int argc, char* argv[])
{
	// 准备所有内容
	PrepareAll();

	// 设置渲染器颜色
	SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 0);
	// 清除渲染器
	SDL_RenderClear(Renderer);
	// 渲染菜单纹理
	SDL_RenderCopy(Renderer, Dino_menu_Texture, NULL, &Dino_menu_Rect);
	// 渲染渲染器
	SDL_RenderPresent(Renderer);
	
	// 设置背景音乐音量
	Mix_VolumeMusic(5);
	// 淡入背景音乐
	Mix_FadeInMusic(Bgm, -1, 10000);

	// 循环监听事件
	while (SDL_WaitEvent(&MainEvent))
	{
		// 根据事件类型进行不同的操作
		switch (MainEvent.type)
		{
		// 如果接收到退出事件
		case SDL_QUIT:
			// 退出程序
			QUIT();
			break;
		
		// 如果接收到按键按下事件
		case SDL_KEYDOWN:

			// 根据按键类型进行不同的操作
			switch (MainEvent.key.keysym.sym)
			{
			// 如果按下Esc键
			case SDLK_ESCAPE:
				// 退出程序
				QUIT();
				break;

			// 如果按下回车键
			case SDLK_RETURN:
			// 如果按下空格键
			case SDLK_SPACE:
				// 清除渲染器
				SDL_RenderClear(Renderer);
				// 渲染小恐龙纹理
				SDL_RenderCopy(Renderer, Blinking_Texture, NULL, TheDINO_Rect);
				// 渲染道路纹理
				SDL_RenderCopy(Renderer, Road_Texture, NULL, Road_Rect);
				// 跳跃
				Jump();
				// 播放游戏bgm
				Play();
				// 退出程序
				QUIT();
				break;

			default:
				break;
			}
			break;

		default:
			break;
		}
	}
	return 0;
}

void Load()
{
	// 加载字体
	Score_Font = TTF_OpenFont("fonts/JOKERMAN.TTF", 32);
	Gameover_Font = TTF_OpenFont("fonts/CHILLER.TTF", 90);

	// 加载图片
	Blinking_Surface = IMG_Load("images/Blinking.png");
	Birds_Surface = IMG_Load("images/Birds.png");
	Cloud_Surface = IMG_Load("images/Cloud.png");
	Crouching_Surface = IMG_Load("images/Crouching.png");
	Dino_menu_Surface = IMG_Load("images/Dino_menu.png");
	Hit_Surface = IMG_Load("images/Hit.png");
	Restart_Surface = IMG_Load("images/Restart.png");
	Road_Surface = IMG_Load("images/Road.png");
	Running_Surface = IMG_Load("images/Running.png");
	Sun_Surface = IMG_Load("images/Sun.png");

	// 加载生命值图片
	Life_Surface[0] = IMG_Load("images/Life_0.png");
	Life_Surface[1] = IMG_Load("images/Life_1.png");
	Life_Surface[2] = IMG_Load("images/Life_2.png");
	Life_Surface[3] = IMG_Load("images/Life_3.png");
	Life_Surface[4] = IMG_Load("images/Life_4.png");

	// 加载障碍物图片
	Obstacle_Surface[0] = IMG_Load("images/Obstacle_a.png");
	Obstacle_Surface[1] = IMG_Load("images/Obstacle_b.png");
	Obstacle_Surface[2] = IMG_Load("images/Obstacle_c.png");
	Obstacle_Surface[3] = IMG_Load("images/Obstacle_d.png");
	Obstacle_Surface[4] = IMG_Load("images/Obstacle_e.png");
	Obstacle_Surface[5] = IMG_Load("images/Obstacle_f.png");
	Obstacle_Surface[6] = IMG_Load("images/Obstacle_g.png");
	Obstacle_Surface[7] = IMG_Load("images/Obstacle_h.png");
	Obstacle_Surface[8] = IMG_Load("images/Obstacle_i.png");
	Obstacle_Surface[9] = IMG_Load("images/Obstacle_j.png");
	Obstacle_Surface[10] = IMG_Load("images/Obstacle_k.png");
	Obstacle_Surface[11] = IMG_Load("images/Obstacle_l.png");
	Obstacle_Surface[12] = IMG_Load("images/Obstacle_m.png");
	Obstacle_Surface[13] = IMG_Load("images/Obstacle_n.png");

	// 加载背景音乐
	Bgm = Mix_LoadMUS("audio/BGM.mp3");
}

void PrepareAll()
{
	//Initialize the game
	SDL_Init(SDL_INIT_EVERYTHING);
	//Stop any text input
	SDL_StopTextInput();
	//Initialize the font library
	TTF_Init();
	//Initialize the audio mixer
	Mix_Init(MIX_INIT_MP3);
	//Create the window
	Window = SDL_CreateWindow("MY DINO", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Width_Window, Height_Window, SDL_WINDOW_SHOWN);
	//Create the renderer
	Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
	//Open the audio mixer
	Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 2048);

	//Surface
	Load();
	Gameover_Surface = TTF_RenderUTF8_Blended(Gameover_Font, "G A M E  O V E R", Gameover_Color);
	
	//Creat Texture
	Blinking_Texture = SDL_CreateTextureFromSurface(Renderer, Blinking_Surface);
	Birds_Texture = SDL_CreateTextureFromSurface(Renderer, Birds_Surface);
	Cloud_Texture = SDL_CreateTextureFromSurface(Renderer, Cloud_Surface);
	Crouching_Texture = SDL_CreateTextureFromSurface(Renderer, Crouching_Surface);
	Dino_menu_Texture = SDL_CreateTextureFromSurface(Renderer, Dino_menu_Surface);
	Hit_Texture = SDL_CreateTextureFromSurface(Renderer, Hit_Surface);
	Restart_Texture = SDL_CreateTextureFromSurface(Renderer, Restart_Surface);
	Road_Texture = SDL_CreateTextureFromSurface(Renderer, Road_Surface);
	Running_Texture = SDL_CreateTextureFromSurface(Renderer, Running_Surface);
	Sun_Texture = SDL_CreateTextureFromSurface(Renderer, Sun_Surface);
	for (int i = 0; i < 5; i++)
	{
		Life_Texture[i] = SDL_CreateTextureFromSurface(Renderer, Life_Surface[i]);
	}
	for (int i = 0; i < 14; i++)
	{
		Obstacle_Texture[i] = SDL_CreateTextureFromSurface(Renderer, Obstacle_Surface[i]);
	}
	Gameover_Texture = SDL_CreateTextureFromSurface(Renderer, Gameover_Surface);

	//Determine Rect

	Dino_menu_Rect = (SDL_Rect){ 50,Height_Window - 120,Dino_menu_Surface->w,Dino_menu_Surface->h };

	TheDINO_Rect[0] = (SDL_Rect){ Dino_menu_Rect.x + 4,Dino_menu_Rect.y,Blinking_Surface->w,Blinking_Surface->h };
	TheDINO_Rect[1] = (SDL_Rect){ Dino_menu_Rect.x + 4, Dino_menu_Rect.y + 34,Crouching_Surface->w,Crouching_Surface->h / 2 };

	// 定义道路矩形
	Road_Rect[0] = (SDL_Rect){ 0,Dino_menu_Rect.y + Dino_menu_Rect.h - 24,Road_Surface->w,Road_Surface->h };
	Road_Rect[1] = (SDL_Rect){ Road_Surface->w,Dino_menu_Rect.y + Dino_menu_Rect.h - 24,Road_Surface->w,Road_Surface->h };
	// 定义云朵矩形
	Cloud_Rect[0] = (SDL_Rect){ 0.11 * Width_Window,0.29 * Height_Window,Cloud_Surface->w,Cloud_Surface->h };
	Cloud_Rect[1] = (SDL_Rect){ 0.36 * Width_Window,0.23 * Height_Window,Cloud_Surface->w,Cloud_Surface->h };
	Cloud_Rect[2] = (SDL_Rect){ 0.61 * Width_Window,0.37 * Height_Window,Cloud_Surface->w,Cloud_Surface->h };
	Cloud_Rect[3] = (SDL_Rect){ 0.89 * Width_Window,0.21 * Height_Window,Cloud_Surface->w,Cloud_Surface->h };
	// 定义太阳矩形
	Sun_Rect = (SDL_Rect){ 200,40,100,100 };
	// 定义生命矩形
	Life_Rect = (SDL_Rect){ 214,54,72,72 };
	
	for (int i = 0; i < 2; i++)
	{
		running_rect[i] = (SDL_Rect){ 0,Running_Surface->h / 2 * i,Running_Surface->w ,Running_Surface->h / 2 };
		crouching_rect[i] = (SDL_Rect){ 0,Crouching_Surface->h / 2 * i,Crouching_Surface->w,Crouching_Surface->h / 2 };
	}

	Birds_Rect[0] = (SDL_Rect){ 0,Height_Window - 160,84,60 };
	//定义一个矩形,用于表示鸟的头部
	Birds_Rect[1] = (SDL_Rect){ 0,Height_Window - 172,84,52 };
	//定义一个矩形,用于表示鸟的翅膀
	birds_rect[0] = (SDL_Rect){ 0,12,84,60 };
	//定义一个矩形,用于表示鸟的翅膀
	birds_rect[1] = (SDL_Rect){ 0,72,84,52 };

	for (int i = 0; i < 14; i++)
	{
		Obstacles_Rect[i] = (SDL_Rect){ 0,Road_Rect->y - Obstacle_Surface[i]->h + 22,Obstacle_Surface[i]->w,Obstacle_Surface[i]->h };
	}

	Gameover_Rect = (SDL_Rect){ (Width_Window - Gameover_Surface->w) / 2,Height_Window / 4,Gameover_Surface->w,Gameover_Surface->h };

	Restart_Rect = (SDL_Rect){ (Width_Window - Restart_Surface->w) / 2,Gameover_Rect.y + Gameover_Surface->h + 5,Restart_Surface->w,Restart_Surface->h };
}

void QUIT()
{
	//释放所有的表面
	SDL_FreeSurface(Birds_Surface);//释放鸟的表面
	SDL_FreeSurface(Blinking_Surface);//释放眨眼动画的表面
	SDL_FreeSurface(Cloud_Surface);//释放云朵的表面
	SDL_FreeSurface(Crouching_Surface);//释放蹲下的表面
	SDL_FreeSurface(Dino_menu_Surface);//释放恐龙菜单的表面
	SDL_FreeSurface(Hit_Surface);//释放碰撞效果的表面
	SDL_FreeSurface(Restart_Surface);//释放重新开始的表面
	SDL_FreeSurface(Road_Surface);//释放道路的表面
	SDL_FreeSurface(Running_Surface);//释放奔跑的表面
	SDL_FreeSurface(HI_Surface);//释放最高分的表面
	SDL_FreeSurface(Gameover_Surface);//释放游戏结束的表面
	//释放所有的纹理
	SDL_DestroyTexture(Birds_Texture);//释放鸟的纹理
	SDL_DestroyTexture(Blinking_Texture);//释放眨眼动画的纹理
	SDL_DestroyTexture(Cloud_Texture);//释放云朵的纹理
	SDL_DestroyTexture(Crouching_Texture);//释放蹲下的纹理
	SDL_DestroyTexture(Dino_menu_Texture);//释放恐龙菜单的纹理
	SDL_DestroyTexture(Hit_Texture);//释放碰撞效果的纹理
	SDL_DestroyTexture(Restart_Texture);//释放重新开始的纹理
	SDL_DestroyTexture(Road_Texture);//释放道路的纹理
	SDL_DestroyTexture(Running_Texture);//释放奔跑的纹理
	SDL_DestroyTexture(HI_Texture);//释放最高分的纹理
	SDL_DestroyTexture(Gameover_Texture);//释放游戏结束的纹理
	//释放生命值纹理数组
	for (int i = 0; i < 5; i++)
	{
		SDL_DestroyTexture(Life_Texture[i]);
	}
	//释放障碍物纹理数组
	for (int i = 0; i < 14; i++)
	{
		SDL_DestroyTexture(Obstacle_Texture[i]);
	}
    //关闭游戏结束字体和得分字体
	TTF_CloseFont(Gameover_Font);
	TTF_CloseFont(Score_Font);
	
	Mix_FreeMusic(Bgm);//释放背景音乐
	//销毁窗口和渲染器
	SDL_DestroyWindow(Window);
	SDL_DestroyRenderer(Renderer);

	SDL_Quit();//退出SDL
}

void Jump()
{
	double t = TheDINO_Rect[0].y;	//记录初始纵坐标
	for (int i = 0; i < 2 * V * Tan + 1; i++)	//进行跳跃动画
	{
		t += (i - V * Tan) * 2 * Height_Window / (double)(3 * V * Tan * V * Tan);
		TheDINO_Rect[0].y = t;
		SDL_RenderClear(Renderer);	//清除渲染器
		//渲染眨眼动画和道路
		SDL_RenderCopy(Renderer, Blinking_Texture, NULL, TheDINO_Rect);
		SDL_RenderCopy(Renderer, Road_Texture, NULL, Road_Rect);
		SDL_RenderPresent(Renderer);	//刷新渲染器
		SDL_Delay(1000 / mFPS);	//延时
	}
	TheDINO_Rect->y = Dino_menu_Rect.y;	//重置恐龙纵坐标为菜单时的位置(解决由std取整引起的bug)

void Set()
{
	srand((unsigned int)time(NULL));	//设置随机数种子
	//初始化各种变量和标志
	jump = false;
	down = false;
	crouch = false;
	collision = false;
	j = 0;
	life = 4;
	rate = 1.0;
	score_m = 0;
	r = 4111;
	for (int i = 0; i < 3; i++)		//初始化小鸟的速度数组
	{
		r_bird[i] = 2147516415;
	}
	//初始化恐龙的纵坐标和std
	TheDINO_Rect[0].y = Dino_menu_Rect.y;
	std = Dino_menu_Rect.y;
	for (int i = 0; i < 3; i++)		//初始化障碍物使用结构体数组
	{
		Obstacle_Use[i] = (struct use){ -1,Width_Window / 2 * (i + 2),false };
	}
	//计算最高分的每一位数字
	unsigned long temp = highestscore % 1000000;
	for (int i = 5; i >= 0; i--)
	{
		Score[i] = '0';
		HI[i + 3] = temp % 10 + '0';
		temp /= 10;
	}
	//渲染最高分的表面和纹理
	HI_Surface = TTF_RenderUTF8_Blended(Score_Font, HI, Score_Color);
	HI_Texture = SDL_CreateTextureFromSurface(Renderer, HI_Surface);
	HI_Rect = (SDL_Rect){ Width_Window * 0.8 - HI_Surface->w - 20,20,HI_Surface->w,HI_Surface->h };
}

void Play()
{
	Set();	//初始化游戏
	while (true)	//游戏主循环
	{
		clock_t FStartTime = clock();	//记录游戏开始时间
		if (SDL_PollEvent(&MainEvent))	//处理事件
		{
			switch (MainEvent.type)
			{
			case SDL_QUIT:
				return;
				break;

			case SDL_KEYDOWN:
				switch (MainEvent.key.keysym.sym)
				{
				case SDLK_ESCAPE:
					return;
					break;

				case SDLK_DOWN:
					down = true;
					break;

				case SDLK_UP:
				case SDLK_SPACE:
					jump = true;
					break;

				default:
					break;
				}
				break;

			case SDL_KEYUP:
				switch (MainEvent.key.keysym.sym)
				{
				case SDLK_DOWN:
					down = false;
					crouch = false;
					break;

				default:
					break;
				}
				break;

			default:
				break;
			}
		}
		//更新分数和选择速度
		score_m++;
		//Select Speed
		if (score_m >= 2500)
		{
			rate = 1.25;
		}
		else if (score_m >= 10000)
		{
			rate = 1.5;
		}

		SDL_RenderClear(Renderer);	//清除渲染器

		//渲染背景、障碍物、恐龙和分数
		RenderBackground();
		RenderObstacle();
		RenderDino();
		RenderScore(score_m / 5 % 1000000);

		SDL_RenderPresent(Renderer);	//刷新渲染器

		CD();

		if (life < 0)	//判断游戏是否结束
		{
			Mix_PauseMusic();	//暂停背景音乐

			//渲染游戏结束画面
			if (crouch)
			{
				Hit_Rect = (SDL_Rect){ TheDINO_Rect[1].x + TheDINO_Rect[1].w - Hit_Surface->w,TheDINO_Rect[1].y + 2,Hit_Surface->w,Hit_Surface->h };
				SDL_RenderCopy(Renderer, Hit_Texture, NULL, &Hit_Rect);
			}
			else
			{
				Hit_Rect = (SDL_Rect){ TheDINO_Rect[0].x + TheDINO_Rect[0].w - Hit_Surface->w,TheDINO_Rect[0].y,Hit_Surface->w,Hit_Surface->h };
				SDL_RenderCopy(Renderer, Hit_Texture, NULL, &Hit_Rect);
			}
			SDL_RenderCopy(Renderer, Gameover_Texture, NULL, &Gameover_Rect);
			SDL_RenderCopy(Renderer, Restart_Texture, NULL, &Restart_Rect);
			SDL_RenderPresent(Renderer);

			while (SDL_WaitEvent(&MainEvent))	//等待玩家重新开始或退出
			{
				bool Replay = false;
				switch (MainEvent.type)
				{
				case SDL_QUIT:
					return;
					break;

				case SDL_KEYDOWN:
					switch (MainEvent.key.keysym.sym)
					{
					case SDLK_ESCAPE:
						return;
						break;

					case SDLK_RETURN:
						Replay = true;
						break;

					default:
						break;
					}
					break;

				case SDL_MOUSEBUTTONDOWN:
					if (MainEvent.button.x > Restart_Rect.x && MainEvent.button.y > Restart_Rect.y && MainEvent.button.x < Restart_Rect.x + Restart_Rect.w && MainEvent.button.y < Restart_Rect.y + Restart_Rect.h)
					{
						Replay = true;
					}
					break;

				default:
					break;
				}
				//处理重新开始或退出
				if (Replay)
				{
					Mix_ResumeMusic();	//恢复背景音乐

					if (score_m / 5 > highestscore)	//更新最高分
					{
						highestscore = score_m / 5;
					}
					//释放最高分表面和纹理
					SDL_FreeSurface(HI_Surface);
					SDL_DestroyTexture(HI_Texture);
					//重新开始游戏
					Set();
					break;
				}
			}
			SDL_Delay(100);	//延时
		}
		else
		{
			ControlFPS(FStartTime);
		}
	}
}

void RenderObstacle()
{
	//随机选择障碍物
	if (Obstacle_Use[0].space == Width_Window || Obstacle_Use[1].space == Width_Window || Obstacle_Use[2].space == Width_Window)
	{
		for (int i = 0; i < 3; i++)
		{
			if (Obstacle_Use[i].space == Width_Window)
			{
				Obstacle_Use[i].detect = false;
				int t = score_m > 500 ? 16 : 5;
				Obstacle_Use[i].Obstacle_i = rand() % t;

				if (Obstacle_Use[i].Obstacle_i >= 14)//如果是鸟作为障碍物
				{
					//随机生成鸟的横坐标
					int pre_x = Width_Window + MinInterval_Half + rand() % (Width_Window / 2 - MinInterval_Half * 2 - Birds_Rect[i].w);
					for (int h = 0; h < 2; h++)		//将鸟的坐标赋值给障碍物使用结构体
					{
						Obstacle_Use[i].Rect[h] = Birds_Rect[h];
						Obstacle_Use[i].Rect[h].x = pre_x;
					}
					break;
				}
				//随机生成障碍物的横坐标
				Obstacle_Use[i].Rect[0] = Obstacles_Rect[Obstacle_Use[i].Obstacle_i];
				Obstacle_Use[i].Rect->x = Width_Window + MinInterval_Half + rand() % (Width_Window / 2 - MinInterval_Half * 2 - Obstacle_Use[i].Rect->w);

				break;
			}
		}
	}

	//Render Obstacle
	for (int i = 0; i < 3; i++)
	{
		Obstacle_Use[i].space -= V;

		if (Obstacle_Use[i].space < -Width_Window / 2) //回到起点以被继续使用
		{
			Obstacle_Use[i].space = Width_Window;
		}

		if (Obstacle_Use[i].Obstacle_i > -1)
		{
			if (Obstacle_Use[i].Obstacle_i >= 14)
			{
				r_bird[i] >>= 1;
				if (r_bird[i] == 0)
				{
					r_bird[i] = 2147516415;
				}
				Obstacle_Use[i].Rect[0].x -= V;
				Obstacle_Use[i].Rect[1].x -= V;
				SDL_RenderCopy(Renderer, Birds_Texture, birds_rect + r_bird[i] % 2, Obstacle_Use[i].Rect + r_bird[i] % 2);
			}
			else
			{
				Obstacle_Use[i].Rect->x -= V;
				SDL_RenderCopy(Renderer, Obstacle_Texture[Obstacle_Use[i].Obstacle_i], NULL, Obstacle_Use[i].Rect);
			}
		}
	}
}

void RenderDino()
{
// 判断down键是否被按下
	if (down)
	{
 // 如果jump键被按下并且恐龙的y坐标不等于游戏界面的y坐标,说明恐龙正在快速下降
		if (jump && TheDINO_Rect[0].y != Dino_menu_Rect.y)//Rapidly Drop
		{
// 根据速度V和角度Tan计算出j的值,并根据j的值更新恐龙的y坐标
			j = j <= V * Tan ? 2 * V * Tan + 1 - j : j;
			for (int i = 0; i < 3 && jump; i++)
			{
// 根据计算出的j值和窗口的高度,更新恐龙的y坐标
				std += (j - V * Tan) * 2 * Height_Window / (double)(3 * V * Tan * V * Tan);
				TheDINO_Rect[0].y = std;
				j++;
 // 当j的值达到上限时,重置j的值,并将恐龙的y坐标重置为游戏界面的y坐标,同时结束跳跃状态
				if (j == 2 * V * Tan + 1)
				{
					j = 0;
					TheDINO_Rect->y = Dino_menu_Rect.y;//Reset TheDINO_Rect[0].y(bug来自于std取整)
					jump = false;
				}
			}
// 将恐龙模型复制到渲染器中
			SDL_RenderCopy(Renderer, Blinking_Texture, NULL, TheDINO_Rect);
		}
// 如果jump键没有被按下,说明恐龙处于蹲伏状态
		else//Crouch
		{
// 将恐龙模型从蹲伏状态切换到站立状态,并将r的值右移一位,如果r的值达到上限,则重置r的值
			SDL_RenderCopy(Renderer, Crouching_Texture, crouching_rect + r % 2, TheDINO_Rect + 1);
			r >>= 1;
			if (r == 16)
			{
				r = 4111;
			}
			jump = false;
			crouch = true;
		}
	}
// 如果jump键没有被按下,说明恐龙处于奔跑状态
	else if (jump)
	{
// 根据计算出的j值和窗口的高度,更新恐龙的y坐标,并根据j的值进行跳跃动画的循环播放
		std += (j - V * Tan) * 2 * Height_Window / (double)(3 * V * Tan * V * Tan);
		TheDINO_Rect[0].y = std;
		j++;
		SDL_RenderCopy(Renderer, Blinking_Texture, NULL, TheDINO_Rect);
 // 当j的值达到上限时,重置j的值,并将恐龙的y坐标重置为游戏界面的y坐标,结束跳跃状态
		if (j == 2 * V * Tan + 1)
		{
			j = 0;
			TheDINO_Rect->y = Dino_menu_Rect.y;//Reset TheDINO_Rect[0].y(bug来自于std取整)
			jump = false;
		}
	}
// 如果以上条件都不满足,说明恐龙处于奔跑状态,将恐龙模型切换到奔跑动画并更新r的值,如果r的值达到上限,则重置r的值
	else//Running
	{
		SDL_RenderCopy(Renderer, Running_Texture, running_rect + r % 2, TheDINO_Rect);
		r >>= 1;
		if (r == 16)
		{
			r = 4111;
		}
	}
}// 函数结束注释标记
// 定义一个函数 RenderScore,接受一个无符号长整型参数 score
void RenderScore(unsigned long score)
{
// 从 5 开始循环,直到 score 为 0 或者 i 小于等于 0
	for (int i = 5; i >= 0 && score != 0; i--)
	{
// 将 score 的个位数转换为字符,并赋值给 Score[i]
		Score[i] = score % 10 + '0';
// 将 score 除以 10,以便下一次循环处理下一位
		score /= 10;
	}
// 使用 TTF_RenderUTF8_Blended 方法将计分板文字渲染为 Surface 对象
	Score_Surface = TTF_RenderUTF8_Blended(Score_Font, Score, Score_Color);
// 将 Surface 对象转换为 Texture 对象,以便在屏幕上显示
	Score_Texture = SDL_CreateTextureFromSurface(Renderer, Score_Surface);
// 定义一个矩形对象 Score_Rect,用于存储计分板的显示位置和大小
	Score_Rect = (SDL_Rect){ Width_Window - Score_Surface->w - 20,20,Score_Surface->w,Score_Surface->h };
 // 将 Texture 对象复制到屏幕上,显示计分板
	SDL_RenderCopy(Renderer, Score_Texture, NULL, &Score_Rect);
 // 复制 HI_Texture 到屏幕上,显示另一个部分
	SDL_RenderCopy(Renderer, HI_Texture, NULL, &HI_Rect);
 // 释放 Surface 对象
	SDL_FreeSurface(Score_Surface);
 // 销毁 Texture 对象,释放资源
	SDL_DestroyTexture(Score_Texture);
}
// 定义一个函数 RenderBackground,用于渲染背景

void RenderBackground()
{
// 遍历两次,对于每一轮循环,调整 Road_Rect 的 x 坐标,并判断是否超出边界
	for (int i = 0; i < 2; i++)
	{
		Road_Rect[i].x -= V;// Road_Rect 的 x 坐标向左移动 V 的距离
		if (Road_Rect[i].x < -Road_Surface->w)// 如果 Road_Rect 的 x 坐标小于 -Road_Surface 的宽度
		{
			Road_Rect[i].x += Road_Surface->w * 2;// 则将其 x 坐标向右移动 Road_Surface 宽度的两倍
		}
 // 将 Road_Texture 复制到 Road_Rect 指定的位置
		SDL_RenderCopy(Renderer, Road_Texture, NULL, Road_Rect + i);
	}
// 将 Sun_Texture 复制到指定的位置,用于显示太阳
	SDL_RenderCopy(Renderer, Sun_Texture, NULL, &Sun_Rect);
 // 再次遍历四次,对于每一轮循环,调整 Cloud_Rect 的 x 坐标,并判断是否超出边界
	for (int i = 0; i < 4; i++)
	{
		Cloud_Rect[i].x -= V / 4;// Cloud_Rect 的 x 坐标向左移动 V/4 的距离
		if (Cloud_Rect[i].x < -Cloud_Surface->w) // 如果 Cloud_Rect 的 x 坐标小于 -Cloud_Surface 的宽度
		{
			Cloud_Rect[i].x = Width_Window;// 则将其 x 坐标设置为窗口的宽度
		}
// 将 Cloud_Texture 复制到 Cloud_Rect 指定的位置
		SDL_RenderCopy(Renderer, Cloud_Texture, NULL, Cloud_Rect + i);
	}
 // 将 Life_Texture[life] 复制到指定的位置,用于显示生命体
	SDL_RenderCopy(Renderer, Life_Texture[life], NULL, &Life_Rect);
}
// 定义一个函数 CD,用于处理碰撞检测
void CD()
{
// 遍历三次,对于每一轮循环,判断是否发生了碰撞
	for (int i = 0; i < 3; i++)
	{
// 如果障碍物的检测标志为 false,并且障碍物的x坐标小于DINO的x坐标加上DINO的宽度加上速度V,并且障碍物的x坐标加上障碍物的宽度大于等于20
		if (Obstacle_Use[i].detect == false && Obstacle_Use[i].Rect->x < TheDINO_Rect->x + TheDINO_Rect[1].w + V && Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w >= 20)
		{// 如果处于蹲姿状态
			if (crouch)
			{
// 如果障碍物的 i 小于 14,并且障碍物的 x 坐标在 DINO 的 x 坐标的前后范围内
				if (Obstacle_Use[i].Obstacle_i < 14 && Obstacle_Use[i].Rect->x >= TheDINO_Rect[1].x && Obstacle_Use[i].Rect->x <= TheDINO_Rect[1].x + TheDINO_Rect[1].w)
				{
 // 设置 collision 为 true,表示发生了碰撞
					collision = true;
				}
			}
 // 如果不是处于蹲姿状态
			else
			{
 // 如果障碍物的 x 坐标在 DINO 的 x 坐标的前后范围内
				if (Obstacle_Use[i].Rect->x >= TheDINO_Rect[0].x && Obstacle_Use[i].Rect->x <= TheDINO_Rect[0].x + TheDINO_Rect[0].w)
				{
// 如果障碍物的y坐标在DINO的y坐标的正上方或下方(即障碍物的y坐标小于等于DINO的y坐标减去障碍物的h,并且大于等于DINO的y坐标)
					if (Obstacle_Use[i].Rect->y <= TheDINO_Rect[0].y + TheDINO_Rect[0].h && Obstacle_Use[i].Rect->y >= TheDINO_Rect[0].y)
// 如果障碍物的i小于等于4,则判断障碍物的y坐标减去DINO的y坐标是否小于一个特定的值
					{
						if (Obstacle_Use[i].Obstacle_i < 4)
						{
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < (91 - (Obstacle_Use[i].Rect->x - TheDINO_Rect[0].x)) * 1.5)
							{
 // 设置 collision 为 true,表示发生了碰撞
								collision = true;
							}
						}
						else if (Obstacle_Use[i].Obstacle_i < 7)
						{
 // 如果障碍物的 i 小于等于 7,则判断障碍物的 y 坐标减去 DINO 的 y 坐标是否小于另一个特定的值
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < (86 - (Obstacle_Use[i].Rect->x - TheDINO_Rect[0].x)) * 1.5)
							{
// 设置 collision 为 true,表示发生了碰撞
								collision = true;
							}
						}
						else
						{
 // 如果障碍物的 i 大于等于 7,则判断障碍物的 y 坐标减去 DINO 的 y 坐标是否小于另一个特定的值
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < (96 - (Obstacle_Use[i].Rect->x - TheDINO_Rect[0].x)) * 1.5)
							{
								collision = true;
// 设置 collision 为 true,表示发生了碰撞
							}
						}
					}
					else if (Obstacle_Use[i].Rect->y >= TheDINO_Rect[0].y - Obstacle_Use[i].Rect->h && Obstacle_Use[i].Rect->y <= TheDINO_Rect[0].y)
 // 如果障碍物的y坐标在DINO 的y坐标的上方和下方范围内
					{
// 如果障碍物的i小于14

						if (Obstacle_Use[i].Obstacle_i < 14)
						{
// 碰撞发生,将collision设置为true
							collision = true;
						}
 // 如果障碍物的x坐标小于等于DINO的x坐标减去30(表示DINO正在远离障碍物)
						else if (Obstacle_Use[i].Rect->x <= TheDINO_Rect[0].x + TheDINO_Rect[0].w - 30)
						{
// 碰撞发生,将collision设置为true
							collision = true;
						}
					}
				}
				else if (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w >= TheDINO_Rect[0].x && Obstacle_Use[i].Rect->x < TheDINO_Rect[0].x)
				{
// 如果障碍物的y坐标在DINO的y坐标范围之内
					if (Obstacle_Use[i].Rect->y <= TheDINO_Rect[0].y + TheDINO_Rect[0].h && Obstacle_Use[i].Rect->y >= TheDINO_Rect[0].y)
					{
 // 如果障碍物的i小于3
						if (Obstacle_Use[i].Obstacle_i < 3)
						{
// 如果障碍物的y坐标减去DINO的y坐标小于另一个值
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < 2 * (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w - TheDINO_Rect[0].x) + 47)
							{
// 碰撞发生,将collision设置为true
								collision = true;
							}
						}
// 如果障碍物的i小于7
						else if (Obstacle_Use[i].Obstacle_i < 7)
						{
// 如果障碍物的y坐标减去DINO的y坐标小于另一个值
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < 2 * (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w - TheDINO_Rect[0].x) + 34)
							{
// 碰撞发生,将collision设置为true
								collision = true;
							}
						}
						else
						{
// 如果障碍物的y坐标减去DINO的y坐标小于另一个值
							if (Obstacle_Use[i].Rect->y - TheDINO_Rect[0].y < 2 * (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w - TheDINO_Rect[0].x) + 54)
							{
// 碰撞发生,将collision设置为true
								collision = true;
							}
						}
					}
// 如果障碍物的y坐标在另一个约束条件下
					else if (Obstacle_Use[i].Rect->y >= TheDINO_Rect[0].y - Obstacle_Use[i].Rect->h && Obstacle_Use[i].Rect->y <= TheDINO_Rect[0].y)
					{
 // 如果Obstacle_Use[i].Obstacle_i大于等于14
						if (Obstacle_Use[i].Obstacle_i >= 14)
						{
// 如果r_bird[i]是奇数
							if (r_bird[i] % 2 == 1)
							{
								if (Obstacle_Use[i].Rect[1].y + Obstacle_Use[i].Rect[1].h - TheDINO_Rect[0].y > 30 || Obstacle_Use[i].Rect[1].x + Obstacle_Use[i].Rect[1].w - TheDINO_Rect[0].x > 40)
								{
// 设置collision为true,表示发生了碰撞
									collision = true;
								}
							}
// 如果r_bird[i]是偶数
							else
							{
								if (Obstacle_Use[i].Rect->y + Obstacle_Use[i].Rect->h - TheDINO_Rect[0].y >= -0.75 * (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w - TheDINO_Rect[0].x - 80))
								{
									if (Obstacle_Use[i].Rect[1].y + Obstacle_Use[i].Rect[1].h - TheDINO_Rect[0].y > 30 || Obstacle_Use[i].Rect[1].x + Obstacle_Use[i].Rect[1].w - TheDINO_Rect[0].x > 40)
									{
										collision = true;
									}
								}
							}
						}
						else
						{
// 如果Obstacle_Use[i]的矩形顶部的距离减去TheDINO的矩形顶部的距离大于-0.75乘以(矩形宽度减去矩形高度的一半)再减去80,并且满足其他条件,则设置collision为true
							if (Obstacle_Use[i].Rect->y + Obstacle_Use[i].Rect->h - TheDINO_Rect[0].y >= -0.75 * (Obstacle_Use[i].Rect->x + Obstacle_Use[i].Rect->w - TheDINO_Rect[0].x - 40))
							{
								collision = true;
							}
						}
					}
				}
			}
			if (collision)
			{
 // 如果存在碰撞,那么将collision设置为false,表示碰撞已经被处理
				collision = false;
// 将障碍物的检测标志设置为true,表示障碍物已经被检测到
				Obstacle_Use[i].detect = true;
// 生命值减一,表示受到伤害或者消耗等
				life--;
			}
			break;
		}
	}
}
// 函数名: ControlFPS, 接收一个参数FStartTime,表示上次开始执行此函数时的时钟时间
void ControlFPS(clock_t FStartTime)
{
 // 计算从上次函数调用到现在经过的时间,用clock()函数获取当前时间,减去FStartTime
	FDurTime = clock() - FStartTime;
 // 检查经过的时间是否小于等于一秒除以当前的FPS(每秒帧数)和速率
	if (FDurTime <= 1000 / mFPS / rate) // mFPS是设定的目标帧率,rate是一个设置好的帧数倍数,以降低FPS。
	{
// 如果经过的时间小于等于所需时间,即游戏的帧率仍然很高(每秒超过设定值),那么使用SDL_Delay函数暂停一段时间,使得帧率降低到设定的FPS
		SDL_Delay(1000 / mFPS / rate - FDurTime); // SDL_Delay函数用于暂停一段时间,参数为需要暂停的毫秒数。这里暂停的时间是剩余的超过一秒的时间减去当前经过的时间。
    }
	}
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值