自学内容网 自学内容网

游戏设计:推箱子【easyx图形界面/c语言】

在之前写程序设计的大作业时,在哔哩哔哩上跟着一个视频的学习的成果【第一个练习的】

今天整理文件的时候看到的,就发出来一下【CSDN和B站都有详细教程】

不是大项目,只有两个界面

这个代码只有两百行不到,但通过这个把基本的运行逻辑什么的掌握了,然后写自己的完整的游戏设计


经典的推箱子玩法,玩家需要控制一个小人,将箱子推到指定的目标位置,直到通关

#include<graphics.h>
#include<conio.h>
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 650  //屏幕宽高

#define RATIO 50 //道具比例

#define START_X 100
#define START_Y 100

#define  LINE 9
#define COLUMN 12


//控制键上下左右,退出键
#define KEY_UP 'w'
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_QUIT 'q'




//#define KEY_UNDO 'u' // 撤回键
//#define KEY_RESTART 'r' // 重玩键



#define isvalid(pos) (pos.x>=0 && pos.x<LINE && pos.y>=0 && pos.y<COLUMN)
//确保下标不会越界,移动的前提

enum _PROPS
{
WALL,//墙0
FLOOR,//地板1
BOX_DES,//箱子目的地2
MAN,//小人3
BOX,//箱子4
HIT,//箱子的正确位置5
GameOver,//通关界面6
ALL    //7数组个数
};
// 显高级枚举法,暂时不想改

typedef enum _PROPS PROPS;//定义别名

//游戏控制方向,枚举变量
enum _DIRECTION 
{
UP,
DOWN,
LEFT,
RIGHT,
};
typedef enum _DIRECTION DIRECTION;//用类型定义作简化

//0:墙 ,1:地板,2:目的地,3:小人,4:箱子,5:正确位置的箱子
int map[9][12] =
{
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,1,1,1,1,1,1,1,0,0},
{0,1,4,1,0,2,1,0,2,1,0,0},
{0,1,0,2,0,1,1,4,1,1,1,0},
{0,1,1,1,0,3,1,1,1,4,1,0},
{0,1,2,1,1,4,1,1,1,1,1,0},
{0,1,0,0,1,0,1,1,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0},
};

IMAGE images[ALL];



struct _POS 
{
int x;//小人所在的二维数组的行
int y;//小人所在的二维数组的列
};
typedef struct _POS POS;//POS小人的坐标的数据类型

POS man;     //小人的实时位置,包含小人的坐标


//
void ChangeMap(POS* pos, PROPS prop)
{
map[pos->x][pos->y] = prop;//位置  数组要改
putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &images[prop]);//视图

}
/********************
实现上下左右控制
输入:

输出
********************/


void GameControl(DIRECTION direct) //void没有返回值,方向类型定义变量
{
POS next_pos = man;//小人下一个的位置,变量初始化
POSnext_next_pos = man;//小人下下个的位置

switch (direct) //switch判断方向
{
case UP:
next_pos.x = man.x - 1;
next_next_pos.x = man.x - 2;
break;
case DOWN:
next_pos.x = man.x + 1;
next_next_pos.x = man.x + 2;//上下行变,列不变
break;
case LEFT:
next_pos.y = man.y - 1;
next_next_pos.y = man.y - 2;
break;
case RIGHT:
next_pos.y = man.y + 1;
next_next_pos.y = man.y + 2;//左右列变
break;
}
/**********
在一个狭小的仓库中,要求把木箱放到指定的位置
稍不小心就会出现箱子无法移动或者通道被堵住的情况
***********/
//逻辑判断,小人怎么走
//如果小人前进一步是地板,则前进
// 人到next_pos位置,原来的位置变成地板
if (isvalid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) 
{
ChangeMap(&next_pos, MAN);//
ChangeMap(&man, FLOOR);//人原来的位置
man = next_pos;//小人的实时位置
}

//如果人前进一步是   箱子  ,并且箱子前面next_next_pos是地板或者箱子目的地,则推着箱子走
// 
if (isvalid(next_pos) && map[next_pos.x][next_pos.y] == BOX)
{
//箱子前面是地板
if (isvalid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == FLOOR)
{
ChangeMap(&next_next_pos,BOX);
ChangeMap(&next_pos, MAN);
ChangeMap(&man, FLOOR);
man = next_pos;
}//箱子前面是目的地
else if (isvalid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == BOX_DES)
{
ChangeMap(&next_next_pos, HIT);//箱在目的地
ChangeMap(&next_pos, MAN);
ChangeMap(&man, FLOOR);
man = next_pos;
}
}

}
bool IsGameover()
{
for (int i = 0; i < LINE; i++) 
{
for (int j = 0; j < COLUMN; j++) 
{
if (map[i][j] == BOX_DES)
{
return false;
}
}
}
return true;
}


