Qt demo:开发2D“沙盒”小游戏(电脑中道崩殂,未完待续)

博主分享了使用Qt 5.14.2开发2D沙盒游戏的过程,包括Qt的安装、Inno Setup的使用,以及项目创建、UI设计、代码编写等步骤。目前游戏开发尚未完成,因电脑故障暂停更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

各位小伙伴们大家好,我是今天第一次发CSDN的mdr,我这几天用Qt做了个小型沙盒游戏,但是还没有做完,我把我的制作过程分享给大家,希望可以有所帮助;同时我也希望大佬们可以指出程序中的不足,我会努力完善

我电脑坏了,呜呜呜
这篇博客先断更一段时间,等电脑修好的吧

开发环境

1. Qt的安装

我用的是Qt 5.14.2版本,下载地址为 点击链接

如图所示,网站提供了三个版本:Windows对应.exe,Linux对应.dmg,MacOS对应.run
还可以使用qt在线安装工具下载最新版本 点击链接

2. Inno Setup

Inno Setup是一个免费的 Windows 安装程序制作软件,可进行构建-编译制作安装包。下载链接

如图所示,点击红框内链接进行下载

代码编写

1. 新建项目

演示版本:Qt 5.14.2 QtCreator 4.11.1

  1. 选择“Qt Widgets Application

  2. 选择项目路径
    注意不要选择带中文的路径,会报错

  3. build system” 就选“qmake

  4. 把窗口的基类改成“QWidget在这里插入图片描述

  5. “translation” 无需更改

  6. Select all kits可以选中, qt会帮我们自动配置项目在这里插入图片描述

  7. 一直点“下一步”,直到项目创建完成

2. 类的创建

  • main.cpp (Qt已经帮我们创建好了)
  • widget.h (Qt已经帮我们创建好了)
  • widget.cpp (Qt已经帮我们创建好了)
  • mblock.h
  • mblock.cpp
  • mworld.h
  • mworld.cpp
  • mplayer.h
  • mplayer.cpp

3. UI设计

  1. 新建项目时,Qt为我们创建了一个空的名字叫widget.ui的UI文件,如图
    在这里插入图片描述
  2. Qt 为我们提供了很多常用的控件,例如label(一个可以显示文字的标签)和button(按钮)
  3. 首先,把窗口的大小固定成800*800:
    1. 点击mininumSize左边的小三角,如图所示:
      在这里插入图片描述
      把“宽度”和“高度”都改成800,如图所示:
      在这里插入图片描述
    2. 同理,把maxinumSize也改成800*800
  4. 我们的页面总共有这样几个组件:
    + Label,显示文本;
    + PushButton,按钮;
    + Vertical Layout(纵向布局)和Horizontal Layout(横向布局)
  5. 把页面分为两个部分:
    • 上半部分宽800,高600,显示世界的方块;
    • 下半部分宽800,高600,显示游戏的基本信息:
      1. 镐子和斧头的等级,还有增加等级的按钮;
      2. 当前所处的x y坐标;
      3. 系统信息(当某些操作错误的时候的提示信息)
      4. 快捷栏位置: 1-镐子,2-斧头,3-铲子,4-方块(方块后面备注当前的默认方块种类);
      5. 背包打开/关闭

(未完待续)

