目录
- 一、简介
- 二、如何建立一个地图包
- 三、关于碰撞图的绘制
- 四、游戏时的说明
- 五、如何更好地绘制赛场图与碰撞图
- 六、实现代码
一、简介
此游戏是《2D 赛车》的”魔改版“——2.5D 双人赛车!
原作实现了 2D 视角的赛车游戏,但是我觉得不够真实、操纵感不强,故挤出数个周末完成了这个”魔改版“,实现了第一人称的视角。
二、如何建立一个地图包
1. 选择赛车,音乐,地图的素材
2. 在程序的 map 文件夹下建立一个文件夹将这些素材放入
3. 建立 set.ini 文件
三、关于碰撞图的绘制
碰撞图色彩格式:
- 黑色(0xFFFFFF)为赛道,减速较小
- 黄色(0xFFFF00)为沙地,会减速
- 蓝色(0x0android000FF)为冰面,会滑动
- 红色(0xFF0000)为围栏,无法通过
- 绿色(0xFFFFFF)为终点线
- 灰色(0xAAAAAA)为终点线的两端,用于判定方向(对应色值 RGB(170,170,170))
- 紫色(0xFF00FF)为玩家 2 起点
- 白色(0x000000)为玩家 1 起点
注意事项:
终点线最好为宽度为一的直线!
灰色只有两个像素点,分布在终点线的两端点
画碰撞图宁可把道路画粗一点,因为实际游戏中可能会因为碰撞图画的太窄,导致玩家好像在路上但是被卡住了
此外,设置玩家起始位置也要考虑玩家车辆的长度,如果玩家的起始位置离终点线太近,以至于玩家的车尾超过了终点线的话,那么开动车子的时候就会触发一次车子越过终点的判定。
四、游戏时的说明
- 上/W 向前开
- 下/S 倒车
- 左/A 左转
- 右/D 右转
如果卡在墙里就按住一个方向键加向前直到出去
五、如何更好地绘制赛场图与碰撞图
利用 PS 的自由路径和描边,一定要用铅笔。
游戏截图
六、实现代码
#include <graphics.h> // 引用图形库头文件 #include <ctime> #include <sstream> #include <fstream> #include <vector> #include <conio.h> // 播放 MP3 所需 #include <mmsystem.h> #pragma comment(lib,"Winmm.lib") using namespace std; #define CMD_UP 1 #define CMD_DOWN 2 #define CMD_LEFT 4 #define CMD_RIGHT 8 #define sCMD_UP 16 #define sCMD_DOWN 32 #define sCMD_LEFT 64 #define sCMD_RIGHT 128 #define CMD_QUIT 256 #define PI 3.1415926 int MaxSpeed = 8; // 最大速度 int FinSand = 5; // 在沙上的摩擦力 int FinRoad = 1; // 在路上的摩擦力 int FinIce = -2; // 在冰上的摩擦力 int SpeedAdd = 2; // 加速度 int Rota = 64; // 转动速度的 -1 次方 int NeedR = 5; // 目标圈数 int WIDE = 1280; int HEIGHT = 960; double EndLineForward = 0; // 终点角度 bool inIce; bool inRoad; bool inSand; bool inWall; bool inEndline; IMAGE Racing; // 赛场地图 IMAGE Toucher; // 碰撞图 IMAGE car1; IMAGE car2; IMAGE Player1; int Px = 150; int Py = 150; double PForward = 0; // 方向 int Pspeed = 0; // 速度 int Ppass = 0; // 通过几次终点 bool Pwrong = false; // 是否逆行 bool PHadPass = false; // 是否通过终点 bool PWaitOut = false; // 是否等待通过终点 bool Pover = false; // 是否结束 clock_t Ptime = 0; clock_t Ptime2 = 0; IMAGE Player2; int Cx = 170; int Cy = 170; double CForward = 0; int Cspeed = 0; int Cpass = 0; bool Cwrong = false; bool CHadPass = false; bool CWaitOut = false; bool Cover = false; clock_t Ctime = 0; clock_t Ctime2 = 0; bool TwoPlayer = true; bool isres = true; bool chexit = false; bool MeumMod = false; clock_t Start = 0; clock_t Now = 0; clock_t MeumUsed = 0; struct bottom // 简易的按钮实现 { int ID; int x; int y; int wide; int heigh; RECT a; wstring str; COLORREF fillcolor; COLORREF linecolor; COLORREF textcolor; LOGFONT textstyle; UINT uFormat; bottom(int gID, int gx, int gy, int gw, int gh, wstring gs) { fillcolor = getfillcolor(); linecolor = getlinecolor(); tandroidextcolor = gettextcolor(); gettextstyle(&textstyle); uFormat = DT_CENTER | DT_VCENTER | DT_SINGLELINE; ID = gID; x = gx; y = gy; wide = gw; heigh = gh; str = gs; a = { x, y, x + wide, y + heigh }; } }; struct page { vector<bottom> botlis编程客栈t; bool MouseTouch(int left, int top, int right, int bottom, MOUSEMSG m) // 鼠标区域判定 { for (int i1 = left; i1 < right; i1++) { for (int i2 = top; i2 < bottom; i2++) { if (m.x == i1 && m.y == i2) { return true; } } } return false; } int ShownPage() // 显示并等待按键被响应,返回相应的ID值 { COLORREF fillcolor = getfillcolor(); COLORREF linecolor = getlinecolor(); COLORREF textcolor = http://www.devze.comgettextcolor(); LOGFONT textstyle; gettextstyle(&textstyle); MOUSEMSG m; setbkmode(TRANSPARENT); for (unsigned int i = 0; i < botlist.size(); i++) { setfillcolor(botlist[i].fillcolor); setlinecolor(botlist[i].linecolor); settextcolor(botlist[i].textcolor); settextstyle(&botlist[i].textstyle); fillrectangle(botlist[i].x, botlist[i].y, botlist[i].x + botlist[i].wide, botlist[i].y + botlist[i].heigh); drawtext(botlist[i].str.c_str(), &botlist[i].a, botlist[i].uFormat); } FlushBATchDraw(); while (true) { FlushMouseMsgBuffer(); m = GetMouseMsg(); if (m.mkLButton) { for (unsigned int i = 0; i < botlist.size(); i++) { if (MouseTouch(botlist[i].x, botlist[i].y, botlist[i].x + botlist[i].wide, botlist[i].y + botlist[i].heigh, m)) { return botlist[i].ID; } } } } setfillcolor(fillcolor); setlinecolor(linecolor); settextcolor(textcolor); settextstyle(&textstyle); } }; struct intro // 地图的介绍信息 { wstring filename; wstring title; wstring intr; wstring inipath; }; vector<intro> IntroList; class timer // 计时器 { private: bool is_start = false; clock_t start; public: bool WaitFor(clock_t s) { if (is_start) { if ((start + s) <= clock()) { is_start = false; return true; } else { return false; } } else { start = clock(); is_start = true; return false; } } }; void init(); void gaming(); int GetCommand(); void DispatchCommand(int _cmd); void OnLeft(bool player); // false 玩家 1,true 玩家 2 void OnRight(bool player); void OnUp(bool player); void OnDown(bool player); void MoveCheck(bool player); // 碰撞判定 int PointTsm(int x, int y, int wide, int high); // 坐标与数值的转换 void Draw(); void End(); void PutImgWithout(IMAGE &obj, int px, int py, COLORREF withouter, dwORD*开发者_JS教程 pbWnd, int wX, int wY, DWORD bitsub); // 放置图片,除了 void SetBirth(); // 第一次读取 void StartWord(); void Loading(); // 加载地图 int ChooseMap(); // 选择地图 void LoadIntro(string File); BOOL SearchFilesByWildcard(spythontring wildcardPath); // 搜索文件,参考自https://blog.csdn.net/faithzzf/article/details/54290084 IMAGE zoomImage(IMAGE* pImg, int newWidth, int newHeight); // 图片缩放 void showhelp(); // 显示帮助文件 void clean(); // 清空缓冲区 void restart(); // 用于重新开始游戏 bool CanRota (bool player);//是否可以旋转
到此这篇关于C语言实现2D赛车游戏的示例代码的文章就介绍到这了,更多相关C语言赛车游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论