C语言 推箱子游戏 图形界面版EGE

使用C语言和EGE图形库实现简单好看的推箱子小游戏

如果您喜欢我的文章可以点赞支持一下。
如果您对我的程序有什么意见和建议欢迎在评论区发表评论。

这是我目前为止写的,无论从时间上还是从工程量上来说都是最长的一个小程序。
从初学EGE到攻克所有的技术难点,总共历时五天。
全代码一千一百多行。

在此向帮助过我解决问题的陌生人和老师表示由衷的感谢。

首先展示几张程序的运行效果:

主菜单界面
效果1
游戏进行中界面:
效果2
效果3
效果4
关卡选择界面
效果5
游戏商城界面
效果6
地图编辑器界面
效果7
程序中除操控人物移动外所有操作均使用鼠标操作

下面进入技术环节:

C语言 EGE实现图形界面版推箱子

编译环境: Windows VS2019
其他编译器,可通过查看下文的“注意事项”将代码更正为其他平台可正常版本

需求:
界面之间互相跳转、选择关卡、控制人物移动推箱子、游戏商城、地图编辑器

思路:
使用EGE库函数在图形界面上画出图片。使用三维数组存储所有关卡。
使用wasd键控制地图数组中的值,根据值的改变实现界面的改变。
地图编辑器根据鼠标移动到的像素坐标判断他属于哪一个格子,鼠标点击则再改格子的位置画出相应图片。

做法:
游戏部分:双重循环找出二维数组中人物的位置,并根据按键和条件改变数组中的值,然后根据数组中的值画出这个数组所对应的地图。
编辑器部分:以格子宽度,通过将循环初始值0加格子边框距离边界的像素值,小于这个像素值加总的格子的宽度,最后内外层循环各循环16次,再根据这个像素值区分鼠标当前坐标所在的格子区域的xy坐标,当鼠标点击左键时在对应xy处画出对应图片。

具体详细做法清查看代码。

使用到知识点:
三维二维数组,写入文件,函数之间相互调用,EGE相关操作

难点:
EGE各种函数的使用
函数之间相互调用
根据按键改变数组中的值
编辑器循环确定鼠标对应网格坐标(不在左上角的情况)

说明:
在写程序的过程中,因为比较赶进度,所以在ege函数的用法和代码规范上可能存在较多缺陷,还请大家多多包涵。

如需要程序需要的图片素材请对我留言。

注意:

因为该程序需要用到ege库函数,所以在编译使用该代码之前需要配置ege图形库
并使用c++编译器进行性编译。

如果要在VS之外的编译环境编译,需要将
文件打开函数fopen_s(&fp, buff, “w”);更改为fp = fopen(buff, “w”);
fprintf_s更改为fprintf fprintf_s()更改为fprintf

代码实现:
#include <graphics.h>       //ege
#include <ege/sys_edit.h>   //输入
#include <stdio.h>  //文件操作

#define LEUPINX 0      //地图最左上角X坐标
#define LEUPINY 0      //地图最左上角Y坐标
#define N 16           //地图的宽高

//设置图像对象图像大小函数:setimage();
//参数:图片对象名称,需要修改的图片对象中图片的宽高
void setimage(PIMAGE img, int pwidth, int pheight);
//自定义图片大小指定位置输出函数:toddback();
//参数:图片路径,图片宽高, 图片位置xy
void toddback(const char charr[100], int bawidth, int baheight, int backx, int backy);
//创建图片对象,锁定图片大小为全屏
PIMAGE tdoimage(const char charr[100]);     //背景图片数组

mouse_msg msg;  //主菜单选择鼠标信息
mouse_msg msg2; //选择游戏模式鼠标信息
mouse_msg msg3; //游戏中返回主菜单鼠标信息
mouse_msg msg4; //游戏中下一关鼠标信息
mouse_msg msg5; //商城界面鼠标信息

int clonum;     //初始从第几关开始游戏

