当前位置: 首页 > news >正文

怎么做租房网站中国免费网站服务器

怎么做租房网站,中国免费网站服务器,本地wordpress模板编辑器,石家庄网站制作建设Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用#xff0c;我们需要自己搭框架首先创建一个QGame类作为框架#xff0c;这个基本框架里面应该有如下功能#xff1a;游戏初始化 void init(const QSize siez,const QString title);游戏反初始化(…Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用我们需要自己搭框架首先创建一个QGame类作为框架这个基本框架里面应该有如下功能游戏初始化 void init(const QSize siez,const QString title);游戏反初始化(清理) void clean();更新游戏 void update(int);渲染游戏 void render(QPainter* painter);游戏是否在运行 bool isRunning() const;退出游戏 void quit();运行游戏 void runGame();设置游戏帧率 void setFps(qreal fps);一个游戏肯定要在一个主循环里面在Qt中肯定不能使用死循环就得使用定时器了基本的变量 //控制游戏进行的变量bool m_isRunning false;//游戏的主循环QTimer* m_mainLoopTimerP{};//游戏帧率60帧qreal m_fps 1000 / 60;基本框架思路判断游戏是否运行中运行中的话需要连接定时器处理游戏更新于绘图然后开启定时器因为qt的绘图只能在事件中完成所以把渲染写在事件中即可在定时器中去调用父类的更新画面基本框架 QGame.h #ifndef QGAME_H_ #define QGAME_H_#include QWidget #include Qtimerclass QGame :public QWidget {Q_OBJECT public:QGame(QWidget* parent nullptr);~QGame();//游戏初始化void init(const QSize size, const QString title);//游戏反初始化void clean();//更新游戏站位符与父类的方法做区别void update(int);//渲染游戏void render(QPainter* painter);//游戏是否进行bool isRuning() const;//退出游戏void quit();//运行游戏void runGame();//设置游戏帧率void setFps(qreal fps);//获取游戏帧数的接口qreal fps() const { return m_fps; } protected:void paintEvent(QPaintEvent* ev) override; private://控制游戏进行的变量bool m_isRunning false;//游戏的主循环QTimer* m_mainLoopTimer{};//游戏帧率60帧qreal m_fps 1000 / 60; };#endifQGame.cpp #include QGame.h #include QApplication #include QPainter QGame::QGame(QWidget* parent) :QWidget(parent), m_mainLoopTimer(new QTimer) {} QGame::~QGame() {//清理clean(); } //游戏初始化 void QGame::init(const QSize size, const QString title) {//设置窗口固定大小setFixedSize(size);//设置标题setWindowTitle(title);//因为上面会有各种资源的初始化如果初始化失败那么m_isRunningfalse;游戏不继续运行了//初始化成功就为true m_isRunning true; } //游戏反初始化 void QGame::clean() { } //更新游戏 void QGame::update(int) { } //渲染游戏 void QGame::render(QPainter* painter) { } //游戏是否进行 bool QGame::isRuning() const {return true; } //退出游戏 void QGame::quit() {m_isRunning false; } //运行游戏 void QGame::runGame() { //显示窗口show();//连接定时器m_mainLoopTimer-callOnTimeout([](){//如果游戏没有在运行那么就结束游戏if (!isRuning()){m_mainLoopTimer-stop();qApp-quit();}//更新游戏,QGame的自定义updateupdate(0);//重绘,父类的updateQWidget::update();//测试游戏是否在进行qDebug() 游戏运行中;});//开始定时器设置游戏开启的帧数m_mainLoopTimer-start(m_fps); } //设置游戏帧率 void QGame::setFps(qreal fps) {m_fps fps; }//绘图事件 void QGame::paintEvent(QPaintEvent* ev) {//开启画家QPainter painter(this);//渲染游戏render(painter); }mian.cpp #include QApplication #include QGame.hint main(int argc,char* argv[]) {QApplication a(argc, argv);QGame game;game.init({ 600,600 }, 小瓜);game.runGame();return a.exec(); }运行结果游戏是在主循环中基本框架搭建完毕 构建精灵与实体类 实体类 新建一个Entity空类什么都不需要继承这个类里面可以存放各种实体我们统一称为精灵每一个精灵都会有一种状态例如是否死亡所以我们还需要存在一个类别用与判断实体类型。 private:bool m_active true;//实体是否是活动的int m_type 0;//实体类型那么这个实体被精灵继承的时候是需要更新释放渲染实体的所以这个实体类一定要有虚析构与纯虚方法不然子类可能释放不了造成内存泄漏 public:virtual ~Entity() {};//虚析构当子类继承重写的时候就可以释放子类的内存virtual void update() 0;//更新实体virtual void render(QPainter* painter);//渲染实体我们当前实体类中的方法可以设置状态的销毁与实体的类型到时候由一个统一的管理类去进行管理 //接口bool active()const { return m_active; }int type()const { return m_type; }//状态销毁void destory() { m_active false; }//设置实体类型void setType(int type) { m_type type; }Entity.h #ifndef ENTITY_H_ #define ENTITY_H_#include QPainterclass Entity { public:virtual ~Entity() {};//虚析构当子类继承重写的时候就可以释放子类的内存virtual void update() 0;//更新实体virtual void render(QPainter* painter) 0;//渲染实体//接口bool active()const { return m_active; }int type()const { return m_type; }//状态销毁void destroy() { m_active false; }//设置实体类型void setType(int type) { m_type type; }private:bool m_active true;//精灵是否是活动的int m_type 0;//精灵类型}; #endif // !ENTITY_H_精灵类 新建一个精灵类这个类需要重写Entity的纯虚方法这个类拥有设置坐标与加载图片的方法 private:QPixmap m_image;QVector2D m_pos;设置图片 //设置图片 void setPixmap(const QString fileName, const QSize size QSize());设置坐标 //设置坐标 void setPos(float x, float y) {m_pos { x,y }; }Sprite.h #ifndef SPRITE_H_ #define SPRITE_H_#include Entity.h #include QVector2Dclass Sprite :public Entity { public:Sprite() default;Sprite(const QString fileName, const QSize size QSize());//接口QVector2D getPos()const { return m_pos; }QPixmap getPixmap()const { return m_image; }//设置坐标void setPos(float x, float y){m_pos { x,y };}//设置图片void setPixmap(const QString fileName, const QSize size QSize());// 通过 Entity 继承void update() override;// 通过 Entity 继承void render(QPainter* painter) override;private:QPixmap m_image;QVector2D m_pos; }; #endif // !SPRITE_H_Sprite.cpp #include Sprite.hSprite::Sprite(const QString fileName, const QSize size) {setPixmap(fileName, size); } //设置图片 void Sprite::setPixmap(const QString fileName, const QSize size) {m_image.load(fileName);if (size.isValid()){//保持缩放 m_image.scaled(size, Qt::AspectRatioMode::KeepAspectRatio);} }void Sprite::update() { }void Sprite::render(QPainter* painter) {painter-drawPixmap(m_pos.toPoint(), m_image); }QGame.cpp 在QGame.cpp中声明一个全局的精灵类然后去初始化精灵 #include QGame.h #include Sprite.h #include QApplication #include QPainterQGame::QGame(QWidget* parent) :QWidget(parent), m_mainLoopTimer(new QTimer) {} QGame::~QGame() {//清理clean(); }//全局精灵类,注意这里必须使用指针类如果是普通类对象会报错 //因为QT里面QApplication执行后是不允许对象还没有构造完的指针是个不完整类就不会默认构造 Sprite* player;//游戏初始化 void QGame::init(const QSize size, const QString title) {//设置窗口固定大小setFixedSize(size);//设置标题setWindowTitle(title);player new Sprite;player-setPixmap(:/plane/Resource/images/hero1.png);//因为上面会有各种资源的初始化如果初始化失败那么m_isRunningfalse;游戏不继续运行了//初始化成功就为true m_isRunning true; } //游戏反初始化 void QGame::clean() { } //更新游戏 void QGame::update(int) {player-update(); } //渲染游戏 void QGame::render(QPainter* painter) {player-render(painter); } //游戏是否进行 bool QGame::isRuning() const {return true; } //退出游戏 void QGame::quit() {m_isRunning false; } //运行游戏 void QGame::runGame() { //显示窗口show();//连接定时器m_mainLoopTimer-callOnTimeout([](){//如果游戏没有在运行那么就结束游戏if (!isRuning()){m_mainLoopTimer-stop();qApp-quit();}//更新游戏,QGame的自定义updateupdate(0);//重绘,父类的updateQWidget::update();//测试游戏是否在进行qDebug() 游戏运行中;});//开始定时器设置游戏开启的帧数m_mainLoopTimer-start(m_fps); } //设置游戏帧率 void QGame::setFps(qreal fps) {m_fps fps; }//绘图事件 void QGame::paintEvent(QPaintEvent* ev) {//开启画家QPainter painter(this);//渲染游戏render(painter); }运行结果 精灵移动 毫无疑问我们需要让精灵动起来那肯定得使用事件去调用采用两种方式去移动精灵键盘事件和鼠标事件使用键盘事件的时候我们需要知道一个知识点我们采用分量概念去乘上速度来达到效果 Sprite.h中 public:Sprite() default; Sprite(const QString fileName, const QSize size QSize());//接口 QVector2D getPos()const { return m_pos; } QPixmap getPixmap()const { return m_image; } QVector2D velocity() const{ return m_velocity; } QVector2D velocity() { return m_velocity; } private //移动速度 float m_speed 3; //速度分量 QVector2D m_velocity; ----------------------------------------------------------------- Sprite.cpp中 void Sprite::update() {//获取一下坐标float x m_pos.x();float y m_pos.y();//通过分量去改变坐标的速度移动就比较正常一点x m_velocity.x() * m_speed;y m_velocity.y() * m_speed;//将坐标给m_posm_pos { x,y }; }QGame.h protected:void paintEvent(QPaintEvent* ev) override;void keyPressEvent(QKeyEvent* ev) override;void keyReleaseEvent(QKeyEvent* ev) override;void mouseMoveEvent(QMouseEvent* ev) override;QGame.cpp //捕获按键事件 void QGame::keyPressEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:player-velocity().setY(-1);break;case Qt::Key_Down:player-velocity().setY(1);break;case Qt::Key_Left:player-velocity().setX(-1);break;case Qt::Key_Right:player-velocity().setX(1);break;} }void QGame::keyReleaseEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:case Qt::Key_Down:player-velocity().setY(0);break;case Qt::Key_Left:case Qt::Key_Right:player-velocity().setX(0);break;} }void QGame::mouseMoveEvent(QMouseEvent* ev) {//让鼠标居中到图片中间auto pos player-sizeImage() / 2;player-setPos(ev-pos() - QPoint{ pos.width(),pos.height() }); }子弹类飞机类与单例设计模式 构造两个类一个子弹类一个飞机类为了在这些类里面能使用QGame的实例我们设计一个单例设计模式让QGame实例唯一存在 QGame.h #ifndef QGAME_H_ #define QGAME_H_ #include QWidget #include Qtimer //宏定义一下这个单例 #define qGame QGame::instance()class QGame :public QWidget {Q_OBJECT public://单例设计模式,让QGame实例只允许存在一个static QGame* instance();QGame(QWidget* parent nullptr);~QGame();//游戏初始化void init(const QSize size, const QString title);//游戏反初始化void clean();//更新游戏站位符与父类的方法做区别void update(int);//渲染游戏void render(QPainter* painter);//游戏是否进行bool isRuning() const;//退出游戏void quit();//运行游戏void runGame();//设置游戏帧率void setFps(qreal fps);//获取游戏帧数的接口qreal fps() const { return m_fps; } protected:void paintEvent(QPaintEvent* ev) override;void keyPressEvent(QKeyEvent* ev) override;void keyReleaseEvent(QKeyEvent* ev) override;void mouseMoveEvent(QMouseEvent* ev) override; private://控制游戏进行的变量bool m_isRunning false;//游戏的主循环QTimer* m_mainLoopTimer{};//游戏帧率60帧qreal m_fps 1000 / 60; };#endifQGame.cpp #include QGame.h #include Sprite.h #include QApplication #include QPainter #include QKeyEvent #include QMessageBox//定义一个静态指针指向唯一对象 static QGame* ins nullptr; QGame* QGame::instance() {return ins; }QGame::QGame(QWidget* parent) :QWidget(parent), m_mainLoopTimer(new QTimer) {//保证不存在调用多个QGame实例Q_ASSERT_X(ins nullptr, QGame, 已经存在一个QGame实例);ins this; } QGame::~QGame() {//清理clean(); }//全局精灵类,注意这里必须使用指针类如果是普通类对象会报错 //因为QT里面QApplication执行后是不允许对象还没有构造完的指针是个不完整类就不会默认构造 Sprite* player;//游戏初始化 void QGame::init(const QSize size, const QString title) {//设置窗口固定大小setFixedSize(size);//设置标题setWindowTitle(title);//开启鼠标自动追踪setMouseTracking(true);player new Sprite;player-setPixmap(:/plane/Resource/images/hero1.png);//因为上面会有各种资源的初始化如果初始化失败那么m_isRunningfalse;游戏不继续运行了//初始化成功就为true m_isRunning true; } //游戏反初始化 void QGame::clean() { } //更新游戏 void QGame::update(int) {player-update(); } //渲染游戏 void QGame::render(QPainter* painter) {player-render(painter); } //游戏是否进行 bool QGame::isRuning() const {return true; } //退出游戏 void QGame::quit() {m_isRunning false; } //运行游戏 void QGame::runGame() { //显示窗口show();//连接定时器m_mainLoopTimer-callOnTimeout([](){//如果游戏没有在运行那么就结束游戏if (!isRuning()){m_mainLoopTimer-stop();qApp-quit();}//更新游戏,QGame的自定义updateupdate(0);//重绘,父类的updateQWidget::update();//测试游戏是否在进行qDebug() 游戏运行中;});//开始定时器设置游戏开启的帧数m_mainLoopTimer-start(m_fps); } //设置游戏帧率 void QGame::setFps(qreal fps) {m_fps fps; }//绘图事件 void QGame::paintEvent(QPaintEvent* ev) {//开启画家QPainter painter(this);//渲染游戏render(painter); }//捕获按键事件 void QGame::keyPressEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:player-velocity().setY(-1);break;case Qt::Key_Down:player-velocity().setY(1);break;case Qt::Key_Left:player-velocity().setX(-1);break;case Qt::Key_Right:player-velocity().setX(1);break;} }void QGame::keyReleaseEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:case Qt::Key_Down:player-velocity().setY(0);break;case Qt::Key_Left:case Qt::Key_Right:player-velocity().setX(0);break;} }void QGame::mouseMoveEvent(QMouseEvent* ev) {//让鼠标居中到图片中间auto pos player-sizeImage() / 2;player-setPos(ev-pos() - QPoint{ pos.width(),pos.height() }); }PlayerPlane.h #ifndef PLAYERPLANE_H_ #define PLAYERPLANE_H_#include Sprite.h #include Bullet.h #include array class PlayerPlane : public Sprite { public:PlayerPlane();//发射子弹bool emitBullet(); private:}; #endif // !PLAYERPLANE_H_PlayerPlane.cpp #include PlayerPlane.hPlayerPlane::PlayerPlane() {}bool PlayerPlane::emitBullet() {return false; }Bullte.h #ifndef BULLET_H_ #define BULLET_H_#include Sprite.h class Bullet :public Sprite { public://更新子弹出边界就得消失void update() override; private:}; #endif // !BULLET_H_Bullte.cpp #include Bullet.h #include QGame.h void Bullet::update() {//父类方法帮忙移动Sprite::update();//就可以调用游戏唯一的单例//如果子弹超出边界让子弹消失if (getPos().x() qGame-width() || getPos().x() 0 - sizeImage().width() ||getPos().y() qGame-height() || getPos().y() 0 - sizeImage().height()){destroy();} } 精灵管理类 创建一个EntityManager类来管理所有的实体与精灵为这个类构造单例然后使用链表去管理存储所有的实体与精灵。主游戏里面的所有实体与精灵就可以通过EntityManger这个单例去完成操作 EntityManager.h #ifndef ENTITYMANAGER_H_ #define ENTITYMANAGER_H_#includeSprite.h #includeQList #includememory #includeQDebug class EntityManager { public://得到唯一的实例static EntityManager instance(){static EntityManager ev;return ev;}//更新管理的所有实体与精灵void update(){for (auto e : m_entities){e-update();}}//渲染void render(QPainter* painter){for (auto e : m_entities){e-render(painter);}}//添加实体开个模版方便使用templatetypename T EntityT* addEntity(T* e){m_entities.emplaceBack(e);return e;}//刷新如果有实体要消除就在这里销毁void refresh(){m_entities.removeIf([](Entity* e){if (!e-active()){//测试输出qDebug() destoryed e;//释放这个实体delete e;return true;}return false;});//测试输出qDebug() m_entities.size();}private:QListEntity* m_entities;//构造函数私有化设计单例EntityManager() {} }; #endif PlayerPlane.h #ifndef PLAYERPLANE_H_ #define PLAYERPLANE_H_#include Sprite.h #include Bullet.h #include array class PlayerPlane : public Sprite { public://继承父类的构造方法using Sprite::Sprite;PlayerPlane();//发射子弹bool emitBullet(); private:}; #endif // !PLAYERPLANE_H_此时的PlayerPlane.cpp就可以处理发射子弹了 #include PlayerPlane.h #include EntityManager.h PlayerPlane::PlayerPlane() {}bool PlayerPlane::emitBullet() {Bullet* b new Bullet;//添加子弹b-setPixmap(:/plane/Resource/images/bullet2.png);//设置子弹在主角上b-setPos(getPos() QVector2D{ sizeImage().width() / 2.0f,0.0f });//子弹发出b-velocity().setY(-1);//添加进实体EntityManager::instance().addEntity(b);return false; } QGame.cpp #include QGame.h #include Sprite.h #include EntityManager.h #include PlayerPlane.h#include QApplication #include QPainter #include QKeyEvent #include QMessageBox//定义一个静态指针指向唯一对象 static QGame* ins nullptr; QGame* QGame::instance() {return ins; }QGame::QGame(QWidget* parent) :QWidget(parent), m_mainLoopTimer(new QTimer) {//保证不存在调用多个QGame实例Q_ASSERT_X(ins nullptr, QGame, 已经存在一个QGame实例);ins this; } QGame::~QGame() {//清理clean(); }//全局精灵类,注意这里必须使用指针类如果是普通类对象会报错 //因为QT里面QApplication执行后是不允许对象还没有构造完的指针是个不完整类就不会默认构造 PlayerPlane* player;//游戏初始化 void QGame::init(const QSize size, const QString title) {//设置窗口固定大小setFixedSize(size);//设置标题setWindowTitle(title);//开启鼠标自动追踪setMouseTracking(true);player EntityManager::instance().addEntity(new PlayerPlane(:/plane/Resource/images/hero1.png));//因为上面会有各种资源的初始化如果初始化失败那么m_isRunningfalse;游戏不继续运行了//初始化成功就为true m_isRunning true; } //游戏反初始化 void QGame::clean() { } //更新游戏 void QGame::update(int) {//刷新销毁所有不需要的实体精灵EntityManager::instance().refresh();//更新实体精灵信息EntityManager::instance().update();//发射子弹player-emitBullet(); } //渲染游戏 void QGame::render(QPainter* painter) {EntityManager::instance().render(painter); } //游戏是否进行 bool QGame::isRuning() const {return true; } //退出游戏 void QGame::quit() {m_isRunning false; } //运行游戏 void QGame::runGame() { //显示窗口show();//连接定时器m_mainLoopTimer-callOnTimeout([](){//如果游戏没有在运行那么就结束游戏if (!isRuning()){m_mainLoopTimer-stop();qApp-quit();}//更新游戏,QGame的自定义updateupdate(0);//重绘,父类的updateQWidget::update();//测试游戏是否在进行//qDebug() 游戏运行中;});//开始定时器设置游戏开启的帧数m_mainLoopTimer-start(m_fps); } //设置游戏帧率 void QGame::setFps(qreal fps) {m_fps fps; }//绘图事件 void QGame::paintEvent(QPaintEvent* ev) {//开启画家QPainter painter(this);//渲染游戏render(painter); }//捕获按键事件 void QGame::keyPressEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:player-velocity().setY(-1);break;case Qt::Key_Down:player-velocity().setY(1);break;case Qt::Key_Left:player-velocity().setX(-1);break;case Qt::Key_Right:player-velocity().setX(1);break;} }void QGame::keyReleaseEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:case Qt::Key_Down:player-velocity().setY(0);break;case Qt::Key_Left:case Qt::Key_Right:player-velocity().setX(0);break;} }void QGame::mouseMoveEvent(QMouseEvent* ev) {//让鼠标居中到图片中间auto pos player-sizeImage() / 2;player-setPos(ev-pos() - QPoint{ pos.width(),pos.height() }); } 背景图滚动 思路因为沿着y轴移动用两个变量来表示图片不同位置的y坐标然后一个位置在窗口上一个位置在窗口上方让两个变量一直自增实现滚动像素当窗口上的坐标大于窗口高度时就把窗口上的y坐标重置为0当窗口之上的坐标大于0时就把y坐标重置为一开始的窗口之上的坐标 Map::Map() {//加载背景图m_pixmap.load(:/plane/Resource/images/background.png);//一个在窗口上面yPos1 -m_pixmap.height();//一个在窗口上yPos2 0; } void Map::update() {//实现滚动背景yPos1 m_scrollSpeed;if (yPos1 0){yPos1 -m_pixmap.height();}yPos2 m_scrollSpeed;//大于等于窗口高度后重新置为0if (yPos2 qGame-height()){yPos2 0;} } void Map::render(QPainter* painter) {painter-drawPixmap(0, yPos1, m_pixmap);painter-drawPixmap(0, yPos2, m_pixmap); }新建地图类继承实体类然后去重写渲染与更新方法 Map.h #ifndef MAP_H_ #define MAP_H_#include Entity.h class Map :public Entity { public:Map();// 通过 Entity 继承virtual void update() override;virtual void render(QPainter* painter) override; private:QPixmap m_pixmap;//用来实现滚动int yPos1,yPos2;int m_scrollSpeed 2; }; #endif // !MAP_H_ Map.cpp #include Map.h #include QGame.h Map::Map() {//加载背景图m_pixmap.load(:/plane/Resource/images/background.png);//一个在窗口上面yPos1 -m_pixmap.height();//一个在窗口上yPos2 0; }void Map::update() {//实现滚动背景yPos1 m_scrollSpeed;if (yPos1 0){yPos1 -m_pixmap.height();}yPos2 m_scrollSpeed;//大于等于窗口高度后重新置为0if (yPos2 qGame-height()){yPos2 0;} }void Map::render(QPainter* painter) {painter-drawPixmap(0, yPos1, m_pixmap);painter-drawPixmap(0, yPos2, m_pixmap); }子弹与敌机碰撞 新建一个类用来存放应该enumenum里面存放不同类别标识现在就需要在子弹player敌机生成的时候设置类别方便后面进行碰撞判断在EntityManager中提供类别识别方法注意识别类型要是活动的不然就没意义在Sprite中构造矩阵变量在update方法中添加矩阵的构造采用矩阵碰撞方式去检测碰撞最后在QGame.cpp中去完成敌机的生成与碰撞。基本完整框架如下 main.cpp #include QApplication #include QGame.hint main(int argc,char* argv[]) {QApplication a(argc, argv);QGame game;game.init({ 480,852 }, 小瓜);game.runGame();return a.exec(); }QGame.h #ifndef QGAME_H_ #define QGAME_H_ #include QWidget #include Qtimer //宏定义一下这个单例 #define qGame QGame::instance()class QGame :public QWidget {Q_OBJECT public://单例设计模式,让QGame实例只允许存在一个static QGame* instance();QGame(QWidget* parent nullptr);~QGame();//游戏初始化void init(const QSize size, const QString title);//游戏反初始化void clean();//更新游戏站位符与父类的方法做区别void update(int);//渲染游戏void render(QPainter* painter);//游戏是否进行bool isRuning() const;//退出游戏void quit();//运行游戏void runGame();//设置游戏帧率void setFps(qreal fps);//获取游戏帧数的接口qreal fps() const { return m_fps; } protected:void paintEvent(QPaintEvent* ev) override;void keyPressEvent(QKeyEvent* ev) override;void keyReleaseEvent(QKeyEvent* ev) override;void mouseMoveEvent(QMouseEvent* ev) override; private://控制游戏进行的变量bool m_isRunning false;//游戏的主循环QTimer* m_mainLoopTimer{};//游戏帧率60帧qreal m_fps 1000 / 60; };#endifQGame.cpp #include QGame.h #include Sprite.h #include EntityManager.h #include PlayerPlane.h #include Map.h#include QApplication #include QPainter #include QKeyEvent #include QMessageBox #include QStringList //随机数头文件 #include qrandom.h//宏定义这个随机生成器函数 #define qRand(min,max) QRandomGenerator::global()-bounded(min, max)//定义一个静态指针指向唯一对象 static QGame* ins nullptr; QGame* QGame::instance() {return ins; }QGame::QGame(QWidget* parent) :QWidget(parent), m_mainLoopTimer(new QTimer) {//保证不存在调用多个QGame实例Q_ASSERT_X(ins nullptr, QGame, 已经存在一个QGame实例);ins this; } QGame::~QGame() {//清理clean(); }//全局精灵类,注意这里必须使用指针类如果是普通类对象会报错 //因为QT里面QApplication执行后是不允许对象还没有构造完的指针是个不完整类就不会默认构造 PlayerPlane* player;//游戏初始化 void QGame::init(const QSize size, const QString title) {//设置窗口固定大小setFixedSize(size);//设置标题setWindowTitle(title);//开启鼠标自动追踪setMouseTracking(true);//初始化背景EntityManager::instance().addEntity(new Map);//初始化主角对象player EntityManager::instance().addEntity(new PlayerPlane(:/plane/Resource/images/hero1.png));player-setType(Player);//因为上面会有各种资源的初始化如果初始化失败那么m_isRunningfalse;游戏不继续运行了//初始化成功就为true m_isRunning true; } //游戏反初始化 void QGame::clean() { } //更新游戏 void QGame::update(int) {//刷新销毁所有不需要的实体精灵EntityManager::instance().refresh();//更新实体精灵信息EntityManager::instance().update();static int BulletVelocity 0;//发射子弹的速率if (BulletVelocity % 10 0){//发射子弹player-emitBullet();}//出现敌机if (BulletVelocity % 60 0){QStringList efile { :/plane/Resource/images/enemy1.png,:/plane/Resource/images/enemy2.png };auto enemy new Sprite(efile[qRand(0,2)]);//设置敌机从上面往下enemy-velocity().setY(1);//设置随机出现的敌机位置enemy-setPos(qRand(0, width()), -50);//设置类别enemy-setType(Enemy);//添加到精灵管理类中EntityManager::instance().addEntity(enemy);}//获取子弹列表auto bullet_list EntityManager::instance().getSpriteByType(bullet);//获取敌机列表auto enemy_list EntityManager::instance().getSpriteByType(Enemy);//遍历查看是否矩形碰撞for (auto e : enemy_list){for (auto b : bullet_list){//判断敌机是否包含子弹如果包含就释放掉子弹和敌机if (e-collider().intersects(b-collider())){e-destroy();b-destroy();break;}}}BulletVelocity;qDebug() 时间值 BulletVelocity; } //渲染游戏 void QGame::render(QPainter* painter) {EntityManager::instance().render(painter); } //游戏是否进行 bool QGame::isRuning() const {return true; } //退出游戏 void QGame::quit() {m_isRunning false; } //运行游戏 void QGame::runGame() { //显示窗口show();//连接定时器m_mainLoopTimer-callOnTimeout([](){//如果游戏没有在运行那么就结束游戏if (!isRuning()){m_mainLoopTimer-stop();qApp-quit();}//更新游戏,QGame的自定义updateupdate(0);//重绘,父类的updateQWidget::update();//测试游戏是否在进行//qDebug() 游戏运行中;});//开始定时器设置游戏开启的帧数m_mainLoopTimer-start(m_fps); } //设置游戏帧率 void QGame::setFps(qreal fps) {m_fps fps; }//绘图事件 void QGame::paintEvent(QPaintEvent* ev) {//开启画家QPainter painter(this);//渲染游戏render(painter); }//捕获按键事件 void QGame::keyPressEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:player-velocity().setY(-1);break;case Qt::Key_Down:player-velocity().setY(1);break;case Qt::Key_Left:player-velocity().setX(-1);break;case Qt::Key_Right:player-velocity().setX(1);break;} }void QGame::keyReleaseEvent(QKeyEvent* ev) {switch (ev-key()){case Qt::Key_Up:case Qt::Key_Down:player-velocity().setY(0);break;case Qt::Key_Left:case Qt::Key_Right:player-velocity().setX(0);break;} }void QGame::mouseMoveEvent(QMouseEvent* ev) {//让鼠标居中到图片中间auto pos player-sizeImage() / 2;player-setPos(ev-pos() - QPoint{ pos.width(),pos.height() }); }Entity.h #ifndef ENTITY_H_ #define ENTITY_H_#include Global.h #include QPainterclass Entity { public:virtual ~Entity() {};//虚析构当子类继承重写的时候就可以释放子类的内存virtual void update() 0;//更新实体virtual void render(QPainter* painter) 0;//渲染实体//接口bool active()const { return m_active; }int type()const { return m_type; }//状态销毁void destroy() { m_active false; }//设置实体类型void setType(int type) { m_type type; } private:bool m_active true;//实体是否是活动的int m_type 0;//实体类型}; #endif // !ENTITY_H_Sprite.h #ifndef SPRITE_H_ #define SPRITE_H_#include Entity.h #include QVector2Dclass Sprite :public Entity { public:Sprite() default;Sprite(const QString fileName, const QSize size QSize());//接口QVector2D getPos()const { return m_pos; }QPixmap getPixmap()const { return m_image; }QVector2D velocity() const{ return m_velocity; }QVector2D velocity() { return m_velocity; }QRect collider()const { return m_collider; }//设置坐标void setPos(float x, float y){m_pos { x,y };}void setPos(const QPointF pos){m_pos { (float)pos.x(),(float)pos.y() };}void setPos(const QVector2D pos) {m_pos pos; }//设置速度分量void setVelocity(float vx, float vy){m_velocity { vx,vy };}//获取图片大小QSize sizeImage()const;//设置图片void setPixmap(const QString fileName, const QSize size QSize());// 通过 Entity 继承void update() override;// 通过 Entity 继承void render(QPainter* painter) override;private:QPixmap m_image;QVector2D m_pos;//移动速度float m_speed 3;//速度分量QVector2D m_velocity;//碰撞器QRect m_collider{}; }; #endif // !SPRITE_H_ Sprite.cpp #include Sprite.hSprite::Sprite(const QString fileName, const QSize size) {setPixmap(fileName, size); }//获取精灵图片大小 QSize Sprite::sizeImage() const {if (m_image.isNull()){return QSize();}return m_image.size(); } //设置图片 void Sprite::setPixmap(const QString fileName, const QSize size) {m_image.load(fileName);if (size.isValid()){//保持缩放 m_image.scaled(size, Qt::AspectRatioMode::KeepAspectRatio);} }void Sprite::update() {//获取一下坐标float x m_pos.x();float y m_pos.y();//通过分量去改变坐标的速度移动就比较正常一点x m_velocity.x() * m_speed;y m_velocity.y() * m_speed;//将坐标给m_posm_pos { x,y };//设置矩形m_collider QRect(m_pos.x(), m_pos.y(), m_image.width(), m_image.height()); }void Sprite::render(QPainter* painter) {painter-drawPixmap(m_pos.toPoint(), m_image); }Bullet.h #ifndef BULLET_H_ #define BULLET_H_#include Sprite.h class Bullet :public Sprite { public://更新子弹出边界就得消失void update() override; private:}; #endif // !BULLET_H_ Bullet.cpp #include Bullet.h #include QGame.h void Bullet::update() {//继承父类的方法帮忙移动Sprite::update();//就可以调用游戏唯一的单例//如果子弹超出边界让子弹消失if (getPos().x() qGame-width() || getPos().x() 0 - sizeImage().width() ||getPos().y() qGame-height() || getPos().y() 0 - sizeImage().height()){destroy();} }PlayerPlane.h #ifndef PLAYERPLANE_H_ #define PLAYERPLANE_H_#include Sprite.h #include Bullet.h #include array class PlayerPlane : public Sprite { public://继承父类的构造方法using Sprite::Sprite;PlayerPlane();//发射子弹bool emitBullet(); private:}; #endif // !PLAYERPLANE_H_ PlayerPlane.cpp #include PlayerPlane.h #include EntityManager.h PlayerPlane::PlayerPlane() {}bool PlayerPlane::emitBullet() {Bullet* b new Bullet;//添加子弹b-setPixmap(:/plane/Resource/images/bullet2.png);//设置子弹在主角上b-setPos(getPos() QVector2D{ sizeImage().width() / 2.0f,0.0f });//子弹发出b-velocity().setY(-2);//设置类型b-setType(bullet);//添加进实体EntityManager::instance().addEntity(b);return false; }EntityManager.h #ifndef ENTITYMANAGER_H_ #define ENTITYMANAGER_H_#includeSprite.h #includeQList #includememory #includeQDebug class EntityManager { public://得到唯一的实例static EntityManager instance(){static EntityManager ev;return ev;}//更新管理的所有实体与精灵void update(){for (auto e : m_entities){e-update();}}//渲染void render(QPainter* painter){for (auto e : m_entities){e-render(painter);}}//添加实体开个模版方便使用templatetypename T EntityT* addEntity(T* e){m_entities.emplaceBack(e);return e;}//刷新如果有实体要消除就在这里销毁void refresh(){m_entities.removeIf([](Entity* e){//不是活动的就释放if (!e-active()){//测试输出qDebug() destoryed e;//释放这个实体delete e;return true;}return false;});//测试输出qDebug() m_entities.size();}//获取类别好做碰撞QListSprite* getSpriteByType(int type){QListSprite* s;for (auto e : m_entities){//要是活动的if(e-type()type e-active()){s.append(dynamic_castSprite*(e));}}return s;} private:QListEntity* m_entities;//构造函数私有化设计单例EntityManager() {} };#endifMap.h #ifndef MAP_H_ #define MAP_H_#include Entity.h class Map :public Entity { public:Map();// 通过 Entity 继承virtual void update() override;virtual void render(QPainter* painter) override; private:QPixmap m_pixmap;//用来实现滚动int yPos1,yPos2;int m_scrollSpeed 2; }; #endif // !MAP_H_ Map.cpp #include Map.h #include QGame.h Map::Map() {//加载背景图m_pixmap.load(:/plane/Resource/images/background.png);//一个在窗口上面yPos1 -m_pixmap.height();//一个在窗口上yPos2 0; }void Map::update() {//实现滚动背景yPos1 m_scrollSpeed;if (yPos1 0){yPos1 -m_pixmap.height();}yPos2 m_scrollSpeed;//大于等于窗口高度后重新置为0if (yPos2 qGame-height()){yPos2 0;} }void Map::render(QPainter* painter) {painter-drawPixmap(0, yPos1, m_pixmap);painter-drawPixmap(0, yPos2, m_pixmap); } Global.h #ifndef GLOBAL_H_ #define GLOBAL_H_enum EntityType {None,Player,Enemy,bullet };#endif运行结果
http://www.dnsts.com.cn/news/261173.html

