交换一个苹果,得到一个苹果;交换一种思想,得到一种思想。选择与你才干,性格不同的人,他可以弥补你的缺陷。
嗨!这里是狐狸~~最近有点网抑云了,脑子很乱,不晓得想些什么,到了年底感觉什么都没做显得格外的浮躁,每晚睡觉时都有万根针在扎似的,时间又是一年去,时间的年轮又转了一圈,不知道大家有没有和我相似的感受呢,扯远了,回归正题,今天来和大家分享的项目是《疯狂赛车》
当然啦,我们今天做的是个简易版的,也不是3d的,主要是希望大家可以更容易的理解里面的逻辑关系,好了,先给大家展示一下我们的游戏界面吧
看起来还是比较粗糙的,但这都不是问题,我说过很多次了,我只教方法,至于做成什么样还得看自己的审美以及能力,OK,接下来来教大家怎么具体的实现这个游戏项目。
具体思路 1、图形基础 1.1 如何显示一张图片? 1.1.1 起名字
类型:IMAGE
1.1.2 所以要加载图片
loadimage(&图片名字,"图片的路径");
1.1.3 显示图片:putimage(int x,int y,那张图片);
1.2.1 创建一个多大的窗口
initgraph(int w,int h);
1.2.2 关闭窗口
closegraph();
1.3.1 认识一下背景图和掩码图
1.3.2 采用SRCAND 方式掩码图
putimage(int x,int y,那张图片,SRCAND);
1.3.3 采用SRCPAINT 方式贴背景图
putimage(int x,int y,那张图片,SRCPAINT);
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绘制函数#include //需要安装的 #include"images/tools.hpp" #include #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】了解。想要对程序员的未来发展有兴趣的可以关注微信公众号:【狐狸的编码时光】,希望和大家一起学习进步
视频讲解看文字太枯燥?有需要视频详细讲解的看这里
C语言/C++游戏项目教程:《疯狂赛车》,每个人都要加油活下去啊
完整代码
#include#include //需要安装的 #include"images/tools.hpp" #include #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); } #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; } } } 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; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)