4. 代码填充

  1. 方块设定(详情见 mblock.h的注释)
  2. 世界生成(参见MWorld::MWorld()):
    1. 世界由100*100=10000个方块构成,所以建立一个二维数组;
    2. 最下层是基岩;
    3. 世界分为两侧“平原”和中央“高原”,高原的起止点由mountainBeginmountainEnd决定;
    4. 生成每一位置上面的海拔,储存在int height[100]里面;
      • 在平原和高原中部,后一格的海拔随机执行以下三种操作:比前面高一格;和前面相同;比前面矮一格
      • 在高原开始处,后一格的海拔随机执行以下三种操作:比前面高一格;和前面相同;比前面高两格
      • 在高原结束处,后一格的海拔随机执行以下三种操作:比前面低一格;和前面相同;比前面低两格
    5. 在每一格的海拔高度填充一格草(blocks[height[i]][i].init(52););在草的上面填满空气;在草的下面填充两格泥土(blocks[height[i]+2][i].init(51); blocks[height[i]+1][i].init(51););在泥土下面填满石头;
    6. 生成树:隔4~11格,设置一个“树”的位置;随机生成小树和大树;
  3. 玩家设计
    1. 拥有的方块数量:std::map<int, int> blocks:因为方块编号不能重复,所以使用索引不重复的map;
    2. 镐子等级(int pickaxeLevel)和斧头等级(int axeLevel);
    3. 背包的打开或关闭(bool backpackOpen):打开为true,关闭为false;
    4. 快捷栏位置(int hand);
    5. 默认方块的编号(int defaultBlock):游戏开始时,默认方块为none;玩家可以打开背包,切换默认方块;当快捷栏位于4(block)且满足放置方块的要求时,点击右键会放置默认方块;
  4. 游戏行为:
    1. 升级镐子和斧头:
    2. 放置方块:
    3. 破坏方块:

(未完待续)

5. 代码

  1. main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[]) {
   
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
  1. widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QPaintEvent>
#include "mworld.h"
#include "mplayer.h"

QT_BEGIN_NAMESPACE
namespace Ui {
   
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
   
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);

private slots:
    void on_pushButtonPickaxe_clicked();
    void on_pushButtonAxe_clicked();

private:
    Ui::Widget *ui;
    MWorld *world;
    MPlayer *player;
    QColor defaultBlockColor;
};
#endif // WIDGET_H
  1. widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
   
    ui->setupUi(this);
    this->setWindowTitle("Mdr's sandbox game");
    world = new MWorld();
    player = new MPlayer();
    defaultBlockColor = 0xdddddd;
}

Widget::~Widget() {
    delete ui; }
void Widget::keyPressEvent(QKeyEvent *event) {
   
    ui->labelSystem->setText("System message:");
    if (this->player->backpackOpen) {
   
        if (event->key() == Qt::Key_B) {
   
            this->player->backpackOpen = !this->player->backpackOpen;
            this->ui->labelBackpack->setText(
                        this->player->backpackOpen ? "backpack: open" : "backpack: closed");
        }
    } else {
   
        auto key = event->key();
        if (key == Qt::Key_W) {
   
            // move up
            if (this->player->hand == 4) {
   
                if (this->world->blocks[this->world->x - 1][this->world->y].id == 1) {
   
                    bool ok = this->player->useBlock();
                    if (ok) {
   
                        this->world->move(1);
                        this->world->blocks[this->world->x + 1][this->world->y].init(
                                    this->player->defaultBlock);
                    }
                }
            }
        } else if (key == Qt::Key_S) {
   
            // move down
        } else if (key == Qt::Key_A) {
   
            // move left
            this->world->move(3);
        } else if (key == Qt::Key_D) {
   
            // move right
            this->world->move(4);
        } else if (key == Qt::Key_Q) {
   
            // move right
            this->world->move(5);
        } else if (key == Qt::Key_E) {
   
            // move right
            this->world->move(6);
        } else if (key == Qt::Key_B) {
   
            this->player->backpackOpen = !this->player->backpackOpen;
            this->ui->labelBackpack->setText(
                        this->player->backpackOpen ? "backpack: open" : "backpack: closed");
        } else if (key == Qt::Key_1) {
   
            this->player->hand = 1;
        } else if (key == Qt::Key_2) {
   
            this->player->hand = 2;
        } else if (key == Qt::Key_3) {
   
            this->player->hand = 3;
        } else if (key == Qt::Key_4) {
   
            this->player->hand = 4;
        }
        ui->labelHand->setText("hand: " + QString::number(this->player->hand));
        this->world->fall();
    }
    update();
}

void Widget::mousePressEvent(QMouseEvent *event) {
   
    ui->labelSystem->setText("System message:");
    int x = event->x();
    int y = event->y();
    if (event
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Minsecrus_dreamers

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值