//游戏结束
void GameOverScene(IMAGE* bg)
{
putimage(0, 0, bg);
settextcolor(RED);
RECT rec = { 0,0,SCREEN_WIDTH,SCREEN_HEIGHT };//跟屏幕同宽高
settextstyle(80, 0, "楷体");
drawtext("恭喜您成功通关", & rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

}




int main(void)
{
//定义一个表示图片的变量
IMAGE bg_img;
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);//屏幕宽高
//定义一个表示图片的变量
IMAGE gameoverscene;
//设置成功背景
loadimage(&gameoverscene, "GameOverScene.png", SCREEN_WIDTH, SCREEN_HEIGHT, true);//true表示图片自适应
//设置背景
loadimage(&bg_img, "beijing.png", SCREEN_WIDTH, SCREEN_HEIGHT, true);//true表示图片自适应
putimage(0, 0, &bg_img);
//物件图片
loadimage(&images[0], "wall.png", RATIO, RATIO, true);//墙 
loadimage(&images[1], "floor.png", RATIO, RATIO, true);//地板
loadimage(&images[2], "des.png", RATIO, RATIO, true);//目的地
loadimage(&images[3], "man.png", RATIO, RATIO, true);//小人
loadimage(&images[4], "box.png", RATIO, RATIO, true);//箱子
loadimage(&images[5], "box.png", RATIO, RATIO, true);//正确位置的箱子

for (int i = 0;i < 9;i++)
{
for (int j = 0;j < 12;j++)
{
if (map[i][j] == MAN)
{
man.x = i;
man.y = j;//x行,y列
}//小人的位置
putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);
}
}


bool quit = false;//游戏结束条件

//热键控制
do
{
if (_kbhit())      //_kbnit(),_grtch()关于按键的函数
{//判断是否有按键,如果有按键按
char ch = _getch();
if (ch == KEY_UP)//w
{
GameControl(UP);//游戏控制
}
else if (ch == KEY_DOWN)//s
{
GameControl(DOWN);
}
else if (ch == KEY_LEFT)//a
{
GameControl(LEFT);
}
else if (ch == KEY_RIGHT)//d
{
GameControl(RIGHT);
}
else if (ch == KEY_QUIT) //q
{
quit = true;
}
else if (ch == KEY_QUIT) //q
{
quit = true;
}
if (IsGameover())//判断游戏是否结束,所有的2全没了
{
GameOverScene(& gameoverscene);
}
}
Sleep(100);//100ms,0.1s
//在没有按键的情况下让CPU休息一下,降低CPU率
} while (quit == false);


system("pause");
return 0;


}

是一个简单的推箱子游戏的实现,使用了 graphics.h 库来进行图形显示。

功能简单明了。

1. 游戏地图的初始化

游戏地图是一个二维数组,包含墙壁、地板、箱子、目的地等不同的元素。通过 map 数组表示,不同的整数值代表不同的元素。

int map[9][12] = {
    {0,0,0,0,0,0,0,0,0,0,0,0},  // 0代表墙
    {0,1,0,1,1,1,1,1,1,1,0,0},  // 1代表地板
    {0,1,4,1,0,2,1,0,2,1,0,0},  // 4代表箱子,2代表目的地
    // ...
};
  • 0 表示墙壁
  • 1 表示地板
  • 2 表示箱子目的地
  • 3 表示小人
  • 4 表示箱子
  • 5 表示正确放置的箱子

2. 结构体与枚举类型

  • PROPS 枚举定义了不同的游戏元素类型(如墙、地板、箱子等)。

  • DIRECTION 枚举定义了小人的移动方向(上、下、左、右)。

  • POS 结构体用来表示位置,包含 xy 两个成员,分别表示二维数组的行列。

3. 游戏控制和移动逻辑

GameControl 函数是控制小人移动的核心。根据输入的方向(上下左右),更新小人的位置,并处理箱子的推送逻辑。具体逻辑如下:

  • 如果小人前进的方向是地板,则小人可以移动。

  • 如果小人前进的方向是箱子,且箱子后方是地板或目的地,箱子可以被推移。

4. 游戏结束判断

IsGameover 函数用来判断游戏是否结束,判断标准是所有目的地(BOX_DES)上是否都有箱子。

5. 图形显示

使用 putimage 函数显示图像,加载各类图像(如墙壁、地板、箱子等),并通过 ChangeMap 函数来更新游戏地图的显示。

6. 用户输入与游戏循环

游戏通过 _kbhit()_getch() 检测用户的按键输入。如果按下控制键(如 w, a, s, d),则调用 GameControl 函数进行相应的移动操作。如果按下退出键(q),则退出游戏。


把这些东西理解后就可以自己扩写改造了,

我最后的大作业就是基于最简单的推箱子游戏进行改动,增加其他的功能进行功能扩展

这里的图片来源于网络,可能按照自己的想法更改

完整文件我上传到这了,下载可以直接运行

游戏设计:推箱子【easyx图形界面/c语言】资源-CSDN文库

自己看用上面代码然后自己整加图片素材也可以正常运行

图像加载

游戏中的每个对象(如墙、地板、小人、箱子等)都通过图像来表示。我们使用loadimage函数将图像加载到内存,并通过图形界面显示出来。

loadimage(&images[0], "wall.png", RATIO, RATIO, true); // 加载墙壁图像
loadimage(&images[1], "floor.png", RATIO, RATIO, true); // 加载地板图像
loadimage(&images[2], "des.png", RATIO, RATIO, true);   // 加载目标图像
loadimage(&images[3], "man.png", RATIO, RATIO, true);    // 加载小人图像
loadimage(&images[4], "box.png", RATIO, RATIO, true);    // 加载箱子图像

“”里就是图片对应的图片路径

loadimage(&images[4], "box.png", RATIO, RATIO, true);

"box.png" 是图像文件的路径,它是一个名为 box.png 的图像文件。

图像文件可以是多种格式,比如 .png, .jpg 等,这里使用的是 .png 格式。box.png 应该是存放在程序的工作目录下,或者是通过相对/绝对路径进行访问。

这里是直接存储在代码所在的文件夹

如果想现有运行效果,针对导入图片的一些代码加入自己的图片路径即可
 


原文地址:https://blog.csdn.net/Z15922342915/article/details/143662023

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!