C语言推箱子小游戏分析
程序员文章站
2024-03-19 09:04:16
...
EasyX图形库:https://www.easyx.cn/
也可以不用图形库,直接在那个黑框框打一些正方形圆形之类的也可以~
Windows,VS2017。文章后附有代码和游戏素材。
先来捋一捋思路:
推箱子的地图,怎么搞?
用一个二维数组来表示整个地图,我们先网上找一张地图来分析下。
分析:地图上有 墙、目的地、箱子、人、背景墙、目的地和箱子合起来的(红箱子)
我们用数字来在二维数组中对应的标记这些东西,二维数组的大小就是地图的大小咯。
//定义地图大小 8*8 int Map[8][8] { 0,0,1,1,1,0,0,0, 0,0,1,3,1,0,0,0, 0,0,1,0,1,1,1,1, 1,1,1,4,0,4,3,1, 1,3,0,4,5,1,1,1, 1,1,1,1,4,1,0,0, 0,0,0,1,3,1,0,0, 0,0,0,1,1,1,0,0 };
然后干啥?
哈哈哈,当然是初始化这个地图咯,就是往这个二维数组对应的位置上贴图。
EasyX图形库自带了使用文档,大家可以看一看文档里面各种函数的使用说明。
初始化地图:1.加载图片 2.打印图片
//加载图片 void GameInit() { loadimage(&BackGroundImage, "./loop/背景.jpg"); loadimage(&Wall, "./loop/wall.jpg"); loadimage(&Destination1, "./loop/mbb.jpg"); loadimage(&People1, "./loop/ren.jpg"); loadimage(&Box1, "./loop/zd.jpg"); loadimage(&Box2, "./loop/zd副本.jpg"); loadimage(&Boom1, "./loop/boom.jpg"); loadimage(&Boom2, "./loop/boom副本.jpg"); } //打印图片 void GamePaint() { putimage(0, 0, &BackGroundImage); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { switch (Map[j][i]) { case 1: putimage(i * 45, j * 45, &Wall); break; case 3: putimage(i * 45, j * 45, &Destination1); break; case 5: putimage(i * 45, j * 45, &People1); break; case 4: putimage(i * 45, j * 45, &Box2, SRCPAINT);//这里是透明背景什么的,不解释了,大家可以百度看一看。 putimage(i * 45, j * 45, &Box1, SRCAND); break; case 7: putimage(i * 45, j * 45, &Boom2, SRCPAINT); putimage(i * 45, j * 45, &Boom1, SRCAND); break; case 8: putimage(i * 45, j * 45, &People1); break; } } } }
这里!我们就完成了地图的初始化!
下来我们来解决游戏的控制和判定部分。
我们想用上下左右键控制人物的移动,那么就得先找到人物在哪个地方。当然,我们在初始化地图的时候就已经知道了人物在哪个位置,但是如果我们重新弄一张地图初始化,我们还得来这里修改这里的代码,所以我们就让程序自己找那个人物吧。对于墙,如果人物的一面是墙,按下对应的方向键就会不作为,如果是箱子,那就判断箱子的那个方向是不是墙……等等。
//游戏控制
void GamePlay()
{
char ch;
int x, y;
BeginBatchDraw();//开启批量绘图,这样就让游戏显示的快一些,不然会有卡顿。
while (1)
{
if (!GameWin())//这里的游戏判定后面说
{
GamePaint();
FlushBatchDraw();
//MessageBox(GetHWnd(), "YOU WIN", "GO", MB_OK);
break;
}
cleardevice();
GamePaint();
FlushBatchDraw();
//找到人物的位置
for (x = 0; x < 8; x++)
{
for (y = 0; y < 8; y++)
{
if (Map[x][y] == 5 || Map[x][y] == 8)
{
break;
}
}
if (Map[x][y] == 5 || Map[x][y] == 8)
{
break;
}
//for循环结束后 Map[x][y]就是小鸟的位置
}
ch = getch();
switch (ch)
{
case 72:
case'W':
case'w':
if (Map[x - 1][y] == 0 || Map[x - 1][y] == 3)
{
Map[x][y] = Map[x][y] - 5;
Map[x - 1][y] = Map[x - 1][y] + 5;
}
else if (Map[x - 1][y] == 4 || Map[x - 1][y] == 7)
{
if (Map[x - 2][y] == 0 || Map[x - 2][y] == 3)
{
Map[x - 2][y] += 4;
Map[x - 1][y] += 1;
Map[x][y] -= 5;
}
}
break;
case 80:
case 's':
case 'S':
if (Map[x + 1][y] == 0 || Map[x + 1][y] == 3)
{
Map[x][y] -=5;
Map[x + 1][y] += 5;
}
else if (Map[x + 1][y] == 4 || Map[x + 1][y] == 7)
{
if (Map[x + 2][y] == 0 || Map[x + 2][y] == 3)
{
Map[x + 2][y] += 4;
Map[x + 1][y] += 1;
Map[x][y] -= 5;
}
}
break;
case 75:
case 'A':
case 'a':
if (Map[x][y - 1] == 0 || Map[x][y - 1] == 3)
{
Map[x][y - 1] += 5;
Map[x][y] -= 5;
}
else if (Map[x][y - 1] == 4 || Map[x][y - 1] == 7)
{
if (Map[x][y - 2] == 0 || Map[x][y - 2] == 3)
{
Map[x][y - 2] += 4;
Map[x][y - 1] += 1;
Map[x][y] -= 5;
}
}
break;
case 77:
case 'D':
case 'd':
if (Map[x][y + 1] == 0 || Map[x][y + 1] == 3)
{
Map[x][y + 1] += 5;
Map[x][y] -= 5;
}
else if (Map[x][y + 1] == 4 || Map[x][y + 1] == 7)
{
if (Map[x][y + 2] == 0 || Map[x][y + 2] == 3)
{
Map[x][y + 2] += 4;
Map[x][y + 1] += 1;
Map[x][y] -= 5;
}
}
break;
}
}
EndBatchDraw();//关闭批量绘图
MessageBox(GetHWnd(), "YOU WIN", "OK,GO ON!", MB_OK);
}
游戏win判定:
判定很好办,我们只要遍历地图,只要是所有的箱子和所有的目的地重合了,就赢了。
//游戏判定
int GameWin()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (Map[i][j] == 4)
{
winner4++;
}
if (Map[i][j] == 7)
{
winner7++;
}
}
}
if (winner4 == winner7)
{
return 0;
}
else
{
return 1;
}
}
main、main、main!
//主函数
int main()
{
initgraph(360, 360);//初始化窗口大小360*360
GameInit();//初始化地图
GamePaint();//绘制地图
GamePlay();//玩~
return 0;
}
上一篇: 记一次"内存泄露"排查过程
下一篇: 暗藏杀机? 不简单的三目运算符号!