第二次机器人大战吧 关注:25,452贴子:375,689

【直播】用 Qt 和 C++ 制作第二次机器人大战

只看楼主收藏回复

楼楼也算机战的老玩家了,从小学五年级到现在,前前后后大概共通关了十遍。成为一枚码农后,也慢慢萌生了重新制作这个游戏的想法,就当做给童年的一份礼物
经典截图镇楼



最近接触了Qt的图形视图框架,发现它的特性非常适合制作此类战棋游戏(一个格子正好对应一个Item,整个地图就对应一个场景Scene),话不多说,马上开始!Qt的版本是5.8


IP属地:北京1楼2018-03-20 18:57回复
    先来新建一个Qt widget项目,就叫srw2_cpp好了

    按照游戏开发的惯例,先新建一个Game类,用来实现整个游戏,这样在main函数中只需要new一个Game对象然后start游戏方法。
    Game类也作为显示游戏的界面,所以需要继承自 QGraphicsView 类,并包含一个 QGraphicsScene 对象。
    #include <QGraphicsView>
    class Game : public QGraphicsView
    {
    public:
    Game(QWidget * parent = 0);
    void start();
    QGraphicsScene * scene;
    };
    scene可以看做整个游戏的画布,后面只要把机器人 addItem 到 scene 上面。在构造函数里先初始化一下scene,先设置大小1024*768算了
    #include "game.h"
    Game::Game(QWidget *parent)
    {
    //设置不显示滚动条
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //设置视图固定大小
    setFixedSize(1024, 768);
    //新建场景,大小1024*768
    scene = new QGraphicsScene();
    scene->setSceneRect(0,0,1024,768);
    //将scene和View绑定
    setScene(scene);
    }
    void Game::start()
    {
    }
    这样就有了一张1024*768的画布


    IP属地:北京2楼2018-03-20 19:21
    收起回复
      技术贴


      IP属地:广东来自Android客户端3楼2018-03-20 19:24
      收起回复
        忘了贴main函数的代码,main函数这样以后基本不用改了,所有功能都在Game里实现

        先从地图开始吧,因为是格子游戏,可以正好用一个二维数组包含所有的格子。每一个格子继承自一个 QGraphicsPixmapItem ,它可以显示图像。


        IP属地:北京4楼2018-03-20 19:26
        回复
          支持,希望楼主坚持下去


          IP属地:四川来自Android客户端5楼2018-03-20 19:33
          收起回复
            从吧盘里下载了好多修改资料,感谢贴吧前辈的辛勤整理和付出
            在2站修改器里的地图图片,共有64张,他们分成4种类型,分别对应

            先来实现一个小格子对应的类,就叫MapRect好了,它代表地图上的一个小格子。那就要记录格子的类型,用一个int数字表示,其实范围是0到F,共16种。因为一个地图只有A、B、C或者D的其中一种风格。
            另外,移动的时候需要消耗行动力,这也需要一个变量记录下

            然后构造函数里根据地形编号设置图像,先用A类型的吧,拼接一下图像地址
            static QString gAImgPaths[16] = { "_00.png", "_01.png", "_02.png", "_03.png", "_04.png", "_05.png", "_06.png", "_07.png", "_08.png", "_09.png", "_0A.png", "_0B.png", "_0C.png", "_0D.png", "_0E.png", "_0F.png"};
            MapRect::MapRect(int kindOfMap, QGraphicsItem *parent) : QGraphicsPixmapItem(parent){ style = 'A'; kind = kindOfMap;
            setPixmap(QPixmap(game->workDir + "res/images/map32/" + style + gAImgPaths[kind]));
            }
            然后在Game start里测试一下效果

            新建一个id为2的地形,然后显示到场景中

            可以看到成功显示了出来。


            IP属地:北京6楼2018-03-20 19:45
            回复
              66666666


              IP属地:黑龙江来自iPhone客户端7楼2018-03-20 19:46
              收起回复
                再添加设置地形消耗移动力的吧

                16种地形在4种风格中应该都是一致的,比如地球的1号地形平原和宇宙的1号地形,消耗行动力应该是一样的
                通过楼楼观察和猜测,先用下面的数字好了 0号地形也就是白色的墙,实际是不可以移动的,设置消耗999行动
                static int moveConsumeTable[3][16] = {
                {999,2,2,3,4,1,3,3,3,2,2,2,2,2,2,2}, //海
                {999,1,1,2,3,3,2,2,2,1,1,1,1,1,1,1}, //陆
                {999,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} //空
                };
                void MapRect::setMoveConsume()
                {
                moveConsume[0] = moveConsumeTable[0][kind];
                moveConsume[1] = moveConsumeTable[1][kind];
                moveConsume[2] = moveConsumeTable[2][kind];
                if (style == "C" && kind == 1)
                moveConsume[0] = 1;
                }
                海类型机体 的在C风格的室内地板和A类型的平原 消耗不一样,特殊处理了一下
                然后在新建地图格子的时候,就初始化一下行动力消耗的数值。


                IP属地:北京8楼2018-03-20 19:52
                回复
                  再来画出整个地图,用一个Map类,它包含一个二维数组,里面是地图里所有的格子

                  Map里的格子按照左上角为原点(0,0)格子。向右增加第一个维度,向下增加第二个维度。
                  先在代表小格子的MapRect类里添加x和y变量,表示格子所在的位置,setxy(int x, int y)用来设置格子的位置。因为我把图片放大到了32*32像素,所以实际的像素位置应该是格子位置乘以32
                  void MapRect::setxy(int xPos, int yPos)
                  {
                  x = xPos;
                  y = yPos;
                  setPos(32*x, 32*y);
                  }
                  有了这个后,在Map里我只需要遍历二维数组,然后不断新建MapRect生成一个个的小格子
                  Map::Map(int width, int height)
                  {
                  map = QVector<QVector<MapRect *> >(width, QVector<MapRect *>(height, 0));
                  for (int i = 0; i < width; ++i)
                  {
                  for (int j = 0; j < height; ++j)
                  {
                  map[i][j] = new MapRect(rand() % 16); //先用随机数生成试试看
                  map[i][j]->setxy(i, j);
                  game->scene->addItem(map[i][j]);
                  }
                  }
                  }
                  在game的start里测试一下

                  生成一个16*20的地图,每个格子类型是随机的


                  IP属地:北京9楼2018-03-20 20:08
                  回复
                    随机的图太难看啦,我还是来copy原版的地图吧

                    第一关的地图数据应该是从5AE5到5B67

                    地图大小16*20个格子,刚开始我以为一个数字代表一种类型,后来发现不是的,而是这样:
                    前面两个字节10 14不知道有什么用,从04开始是地图
                    没一个字节,前4位表示连续有多少个,后4位才是地形的类型

                    第一行对应的数据时 04 11 14 27 02 74 ,0表示1个,1表示2个,也就是
                    1个4号(山地),2个1号(平原),2个4号(山地),3个7号(树木)...
                    这样的存储方式大概是为了省内存吧,然而也导致修改地图后地图数据大小会发生变化。因为连续的相同的格子越多就越省内存。
                    然后写了一个void loadMapFromTxt(QString filename); 用来读这段文本,并转换成我们程序中的二维数组的形式。
                    为了方便我还在地图外面加了一圈0号地形,也就是白色板砖
                    现在终于有一点游戏的样子了


                    IP属地:北京10楼2018-03-20 20:30
                    收起回复
                      不错哦,如果能坚持做下去,有啥资料都会提供给你的


                      IP属地:浙江11楼2018-03-20 21:15
                      收起回复
                        辛苦了!还希望楼主能坚持下去


                        IP属地:广东来自Android客户端12楼2018-03-20 21:35
                        收起回复


                          IP属地:安徽13楼2018-03-20 22:12
                          收起回复
                            居然加精了谢谢吧务,继续更咯


                            IP属地:北京14楼2018-03-20 23:05
                            回复
                              有问题及时在贴吧或加群反馈,我们尽量帮你


                              IP属地:山东来自Android客户端15楼2018-03-20 23:09
                              收起回复