#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函数用于暂停一段时间,参数为需要暂停的毫秒数。这里暂停的时间是剩余的超过一秒的时间减去当前经过的时间。
}
}
}
01-20
04-01
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交