【C语言】游戏开发:天天酷跑丨完美练手项目 [附源码]

目录

一.项目说明:

二.项目作用

三.项目技术要求

四.库、宏、主函数说明

五.项目实现

        5.1游戏背景的实现

5.2实现Hero奔跑

5.3 实现Hero跳跃

5.4 优化帧等待

5.6使用结构体优化障碍物

5.7添加柱子障碍物

5.8碰撞检测

5.9优化下蹲-实现血条

5.10判断游戏结束、添加背景音乐、添加初始界面

5.11解决死亡障碍

5.12​​​​​​​显示分数

5.13​​​​​​​判断胜利

六:成品展示


一.项目说明:

原作者:奇牛编程 Rock老师

视频原地址:C语言手写天天酷跑_哔哩哔哩_bilibili

1.编程语言:C语言加上一点点C++的函数
2.开发环境:VC2010-VS2022 都可
3.开发用时:7小时
4.素材、源码、第三方库等加学习群:817459939  【传送门】


二.项目作用


1. 多层次滚动背景实现立体距离
2. 游戏引擎架构的设计
3. 多重障碍物的设计和实现
4. 游戏核心:碰撞检测的实现
5. 跳跃、下蹲的设计和实现
6. 炫酷分数的设计和实现

能够快速提升项目开发能力!
项目和笔记,可以直接作为课设。

三.项目技术要求

最低要求:

常量,变量,数组,循环,函数。

四.库、宏、主函数说明

#define _CRT_SECURE_NO_WARNINGS//使用scanf函数防止报错
#define WIN_SCORE 20//用于定义游戏获胜的分数条件
#define WIDTH 1012//游戏背景的宽度
#define HEIGHT 396//高度
#define OBSTACLE_COUNT 10//障碍物数量
#include//标准输入输出库函数
#include//引入图形库
#include//按键输入库
#include"tools.h"//添加本地头文件
#include//引入c++库用于使用容器变长数组
——————————————————————————————————————————————————

int main(void) { 
	init();//初始化函数
	loadimage(0, "res/over.png");//初始画面
	system("pause");//调用DOS系统的暂停命令 pause 来暂停程序执行,按任意一个键后将继续执行。
	int timer = 0;
	while (1) {
		keyEvent();//用于接收空格和tab键来去执行对应的跳跃/下蹲函数
		timer+=getDelay();//第三方封装函数用于返回距离上次间隔调用的时间
		if (timer > 30) {//间隔30帧刷新一次页面
			timer = 0;
			update = true;
		}
		if (update) {//刷新页面
			update = false;
			BeginBatchDraw();//去除闪烁
			updateBg();//渲染游戏背景
			//putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
			updateHero();//渲染下蹲图片
			updateEnemy();//渲染障碍物
			updateBloodBar();//调用第三方接口渲染血条
			updateScore();//渲染分数图片输出
			checkWin();//检查游戏是否胜利
			EndBatchDraw();//去除闪烁
			checkOver();//检查游戏是否结束
			checkScore();//计算得分
			fly();//实现跳跃,下蹲,障碍物的移动等动态效果
		}
	}
	system("pause");
//调用DOS系统的暂停命令 pause 来暂停程序执行,按任意一个键后将继续执行。
	return 0;
}

五.项目实现

        5.1游戏背景的实现

#include 
#include 
#include "tools.h"

#define WIN_WIDTH  1012
#define WIN_HEIGHT 396

IMAGE imgBgs[3]; // 背景图片
int bgX[3];  //背景图片的x坐标
int bgSpeed[3] = { 1, 2, 4 };

// 游戏的初始化
void init() {
    // 创建游戏窗口
    initgraph(WIN_WIDTH, WIN_HEIGHT);

    // 加载背景资源
    char name[64];
    for (int i = 0; i < 3; i++) {
        // "res/bg001.png"    "res/bg002.png"     "res/bg003.png"   
        sprintf(name, "res/bg%03d.png", i + 1);
        loadimage(&imgBgs[i], name);

        bgX[i] = 0;
    }
     
}

void fly() {
    for (int i = 0; i < 3; i++) {
        bgX[i] -= bgSpeed[i];
        if (bgX[i] < -WIN_WIDTH) {
            bgX[i] = 0;
        }
    }
}

// 渲染“游戏背景”
void updateBg() {
    putimagePNG2(bgX[0], 0, &imgBgs[0]);
    putimagePNG2(bgX[1], 119, &imgBgs[1]);
    putimagePNG2(bgX[2], 330, &imgBgs[2]);
}