//关卡选择界面
void chcheck()              //关卡选择界面
{
   
    setbkmode(TRANSPARENT);
    setcolor(WHITE);
    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\开始游戏选择背景图.jpg", getwidth(), getheight(), 0, 0);
    //背景图与模式选择界面相同

    setfont(36, 0, "黑体");   //设置字体和字号
    PIMAGE backstep = newimage();         //为文本背景图片创建新的对象
    getimage(backstep, "C:\\Users\\ASUS\\Desktop\\推箱子素材\\用于关卡选择界面.png");//步数信息文本背景图片
    setimage(backstep, 200, 55);       //设置背景图片大小
    putimage(50, 70, backstep);        //在指定位置画出图片
    //一行四个按钮                     //一个按钮宽度200,高度55,上边距70,左边距50,标准
    outtextxy(95, 80, "第一关");

    putimage(100 + 200, 70, backstep); outtextxy(95 + 250, 80, "第二关");    //第二关
    putimage(150 + 400, 70, backstep); outtextxy(95 + 500, 80, "第三关");
    putimage(200 + 600, 70, backstep); outtextxy(95 + 750, 80, "第四关");   
    putimage(50, 210, backstep); outtextxy(95, 80 + 140, "第五关");
    putimage(100 + 200, 210, backstep); outtextxy(95 + 250, 80 + 140, "第六关");
    putimage(150 + 400, 210, backstep); outtextxy(95 + 500, 80 + 140, "第七关");
    putimage(200 + 600, 210, backstep); outtextxy(95 + 750, 80 + 140, "第八关");
    putimage(50, 350, backstep); outtextxy(95, 80 + 280, "第九关");
    putimage(100 + 200, 350, backstep); outtextxy(95 + 250, 80 + 280, "第十关");
    putimage(150 + 400, 350, backstep); outtextxy(95 + 482, 80 + 280, "第十一关");

    delimage(backstep);               //用完图片对象需要释放

    while (true)
    {
   
        msg2 = getmouse();

        if (msg2.is_move())          //第二条鼠标点击并移动后break,继续
            break;
        delay_fps(59);
    }

    while (true)                    //鼠标点击开始游戏按钮时进入下一步
    {
   
        msg2 = getmouse();

        if (msg2.x >= 50 && msg2.y >= 70 && msg2.x <= 250 && msg2.y <= 125)
            if (msg2.is_left()) {
    clonum = 1; break; }  //第一关开始

        if (msg2.x >= 300 && msg2.y >= 70 && msg2.x <= 500 && msg2.y <= 125)
            if (msg2.is_left()) {
    clonum = 2; break; }

        if (msg2.x >= 550 && msg2.y >= 70 && msg2.x <= 750 && msg2.y <= 125)
            if (msg2.is_left()) {
    clonum = 3; break; }

        if (msg2.x >= 800 && msg2.y >= 70 && msg2.x <= 1000 && msg2.y <= 125)
            if (msg2.is_left()) {
    clonum = 4; break; }

        if (msg2.x >= 50 && msg2.y >= 210 && msg2.x <= 250 && msg2.y <= 265)
            if (msg2.is_left()) {
    clonum = 5; break; }

        if (msg2.x >= 300 && msg2.y >= 210 && msg2.x <= 500 && msg2.y <= 265)
            if (msg2.is_left()) {
    clonum = 6; break; }

        if (msg2.x >= 550 && msg2.y >= 210 && msg2.x <= 750 && msg2.y <= 265)
            if (msg2.is_left()) {
    clonum = 7; break; }

        if (msg2.x >= 800 && msg2.y >= 210 && msg2.x <= 1000 && msg2.y <= 265)
            if (msg2.is_left()) {
    clonum = 8; break; }

        if (msg2.x >= 50 && msg2.y >= 350 && msg2.x <= 250 && msg2.y <= 405)
            if (msg2.is_left()) {
    clonum = 9; break; }

        if (msg2.x >= 300 && msg2.y >= 350 && msg2.x <= 500 && msg2.y <= 405)
            if (msg2.is_left()) {
    clonum = 10; break; }

        if (msg2.x >= 550 && msg2.y >= 350 && msg2.x <= 750 && msg2.y <= 405)
            if (msg2.is_left()) {
    clonum = 11; break; }
        //循环?
        delay_fps(100);
    }
}
//关卡选择界面

//选择模式界面
void selsch()
{
   
    setbkmode(TRANSPARENT);
    setcolor(WHITE);
    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\开始游戏选择背景图.jpg", getwidth(), getheight(), 0, 0);

    //新游戏文字
    PIMAGE degnewbuttback = newimage();//为背景图片创建新的对象
    getimage(degnewbuttback, "C:\\Users\\ASUS\\Desktop\\推箱子素材\\选择界面标准.png");            //步数信息文本背景图片
    setimage(degnewbuttback, 250, 70); //设置背景图片大小
    putimage_withalpha(NULL, degnewbuttback, 404, 90);//输出位置
    delimage(degnewbuttback);                //用完图片对象需要释放


    setcolor(WHITE);                //文字颜色白色
    setfont(36, 0, "黑体");         //文字自号和字体,第二个参数默认0
    outtextxy(454, 106, "新 游 戏");//输出“开始游戏”文字
    //新游戏文字

    //选择关卡文字
    PIMAGE degifbuttback = newimage();//为背景图片创建新的对象
    getimage(degifbuttback, "C:\\Users\\ASUS\\Desktop\\推箱子素材\\选择界面标准.png");
    setimage(degifbuttback, 250, 70); //设置背景图片大小
    putimage_withalpha(NULL, degifbuttback, 404, 270);//输出位置
    delimage(degifbuttback);        //用完图片对象需要释放

    setcolor(WHITE);                //文字颜色白色
    setfont(36, 0, "黑体");         //文字自号和字体,第二个参数默认
    outtextxy(454, 286, "选择关卡");//输出“开始游戏”文字
    //选择关卡文字

    while (true)
    {
   
        msg = getmouse();

        if (msg.is_move())          //鼠标移动时move为1,所以必须在鼠标移动后再次点击按钮才能代表第二条鼠标消息
            break;
        delay_fps(60);
    }

    while (true)                    //鼠标点击开始游戏按钮时进入下一步
    {
   
        msg2 = getmouse();

        if (msg2.x >= 404 && msg2.y >= 90 && msg2.x <= 404 + 250 && msg2.y <= 90 + 70)//鼠标移动到指定范围时
                                    //这个范围是背景图片xy到背景图片xy+背景图片的宽高                      
            if (msg2.is_left())     //鼠标左键点击时
            {
   
                clonum = 1;         //选择新游戏从第一关开始
                break;
            }

        if (msg2.x >= 404 && msg2.y >= 270 && msg2.x <= 404 + 250 && msg2.y <= 270 + 70)
            if (msg2.is_left())
            {
   
                chcheck();          //关卡选择

                break;
            }

        delay_fps(60);     //平均延迟1000/fps毫秒,用于稳定帧率控制
    }

}
//选择模式界面结束