相关文章:

  • 做视频网站视频存放问题python18+21
  • 鄂州网站制作中天建设集团山西分公司网站
  • ae模板免费下载网站有哪些软件开发项目管理系统
  • 网站的后台地址梧州网站建设
  • php做的网站怎么运行浙江大学陈越做的刷题网站
  • 网站建设在国内外研究现状php 深圳 电子商务网站开发
  • 做铝锭的网站郑州seo联系搜点网络效果好
  • 如何做网站ip跳转asp网站知道用户名是admin
  • 中卫企业管理培训网站动易网站管理系统下载
  • 购物网站怎么创建百度竞价关键词质量度怎么提升
  • 厦门企业建网站制作网站开发的数据库设计实体是什么
  • 有域名了如何建设网站今晚比赛预测比分
  • 做新闻封面的网站微网站 无锡
  • 新手做电影网站好wordpress显示文章点击量
  • 建设银行租房网站湖北用什么软件做公司网站
  • 烟台网站建设设计开发网站建设技术哪些内容
  • 网站的推广方式wordpress 插件写
  • 电影网站做cpa旅游网站怎么设计
  • 办公门户网站模板下载网站及建设中页面
  • 富平做网站办公室设计说明
  • 企业建网站一般要多少钱阳朔到桂林大巴时刻表
  • 2017网站备案抽查佛山网站建设首页排名
  • 网站系统哪个网站可以做付费推广
  • 虹口 教育 网站建设中国有限公司官网
  • 犀牛云做的网站好不好北京市建设工程审核网站
  • 网站开发是前端还是后台wordpress对话框模板
  • 公司网站建设公司局网站建设管理整改情况
  • 网站怎么做才能赚钱吗郑州网站怎么推广
  • 网站建设收费标准不一广东品牌网站设计
  • 无锡高端网站建设开发seo分析及优化建议