初学编程,代码屎山,仅供参考。
主函数中的一些操作可以适当用函数块代替,减少代码复杂度。
在该项目中没有使用渲染器,直接用的BlitSurface。但还是建议大家使用renderer。
参考教程:www.bilibili.com/video/BV1rK411V7eu
游戏演示:www.bilibili.com/video/BV1r84y1s7Gf
试玩版:https://pan.baidu.com/s/1GlOw62K8ZVM8-gtsBCBgHg 提取码:1919
#define _CRT_SECURE_NO_WARNINGS
#define SDL_MAIN_HANDLED
#include <stdio.h>
#include <stdlib.h>
#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include "SDL2/SDL_ttf.h"
#define WIDTH 1280
#define HEIGHT 720
#define FONT_SIZE 35
// 图片
struct SDL_Surface* background;
struct SDL_Surface* cat_1, * cat_2, * cat_flag;
struct SDL_Surface* obstacle_1, * obstacle_2;
// 字体
SDL_Color color = { 0, 0, 0, 255 };
TTF_Font* font;
TTF_Font* font_gameover;
int score = 1, plus = 1; // 得分
int speed = 7;
int temp_score, temp_plus, temp_speed;
int ret1; // 随机数生成
int x_cat = 130, y_cat = 350;
int x_ob = 1920, y_ob1 = 450, y_ob2 = 300;
int x_bg = 0;
int start = 0;
void draw_bg(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_cat(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_catflag(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_ob1(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_ob2(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void PrintInfo_Start(TTF_Font* font, SDL_Surface* screen, SDL_Window* win);
void PrintInfo_End(SDL_Surface* screen, SDL_Window* win);
void PrintInfo_Restart(TTF_Font* font, SDL_Surface* screen, SDL_Window* win);
void PrintInfo_Pause(TTF_Font* font, SDL_Surface* screen, SDL_Window* win);
void print_score(TTF_Font* font, SDL_Surface* screen, SDL_Window* win);
void print_score_end(TTF_Font* font, SDL_Surface* screen, SDL_Window* win);
void draw_screen1(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_screen2(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win);
void draw_gameover(SDL_Surface* screen, SDL_Window* win);
void end();
int main(int argc, char* argv[])
{
ret1 = rand() % 10 + 1; //障碍物随机数.
float x0 = x_cat, y0 = y_cat;
// 图片
cat_1 = IMG_Load("IMAGE/cat_1.png");
cat_2 = IMG_Load("IMAGE/cat_2.png");
cat_flag = IMG_Load("IMAGE/cat_flag.png");
obstacle_1 = IMG_Load("IMAGE/obstacle_1.png");
obstacle_2 = IMG_Load("IMAGE/obstacle_2.png");
background = IMG_Load("IMAGE/background.png");
// 字体
TTF_Init();
font = TTF_OpenFont("TTF/Minecraft.ttf", 35);
font_gameover = TTF_OpenFont("TTF/Minecraft.ttf", 60);
if (font == NULL) {
SDL_Log("Can not open font");
return 1;
}
if (TTF_Init()) {
SDL_Log("Can not init ttf, %s", TTF_GetError());
return 1;
}
SDL_Window* win = SDL_CreateWindow(
"Cat, cat, I really surrendered.", // 窗口标题
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT,
SDL_WINDOW_SHOWN);
if (win == NULL) {
SDL_Log("Can not create window, %s", SDL_GetError());
return 2;
}
struct SDL_Surface* screen = SDL_GetWindowSurface(win);
while (1) {
if (start == 0) {
draw_bg(background, screen, win);
draw_cat(cat_1, screen, win);
PrintInfo_Start(font, screen, win);
SDL_UpdateWindowSurface(win);
SDL_Delay(50);
}
if (start == 1) {
if (score >= 5000 && speed == 7) {
speed += 2;
plus *= 2;
}
else if (score >= 15000 && speed == 9) {
speed += 2;
plus *= 2;
}
else if (score >= 50000 && speed == 11) {
speed += 2;
plus *= 2;
}
draw_screen1(cat_1, screen, win);
}
if (start == 2) {
draw_gameover(screen, win);
}
SDL_Event event;
UP:
if (SDL_PollEvent(&event)) {
if (start == 0 && event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_SPACE:
start = 1;
break;
}
}
else if (start == 1 && event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_UP:
for (int t = 1; t <= 72; t++) {
float a = 0.5, v = -18;
float h = 0;
h = v * t + 0.5 * a * t * t;
y_cat = y0 + h;
draw_screen1(cat_1, screen, win);
if (start == 2)
break;
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_1:
{
PrintInfo_Pause(font, screen, win);
SDL_UpdateWindowSurface(win);
while (1)
{
SDL_Delay(20);
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN)
switch (event.key.keysym.sym)
{
case SDLK_1:
goto CONTINUE2;
}
if (event.type == SDL_QUIT)
goto END;
}
CONTINUE2:;
}
}
}
}
break;
case SDLK_SPACE:
for (int t = 1; t <= 72; t++) {
float a = 0.5, v = -18;
float h = 0;
h = v * t + 0.5 * a * t * t;
y_cat = y0 + h;
if (start == 2)
break;
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_1:
{
PrintInfo_Pause(font, screen, win);
SDL_UpdateWindowSurface(win);
while (1)
{
SDL_Delay(20);
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN)
switch (event.key.keysym.sym)
{
case SDLK_1:
goto CONTINUE3;
}
if (event.type == SDL_QUIT)
goto END;
}
CONTINUE3:;
}
}
}
draw_screen1(cat_1, screen, win);
}
break;
case SDLK_DOWN: {
while (1) {
if (start == 2)
break;
if (SDL_PollEvent(&event) && event.type == SDL_KEYUP)
switch (event.key.keysym.sym) {
case SDLK_DOWN: {
goto UP;
}
}
else if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_1:
{
PrintInfo_Pause(font, screen, win);
SDL_UpdateWindowSurface(win);
while (1)
{
SDL_Delay(20);
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN)
switch (event.key.keysym.sym)
{
case SDLK_1:
goto UP;
}
if (event.type == SDL_QUIT)
goto END;
}
}
}
}
draw_screen2(cat_2, screen, win);
}
}
break;
case SDLK_1: {
PrintInfo_Pause(font, screen, win);
SDL_UpdateWindowSurface(win);
while (1) {
SDL_Delay(20);
if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN)
switch (event.key.keysym.sym) {
case SDLK_1:
goto CONTINUE1;
}
if (event.type == SDL_QUIT)
goto END;
}
CONTINUE1:;
}
}
}
else if (start == 2 && event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_SPACE: {
start = 0;
score = 1, plus = 1;
speed = 7;
x_cat = 130, y_cat = 350;
x_ob = 1920, y_ob1 = 450;
x_bg = 0;
}
}
}
if (event.type == SDL_QUIT) {
break;
}
}
}
END:
SDL_FreeSurface(background);
SDL_FreeSurface(cat_1), SDL_FreeSurface(cat_2), SDL_FreeSurface(cat_flag);
SDL_FreeSurface(obstacle_1), SDL_FreeSurface(obstacle_2);
TTF_CloseFont(font), TTF_CloseFont(font_gameover);
SDL_FreeSurface(screen);
SDL_DestroyWindow(win);
return 0;
}
void draw_bg(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win) {
SDL_Rect src1 = { x_bg, 0, img->w, img->h }; // 捕获图片区域1
SDL_Rect src2 = { 0, 0, x_bg, img->h }; // 捕获图片区域2
SDL_Rect put1 = { 0, 0, img->w - x_bg, img->h }; // 显示区域1
SDL_Rect put2 = { img->w - x_bg, 0, img->w, img->h }; // 显示区域2
SDL_BlitSurface(img, &src1, screen, &put1);
SDL_BlitSurface(img, &src2, screen, &put2);
// SDL_UpdateWindowSurface(win);
}
void draw_cat(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win) {
SDL_Rect get_image = { 0, 0, img->w, img->h };
SDL_Rect put_screen = { x_cat, y_cat, x_cat + img->w, y_cat + img->h };
SDL_BlitSurface(img, &get_image, screen, &put_screen);
}
void draw_catflag(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win) {
SDL_Rect get_image = { 0, 0, img->w, img->h };
SDL_Rect put_screen = { 500, 280, 600 + img->w, 280 + img->h };
SDL_BlitSurface(img, &get_image, screen, &put_screen);
}
void draw_ob1(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win) {
SDL_Rect get_image = { 0, 0, img->w, img->h };
SDL_Rect put_screen = { x_ob, y_ob1, x_ob + img->w, y_ob1 + img->h };
SDL_BlitSurface(img, &get_image, screen, &put_screen);
}
void draw_ob2(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win) {
SDL_Rect get_image = { 0, 0, img->w, img->h };
SDL_Rect put_screen = { x_ob, y_ob2, x_ob + img->w, y_ob2 + img->h };
SDL_BlitSurface(img, &get_image, screen, &put_screen);
}
void PrintInfo_Start(TTF_Font* font, SDL_Surface* screen, SDL_Window* win) {
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font, "Press 'SPACE' to start !", color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 100, 100, 100 + text->w, 100 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void PrintInfo_End(SDL_Surface* screen, SDL_Window* win) {
char s[10086] = { 0 };
sprintf(s, "SCORE : %d", score);
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font_gameover, "G A M E O V E R", color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 350, 150, 350 + text->w, 150 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void PrintInfo_Restart(TTF_Font* font, SDL_Surface* screen, SDL_Window* win) {
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font, "Press 'SPACE' to restart !", color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 350, 550, 350 + text->w, 550 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void PrintInfo_Pause(TTF_Font* font, SDL_Surface* screen, SDL_Window* win) {
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font, "Press '1' to continue !", color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 720, 150, 720 + text->w, 150 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void print_score(TTF_Font* font, SDL_Surface* screen, SDL_Window* win) {
char s[10086] = { 0 };
sprintf(s, "SCORE : %d", score);
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font, s, color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 900, 50, 50 + text->w, 50 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void print_score_end(TTF_Font* font, SDL_Surface* screen, SDL_Window* win) {
char s[10086] = { 0 };
sprintf(s, "SCORE : %d", score);
struct SDL_Surface* text = TTF_RenderUTF8_Blended(font, s, color);
SDL_Rect src = { 0, 0, text->w, text->h };
SDL_Rect put_screen = { 350, 225, 350 + text->w, 225 + text->h };
SDL_BlitSurface(text, &src, screen, &put_screen);
SDL_FreeSurface(text);
}
void end() {
speed = 0, plus = 0, start = 2;
ret1 = rand() % 100 + 1;
SDL_Delay(600);
}
void draw_screen1(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win)
{
if (x_bg >= 1280) {
x_bg = 0;
}
if (x_ob <= -100) {
x_ob = 1680;
ret1 = rand() % 100 + 1;
}
x_bg += speed, x_ob -= speed;
score += plus;
draw_bg(background, screen, win);
draw_cat(img, screen, win);
if (ret1 <= 80)
draw_ob1(obstacle_1, screen, win);
else if (ret1 > 80)
draw_ob2(obstacle_2, screen, win);
print_score(font, screen, win);
if (start == 1) {
SDL_UpdateWindowSurface(win);
SDL_Delay(5);
}
if (ret1 <= 80
&& x_ob + obstacle_1->w >= x_cat + 80
&& x_ob <= x_cat + 150
&& y_ob1 <= y_cat + 220) {
end();
}
else if (ret1 > 80
&& x_ob + obstacle_2->w >= x_cat + 75
&& x_ob <= x_cat + 140
&& y_ob2 + obstacle_2->h >= y_cat + 30
&& y_ob2 <= y_cat + 223) {
end();
}
}
void draw_screen2(SDL_Surface* img, SDL_Surface* screen, SDL_Window* win)
{
if (x_bg >= 1280) {
x_bg = 0;
}
if (x_ob <= -100) {
x_ob = 1680;
ret1 = rand() % 100 + 1;
}
x_bg += speed, x_ob -= speed;
score += plus;
draw_bg(background, screen, win);
draw_cat(img, screen, win);
if (ret1 <= 80)
draw_ob1(obstacle_1, screen, win);
else if (ret1 > 80)
draw_ob2(obstacle_2, screen, win);
print_score(font, screen, win);
if (start == 1) {
SDL_UpdateWindowSurface(win);
SDL_Delay(5);
}
if (ret1 <= 80
&& x_ob + obstacle_1->w >= x_cat + 80
&& x_ob <= x_cat + 220
&& y_ob1 <= y_cat + 110) {
end();
}
}
void draw_gameover(SDL_Surface* screen, SDL_Window* win) {
SDL_Surface* screen0 = SDL_GetWindowSurface(win);
SDL_Rect r = { 0, 0, WIDTH, HEIGHT };
SDL_FillRect(screen0, &r, 0xffffffff);
// 绘制矩形背景板,ARGB
draw_catflag(cat_flag, screen, win);
PrintInfo_End(screen, win);
print_score_end(font, screen, win);
PrintInfo_Restart(font, screen, win);
SDL_UpdateWindowSurface(win);
SDL_Delay(20);
}