IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】游戏项目:《疯狂赛车》,每个人都要加油活下去 -> 正文阅读

[C++知识库]【C语言】游戏项目:《疯狂赛车》,每个人都要加油活下去

交换一个苹果,得到一个苹果;交换一种思想,得到一种思想。选择与你才干,性格不同的人,他可以弥补你的缺陷。

嗨!这里是狐狸~~

最近有点网抑云了,脑子很乱,不晓得想些什么,到了年底感觉什么都没做显得格外的浮躁,每晚睡觉时都有万根针在扎似的,时间又是一年去,时间的年轮又转了一圈,不知道大家有没有和我相似的感受呢,扯远了,回归正题,今天来和大家分享的项目是《疯狂赛车》

当然啦,我们今天做的是个简易版的,也不是3d的,主要是希望大家可以更容易的理解里面的逻辑关系,好了,先给大家展示一下我们的游戏界面吧

看起来还是比较粗糙的,但这都不是问题,我说过很多次了,我只教方法,至于做成什么样还得看自己的审美以及能力,OK,接下来来教大家怎么具体的实现这个游戏项目。

具体思路

1、图形基础

? ? ?1.1 如何显示一张图片?

? ? ? ? ? 1.1.1 起名字
?? ??? ??? ??? ?类型:IMAGE
?? ??? ??? 1.1.2 所以要加载图片
?? ??? ??? ??? ?loadimage(&图片名字,"图片的路径");
?? ??? ??? ?1.1.3 显示图片:putimage(int x,int y,那张图片);

? ? ? 1.2 创建图形窗口

? ? ? ? ? ?1.2.1 创建一个多大的窗口
?? ??? ??? ??? ?initgraph(int w,int h);
?? ??? ??? ?1.2.2 关闭窗口
?? ??? ??? ??? ?closegraph();

? ? ?1.3?透明贴图技术

? ? ? ? ?1.3.1 认识一下背景图和掩码图
?? ??? ??? ?1.3.2 采用SRCAND 方式掩码图
?? ??? ??? ??? ?putimage(int x,int y,那张图片,SRCAND);
?? ??? ??? ?1.3.3 采用SRCPAINT 方式贴背景图
?? ??? ??? ??? ?putimage(int x,int y,那张图片,SRCPAINT);

2、绘制赛道

? ? 2.1设置线条样式

? ? ? ? ? ? ? ?setlinestyle(PS_SOLID, 3);

? ? 2.2设置线条的颜色

? ? ? ? ? ? ? setlinecolor(BLACK);

? ? 2.3画赛道中心线

? ? ? ? ? ? ? setlinecolor(WHITE);

? ? ? ? ? ? ? line(IMG_SIZE * 2, 0, IMG_SIZE * 2, IMG_SIZE * ROW);

3、绘制赛车

? ? 3.1 绘制玩家赛车

? ? ? ? ? ? drawImg(player.x, player.y, img_car + player.i);

? ? 3.2绘制敌车

? ? ? ? ? ? ? for (size_t i = 0; i < 3; i++){

? ? ? ? ? ? ? ?drawImg(enemy[i].x, enemy[i].y, img_car + enemy[i].i);

? ? ? ? ? ? ? ? ? ? ?}

4、赛车的移动

? ? ? ? ? 键盘控制赛车的移动

if (GetAsyncKeyState(VK_UP) && player.y >= 0)
	{
		player.y -= player.speed;
	}
	if (GetAsyncKeyState(VK_DOWN) && player.y + 60 <= getheight())
	{
		player.y += player.speed;
	}
	if (GetAsyncKeyState(VK_LEFT) && player.x > IMG_SIZE)
	{
		player.x -= player.speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) && player.x + 40 <= IMG_SIZE * 3)
	{
		player.x += player.speed;
	}

5、碰撞检测(重点)

? ? ? ? ?如果我方赛车碰撞敌方赛车 返回1 否则返回-1, 如过没有碰撞返回0

