目录
一.项目说明:
二.项目作用
三.项目技术要求
四.库、宏、主函数说明
五.项目实现
? ? ? ? 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<stdio.h>//标准输入输出库函数
#include<graphics.h>//引入图形库
#include<conio.h>//按键输入库
#include"tools.h"//添加本地头文件
#include<vector>//引入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 <stdio.h>
#include <graphics.h>
#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<IMAGE> 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.启动界面
?2.游戏界面
?3.胜利画面
?
???????
一个很棒的练手项目,如果你学完了基本语法,
恰好又需要一个项目来锻炼一下自己
那么值得一学哦!
原作者:奇牛编程 Rock老师
视频原地址:C语言手写天天酷跑_哔哩哔哩_bilibili
(如需转载,请表明出处)...
|