//游戏商城界面
int figure;         //人物形象变量
double money = 5.0; //游戏资金变量

void gamall()       //游戏商城界面
{
   
    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\商城背景4.jpg", 1543, getheight(), 0, 0);

    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\派大星2.png", 283, 280, 50, 105);
    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\喜洋洋1.jpg", 250, 280, 420, 105);
    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\源氏商城图.jpg", 220, 280, 740, 105);

    setfont(32, 0, "微软雅黑");
    setfontbkcolor(BLACK);
    setbkmode(OPAQUE);      //文字背景不透明
    setcolor(YELLOW);
    outtextxy(120, 410, "价格:免费");
    outtextxy(470, 410, "价格:免费");
    outtextxy(770, 410, "价格:200元");

    outtextxy(120, 480, "正在使用");
    outtextxy(470, 480, "使用          ");
    outtextxy(770, 480, "购买          ");


    xyprintf(0, 60, "剩余资产:%.2lf 元", money);

    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\返回按钮.png", 50, 50, 0, 0);

    toddback("C:\\Users\\ASUS\\Desktop\\推箱子素材\\用于关卡选择界面.png", 200, 50, 850, 0);
    setbkmode(1);      //文字背景透明
    setcolor(WHITE);
    outtextxy(900, 10, "开始游戏");

    int op = 0;         //没有1购买过高级形象op为0

    setbkmode(OPAQUE);      //文字背景不透明
    setcolor(YELLOW);
    while (true)                    //鼠标点击开始游戏按钮时进入下一步
    {
   
        msg5 = getmouse();

        if (msg5.x >= 0 && msg5.y >= 0 && msg5.x <= 50 && msg5.y <= 50) 
            if (msg5.is_left())     //鼠标左键点击时
            {
   
                void gamegoint();
                gamegoint();        //主菜单界面
                break;
            }
        
        if (msg5.x >= 470 && msg5.y >= 0 && msg5.x <= 1050 && msg5.y <= 50)
            if (msg5.is_left())     //鼠标左键点击时
            {
   
                selsch();           //选择模式界面
                break;
            }

        if (msg5.x >= 120 && msg5.y >= 480 && msg5.x <= 120 + 130 && msg5.y <= 480 + 32)
            if (msg5.is_left())     //鼠标左键点击时
            {
   
                op = 0;
                figure = 0;
                outtextxy(120, 480, "              "); outtextxy(120, 480, "正在使用");
                outtextxy(470, 480, "使用          "); outtextxy(770, 480, "使用          ");
            }
        if (msg5.x >= 470 && msg5.y >= 480 && msg5.x <= 470 + 130 && msg5.y <= 480 + 32)
            if (msg5.is_left())     //鼠标左键点击时
            {
   
                op = 0;     //op控制是否可以点击源氏形象下方使用按钮
                figure = 1;
                outtextxy(470, 480, "              "); outtextxy(120, 480, "使用          ");
                outtextxy(470, 480, "正在使用"); outtextxy(770, 480, "使用          ");
            }
        if (msg5.x >= 770 && msg5.y >= 480 && msg5.x <= 770 + 130 && msg5.y <= 480 + 32)
            if (msg5.is_left())     //鼠标左键点击时
            {
   
                if (money < 200)
                {
   
                    outtextxy(770, 550, "资金不足");
                    continue;               //点击购买按钮,如果游戏资金小于200则重新循环
                }
                
                if (op) continue;           //如果已经购买过一次则直接进入下一次循环
                outtextxy(770, 550, "已购买    ");
                money -= 200;               //购买形象后,资金-200
                xyprintf(0, 60, "剩余资产:%.2lf 元", money);

                figure = 2;
                outtextxy(770, 480, "              "); outtextxy(120, 480, "使用          ");
                outtextxy(470, 480, "使用          "); outtextxy(770, 480, "正在使用");
                op = 1;                     //购买过op为1
            }

        delay_fps(90);
    }
    
}

#define MAXP 11      //最大关数
int mapbox[MAXP][N][N] =                       //三维数组
{
   
    {
          //第一关
      {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 1, 9, 1, 1, 1, 1, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 1, 1, 1, 3, 9, 3, 2, 1, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 1, 2, 9, 3, 4, 1, 1, 1, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0},
      {
   0, 0, 0, 0, 0, 0, 0
  • 32
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值