//检测碰撞 c1碰撞c2
	for (size_t i = 0; i < 4; i++)
	{
		if (pc1[i].x > c2->x && pc1[i].x <= c2->x + 40 &&
			pc1[i].y>c2->y && pc1[i].y<=c2->y+60)
		{
			return 1;
		}
	}

	//检测碰撞 c2碰撞c1
	for (size_t i = 0; i < 4; i++)
	{
		if (pc2[i].x > c1->x && pc2[i].x <= c1->x + 40 &&
			pc2[i].y > c1->y && pc2[i].y <= c1->y + 60)
		{
			return -1;
		}
	}

项目代码

头文件

#include<stdio.h>
#include<easyx.h>	//需要安装的
#include"images/tools.hpp"

#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

绘制函数

void draw()
{
	for (size_t i = 0; i < ROW; i++)
	{
		for (size_t k = 0; k < COL; k++)
		{
			if (k == 1 || k == 2)
			{
				putimage(k * IMG_SIZE, i * IMG_SIZE, img+1);

			}
			else
			{
				putimage(k * IMG_SIZE, i * IMG_SIZE, img);
			}		
		}
	}

	//美化车道
	//设置线条样式
	setlinestyle(PS_SOLID, 3);
	//设置线条的颜色
	setlinecolor(BLACK);

	line(IMG_SIZE, 0, IMG_SIZE, IMG_SIZE * ROW);
	line(IMG_SIZE*3, 0, IMG_SIZE*3, IMG_SIZE * ROW);
	//画中心线
	setlinecolor(WHITE);
	line(IMG_SIZE * 2, 0, IMG_SIZE * 2, IMG_SIZE * ROW);
}
void drawCar()
{
	//绘制玩家
	drawImg(player.x, player.y, img_car + player.i);
	//绘制敌车
	for (size_t i = 0; i < 3; i++)
	{
		drawImg(enemy[i].x, enemy[i].y, img_car + enemy[i].i);
	}
}

初始化函数

void initCar()
{
	//玩家
	player.x = carX[rand() % 4];
	player.y = getheight() -  80;
	player.speed = 1;
	player.i = 3;
	//初始化敌车
	for (size_t i = 0; i < 3; i++)
	{
		enemy[i].x = carX[rand() % 4];
		enemy[i].y = rand() % getheight();
		enemy[i].speed = rand() % 3 + 1;//1 2 3
		enemy[i].i = rand() % 4;
	}
}

赛车移动函数

void moveCar()
{
	//获取异步按键状态
	if (GetAsyncKeyState(VK_UP) && player.y >= 0)
	{
		player.y -= player.speed;
	}
	if (GetAsyncKeyState(VK_DOWN) && player.y + 60 <= getheight())
	{
		player.y += player.speed;
	}
	if (GetAsyncKeyState(VK_LEFT) && player.x > IMG_SIZE)
	{
		player.x -= player.speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) && player.x + 40 <= IMG_SIZE * 3)
	{
		player.x += player.speed;
	}

	for (size_t i = 0; i < 3; i++)
	{
		enemy[i].y += enemy[i].speed;
		if (enemy[i].y > getheight())
		{
			enemy[i].y = -70;
			enemy[i].x = carX[rand() % 4];
			enemy[i].speed = rand() % 3 + 1;//1 2 3
			enemy[i].i = rand() % 4;
		}
	}
}

碰撞检测函数

int collision(struct Car* c1, struct Car* c2)
{
	struct Point pc1[4] = { {c1->x,c1->y},{c1->x + 40,c1->y},{c1->x,c1->y + 60},{c1->x + 40,c1->y + 60} };
	struct Point pc2[4] = { {c2->x,c2->y},{c2->x + 40,c2->y },{c2->x,c2->y + 60},{c2->x + 40,c2->y + 60} };

	//检测碰撞 c1碰撞c2
	for (size_t i = 0; i < 4; i++)
	{
		if (pc1[i].x > c2->x && pc1[i].x <= c2->x + 40 &&
			pc1[i].y>c2->y && pc1[i].y<=c2->y+60)
		{
			return 1;
		}
	}

	//检测碰撞 c2碰撞c1
	for (size_t i = 0; i < 4; i++)
	{
		if (pc2[i].x > c1->x && pc2[i].x <= c1->x + 40 &&
			pc2[i].y > c1->y && pc2[i].y <= c1->y + 60)
		{
			return -1;
		}
	}
	return 0;
}