int main(void) {
    init();

    while (1) {
        BeginBatchDraw();
        updateBg();
        EndBatchDraw();
        fly();

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

5.2实现Hero奔跑

void updateHero() {
    if (!heroDown) {
        putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);
    }
    else {
        int y = 345 - imgHeroDown[heroIndex].getheight();
        putimagePNG2(heroX, y, &imgHeroDown[heroIndex]);
    }

}

  

5.3 实现Hero跳跃

// 实现跳跃
    if (heroJump) {
        if (heroY < jumpHeightMax) {
            heroJumpOff = 4;
        }

        heroY += heroJumpOff;

        if (heroY > 345 - imgHeros[0].getheight()) {
            heroJump = false;
            heroJumpOff = -4;
        }
    }
    else if (heroDown) {
        static int count = 0;
        int delays[2] = { 8, 30 };
        count++;
        if (count >= delays[heroIndex]) {
            count = 0;
            heroIndex++;
            if (heroIndex >= 2) {
                heroIndex = 0;
                heroDown = false;
            }
        }
    }
    else { //不跳跃
        heroIndex = (heroIndex + 1) % 12;
    }

5.4 优化帧等待

timer += getDelay(); //10
        if (timer > 30) {
            timer = 0;
            update = true;
        }

5.5 实现随机小乌龟

 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]);
        }
    }

5.6使用结构体优化障碍物


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];

5.7添加柱子障碍物

 // 加载“柱子”障碍物
    IMAGE imgH;
    vector imgHookArray;
    for (int i = 0; i < 4; i++) {
        sprintf_s(name, sizeof(name), "res/h%d.png", i + 1); //帧图片不够,补帧
        loadimage(&imgH, name, 63, 260, true);
        imgHookArray.push_back(imgH);
        obstacleImgs.push_back(imgHookArray);
        imgHookArray.pop_back();
    }

    // 初始化障碍物池
    for (int i = 0; i < OBSTACLE_COUNT; i++) {
        obstacles[i].exist = false;
    }

5.8碰撞检测

  // 玩家和障碍物的“碰撞检测”处理
    checkHit();

5.9优化下蹲-实现血条

优化下蹲:
int delays[2] = { 6, 10 };
改成
int delays[2] = { 8, 30 };

// 预加载音效
preLoadSound("res/hit.mp3");

实现血条
void updateBloodBar() {
    drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}

5.10判断游戏结束、添加背景音乐、添加初始界面

void  updateBloodBar() {
    drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}

void checkOver() {
    if (heroBlood <= 0) {
        loadimage(0, "res/over.png");
        FlushBatchDraw();
        mciSendString("stop res/bg.mp3", 0, 0, 0);
        system("pause");

        // 暂停之后,充币复活,或者直接开始下一局
        heroBlood = 100;
        mciSendString("play res/bg.mp3", 0, 0, 0);
    }
}

int main(void) {
    init();

    // 显示初始画面
    loadimage(0, "res/over.png");
    system("pause");

    int timer = 0;
    while (1) {
        keyEvent();
        timer += getDelay(); //10
        if (timer > 30) {
            timer = 0;
            update = true;
        }

        if (update) {
            update = false;
            BeginBatchDraw();
            updateBg();
            //putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);

5.11​​​​​​​解决死亡障碍

​​​​​​​

int lastObsIndex; //last obstacle index
……

   mciSendString("play res/bg.mp3 repeat", 0, 0, 0);

    lastObsIndex = -1;
}

……

 if (lastObsIndex >= HOOK1 && lastObsIndex <= HOOK4 &&
            obstacles[i].type == LION &&
            obstacles[lastObsIndex].x > (WIN_WIDTH - 500)) {
        obstacles[i].type = TORTOISE;
    }
    lastObsIndex = i;

5.12​​​​​​​显示分数

void updateScore() {
    // 50 => "50"   '5'     '5'-'0' == 5   
    char str[8];
    sprintf(str, "%d", score);

    int x = 20;
    int y = 25;

    for (int i = 0; str[i]; i++) {
        int sz = str[i] - '0';
        putimagePNG(x, y, &imgSZ[sz]);
        x += imgSZ[sz].getwidth() + 5;
    }
}

5.13​​​​​​​判断胜利

void checkOver() {
    if (heroBlood <= 0) {
        loadimage(0, "res/over.png");
        FlushBatchDraw();
        mciSendString("stop res/bg.mp3", 0, 0, 0);
        system("pause");

        // 暂停之后,充币复活,或者直接开始下一局
        heroBlood = 100;
        score = 0;
        mciSendString("play res/bg.mp3 repeat", 0, 0, 0);
    }
}

六:成品展示

视频演示:第一集​​​​​​​C语言手写天天酷跑_哔哩哔哩_bilibili

图片演示:

1.启动界面

【C语言】游戏开发:天天酷跑丨完美练手项目 [附源码]_第1张图片

 2.游戏界面

【C语言】游戏开发:天天酷跑丨完美练手项目 [附源码]_第2张图片

 3.胜利画面

【C语言】游戏开发:天天酷跑丨完美练手项目 [附源码]_第3张图片

 

​​​​​​​


一个很棒的练手项目,如果你学完了基本语法,

恰好又需要一个项目来锻炼一下自己

那么值得一学哦!

原作者:奇牛编程 Rock老师

视频原地址:C语言手写天天酷跑_哔哩哔哩_bilibili

(如需转载,请表明出处)...

你可能感兴趣的:(编程入门,C语言,项目实战,c语言,c++)