RaceGame-Qt游戏项目构建-图形界面
RaceGame-Qt游戏项目构建-图形界面
游戏界面概述
游戏界面的绘制主要包括:地图/墙体,玩家,操作按钮。
QML 框架实现
由于使用旧版的 QWidget
框架还需要单独写一个绘制类,Qt-quick
提供了 QML
框架工具,可以以组件的形式创建窗口界面,处理点击事件和链接函数。只需要把游戏管理类设计成与 QML
形成交互,即可实现游戏逻辑、界面显示,而不用写多余的类。因此之前用 QWidget
框架构建的 class DrawGame
一系列类就不需要了。
与 QWidget
框架实现起来不同的是,C++
和 QML
联合编程,需要在调用界面之前注册C++类。 而 QWidget
的界面由 Ui
类来控制。
Main.qml
游戏开始界面,包括两个组件:Component Entry
、 Component Game
。
Entry.qml
游戏设置界面,可以选择玩家数量,选择游戏地图。
Game.qml
游戏界面,含有游戏地图的绘制,玩家移动的显示。以及一些控制游戏过程的按钮。
说明
游戏界面效果在我的 RaceGame-游戏框架 之中可以看到。
QWidget 框架实现
(此部分基于 QWidget
开发,游戏界面上的组件需要在 C++
类中创建和销毁,这样写出来的代码比较复杂。因此抛弃了这部分类,直接使用 QML
开发界面组件)
Qt
提供了很多图形库,可以直接使用,绘制游戏地图、更新玩家位置,显示操作按钮等。游戏的主体逻辑已经通过 Player
类和 GameMap
类实现,只需要根据玩家信息、地图信息,绘制出图形化界面即可。
DrawGame 相关类
DrawGame
相关类存放在 drawgame.h
头文件中,相应的源文件在 drawgame.cpp
文件中。原理比较简单,主要实现游戏界面的绘制。
一、 class DrawGame
核心类,绘制工具,需要提供边界信息,具有一个纯虚函数 draw()
,在派生类中实现。
class DrawGame { public: DrawGame(int width, int height); protected: int Width; int Height; public: virtual void draw() const = 0; virtual void destoryDraw() const = 0; };
由于 Qt
的 QPainter
库需要在绘制事件中使用,我在这里直接使用Qt 的 QLabel
元素充当填充物,用于直接在窗口绘制图形。 并且 QLabel
标签不仅可以添加文本信息,还能够直接使用 CSS
样式表,自由度高。
不过需要注意的是,刷新帧率高、绘制图形频繁的场合,使用 QLabel + CSS
的形式也许会产生延迟,不利于高刷新的游戏场合。对于保持形状的图形,可以脱离刷新频率的限制,只绘制一次。
RaceGame
游戏并不涉及巨大的绘制开销,使用 QLabel + CSS
的形式可以满足需求。
二、 class DrawPlayer
DrawGame
的派生类,用于绘制玩家。
创建对象初始化的时候需要传递一个 Player
对象指针,用于绘制玩家。还需要传递一个绘制的父窗口,我直接在主界面中绘制。
class DrawPlayer : public DrawGame { public: DrawPlayer(std::shared_ptr<Player> player, QWidget * parent); private: QLabel * label; std::shared_ptr<Player> ptr; public: static const QList<QString> playersColor; void draw() const override; void destoryDraw() const override; };
因为玩家每一帧都在移动,位置不断在变化,因此在每一帧玩家位置变化之后,都会调用这个类的 draw()
方法。 在 Player
类族中的 玩家移动 playersMove
类中,也管理着绘制的工具,因此绘制玩家是每一帧都在调用的。
每一个玩家对应着一个绘制类,对应一个 QLabel
标签,QLabel * label
创建一次即可,不需要重复销毁创建,每一帧改变 label 的位置即可。
三、 class DrawMap
DrawGame
的派生类,用于绘制地图/墙体。
class DrawMap : public DrawGame { public: DrawMap(QWidget * parent); private: std::shared_ptr<GameMap> ptr; static std::array<std::array<QLabel *, MapHeight>, MapWidth> mapLabels; static const QList<QString> mapColorList; public: void draw() const override; static void draw_a_wall(char x, char y); void destoryDraw() const override; };
具有一个指向 GameMap
对象的指针。地图信息储存在一个 45 * 80 的二维 char
类型矩阵中, char
储存着 wallLevel
信息,根据这些信息绘制不同颜色、形状的墙体。
四、 class DrawManager
抽象类,绘制管理器,使用单例设计模式,把 DrawPlayer
和 DrawMap
的对象储存在管理器的共享指针中,直接使用 管理器绘制游戏界面。
// sinleton class DrawManager { private: QWidget * parent; static std::shared_ptr<DrawManager> drawMgr; DrawManager(); public: QList<std::shared_ptr<DrawPlayer>> drawPlayerList; std::shared_ptr<DrawMap> drawMap; void createDrawing(); void destoryDraw(); void setParent(QWidget * p); static std::shared_ptr<DrawManager> getInstance(); };
本文作者:北纬31是条纬线哦
本文链接:https://www.cnblogs.com/beiwei31/p/18663030
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步