效果展示

总结

简单的总结一下,想对初学编程的同学说,其实编程不一定是没有乐趣的,不可否认它确实是一个枯燥而又漫长的过程,在其中苦中做乐就显得十分重要,大家不要想着项目很难做就整天的抱着题目刷,搁谁时间长了都会烦,兴趣是最好的老师,何不把自己学的知识以项目的形式实际的出现在自己面前呢,希望大家可以明白这个道理吧,千万不要被动的去学习,ok,说的有点多了,最后希望可以得到大家的点赞和关注了,十分感谢!

好了,大家还想看什么一定要在评论区告诉我,后续我还会发布更多的项目源或者学习资料,希望大家可以持续关注,有什么问题可以回帖留言。想要C/C++学习资料以及其他项目的源码的可以加群【1083227756】了解。想要对程序员的未来发展有兴趣的可以关注微信公众号:【狐狸的编码时光】,希望和大家一起学习进步

视频讲解

看文字太枯燥?有需要视频详细讲解的看这里?

https://www.bilibili.com/video/BV1M44y1a7nr/icon-default.png?t=LA92https://www.bilibili.com/video/BV1M44y1a7nr/

完整代码

#include<stdio.h>
#include<easyx.h>	//需要安装的
#include"images/tools.hpp"

#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

#define ROW 6
#define COL 4
#define IMG_SIZE	128	//背景图片的宽度

IMAGE img[2];
IMAGE img_car[4];
void loadImg()
{
	loadimage(img + 0, "./images/bk_grass.png");
	loadimage(img + 1, "./images/bk_track.png");

	loadimage(img_car + 0, "./images/000.png");
	loadimage(img_car + 1, "./images/001.png");
	loadimage(img_car + 2, "./images/002.png");
	loadimage(img_car + 3, "./images/003.png");
}
void draw()
{
	for (size_t i = 0; i < ROW; i++)
	{
		for (size_t k = 0; k < COL; k++)
		{
			if (k == 1 || k == 2)
			{
				putimage(k * IMG_SIZE, i * IMG_SIZE, img+1);

			}
			else
			{
				putimage(k * IMG_SIZE, i * IMG_SIZE, img);
			}		
		}
	}

	//美化车道
	//设置线条样式
	setlinestyle(PS_SOLID, 3);
	//设置线条的颜色
	setlinecolor(BLACK);

	line(IMG_SIZE, 0, IMG_SIZE, IMG_SIZE * ROW);
	line(IMG_SIZE*3, 0, IMG_SIZE*3, IMG_SIZE * ROW);
	//画中心线
	setlinecolor(WHITE);
	line(IMG_SIZE * 2, 0, IMG_SIZE * 2, IMG_SIZE * ROW);
}
/*@line*/
#define Line_Num 30
struct Line
{
	int x;
	int y;
	int len;
}lines[Line_Num];
void initLines()
{
	for (size_t i = 0; i < Line_Num; i++)
	{
		lines[i].len = 50;
		//前15条
		if (i < Line_Num / 2)
		{
			lines[i].x = IMG_SIZE + IMG_SIZE / 2;
			lines[i].y = i * (25 + lines[i].len)+25;
		}
		//后15条
		else
		{
			lines[i].x = IMG_SIZE * 2 + IMG_SIZE / 2;
			lines[i].y = (i - Line_Num / 2) * (25 + lines[i].len)+25;
			//15 16 17 18 19 
		}
	}
}
void drawLines()
{
	for (size_t i = 0; i < Line_Num; i++)
	{
		line(lines[i].x, lines[i].y, lines[i].x, lines[i].y + lines[i].len);
	}
}
void moveLines()
{
	for (size_t i = 0; i < Line_Num; i++)
	{
		lines[i].y += 2;
		if (lines[i].y > getheight())
		{
			lines[i].y = -lines[i].len;
		}
	}
}

/*@Car*/
struct Car
{
	int x;
	int y;
	int speed;	//车的移动速度
	int i;		//图片下标,决定贴那一张图片
};
struct Car player;
struct Car enemy[3];
//四条车道的坐标
int carX[4] = 
{ 
	IMG_SIZE + 10,
	IMG_SIZE / 2 * 3 + 10,
	IMG_SIZE * 2 + 10,
	IMG_SIZE / 2 * 5 + 10 
};
void initCar()
{
	//玩家
	player.x = carX[rand() % 4];
	player.y = getheight() -  80;
	player.speed = 1;
	player.i = 3;
	//初始化敌车
	for (size_t i = 0; i < 3; i++)
	{
		enemy[i].x = carX[rand() % 4];
		enemy[i].y = rand() % getheight();
		enemy[i].speed = rand() % 3 + 1;//1 2 3
		enemy[i].i = rand() % 4;
	}
}
void drawCar()
{
	//绘制玩家
	drawImg(player.x, player.y, img_car + player.i);
	//绘制敌车
	for (size_t i = 0; i < 3; i++)
	{
		drawImg(enemy[i].x, enemy[i].y, img_car + enemy[i].i);
	}
}
void moveCar()
{
	//获取异步按键状态
	if (GetAsyncKeyState(VK_UP) && player.y >= 0)
	{
		player.y -= player.speed;
	}
	if (GetAsyncKeyState(VK_DOWN) && player.y + 60 <= getheight())
	{
		player.y += player.speed;
	}
	if (GetAsyncKeyState(VK_LEFT) && player.x > IMG_SIZE)
	{
		player.x -= player.speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) && player.x + 40 <= IMG_SIZE * 3)
	{
		player.x += player.speed;
	}

	for (size_t i = 0; i < 3; i++)
	{
		enemy[i].y += enemy[i].speed;
		if (enemy[i].y > getheight())
		{
			enemy[i].y = -70;
			enemy[i].x = carX[rand() % 4];
			enemy[i].speed = rand() % 3 + 1;//1 2 3
			enemy[i].i = rand() % 4;
		}
	}
}

//碰撞检测
struct Point
{
	int x;
	int y;
};
//如果c1碰撞c2 返回1   否则返回-1, 如过没有碰撞返回0
int collision(struct Car* c1, struct Car* c2)
{
	struct Point pc1[4] = { {c1->x,c1->y},{c1->x + 40,c1->y},{c1->x,c1->y + 60},{c1->x + 40,c1->y + 60} };
	struct Point pc2[4] = { {c2->x,c2->y},{c2->x + 40,c2->y },{c2->x,c2->y + 60},{c2->x + 40,c2->y + 60} };

	//检测碰撞 c1碰撞c2
	for (size_t i = 0; i < 4; i++)
	{
		if (pc1[i].x > c2->x && pc1[i].x <= c2->x + 40 &&
			pc1[i].y>c2->y && pc1[i].y<=c2->y+60)
		{
			return 1;
		}
	}

	//检测碰撞 c2碰撞c1
	for (size_t i = 0; i < 4; i++)
	{
		if (pc2[i].x > c1->x && pc2[i].x <= c1->x + 40 &&
			pc2[i].y > c1->y && pc2[i].y <= c1->y + 60)
		{
			return -1;
		}
	}
	return 0;
}
void judge()
{
	for (size_t i = 0; i < 3; i++)
	{
		if (collision(enemy + i, &player))
		{
			enemy[i].y = -70;
			enemy[i].x = carX[rand() % 4];
			enemy[i].speed = rand() % 3 + 1;//1 2 3
			enemy[i].i = rand() % 4;
		}
	}
}

int main()
{
	//mci  media device interface 
	mciSendString("open ./images/racing.mp3", NULL, 0, NULL);
	mciSendString("play ./images/racing.mp3", NULL, 0, NULL);

	// 创建窗口
	initgraph(COL * IMG_SIZE, ROW * IMG_SIZE);
	loadImg();
	initLines();
	initCar();




	//双缓冲绘图
	BeginBatchDraw();
	while (true)
	{
		draw();
		drawLines();
		moveLines();

		drawCar();
		moveCar();

		judge();

		FlushBatchDraw();
	}
	EndBatchDraw();

	getchar();
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:32:36  更:2021-12-11 15:32:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:46:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码