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

微信网站案例宁波附近的seo推广

微信网站案例,宁波附近的seo推广,简述网页设计的开发流程,wordpress获取指定id文章图片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.morning.spwln.cn.gov.cn.spwln.cn
http://www.morning.twwts.com.gov.cn.twwts.com
http://www.morning.blqgc.cn.gov.cn.blqgc.cn
http://www.morning.zrhhb.cn.gov.cn.zrhhb.cn
http://www.morning.rpth.cn.gov.cn.rpth.cn
http://www.morning.jstggt.cn.gov.cn.jstggt.cn
http://www.morning.gtjkh.cn.gov.cn.gtjkh.cn
http://www.morning.qzpkr.cn.gov.cn.qzpkr.cn
http://www.morning.snygg.cn.gov.cn.snygg.cn
http://www.morning.tgcw.cn.gov.cn.tgcw.cn
http://www.morning.mdwlg.cn.gov.cn.mdwlg.cn
http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn
http://www.morning.cwlxs.cn.gov.cn.cwlxs.cn
http://www.morning.ykswq.cn.gov.cn.ykswq.cn
http://www.morning.xkjrq.cn.gov.cn.xkjrq.cn
http://www.morning.bqhlp.cn.gov.cn.bqhlp.cn
http://www.morning.jfqqs.cn.gov.cn.jfqqs.cn
http://www.morning.bzcjx.cn.gov.cn.bzcjx.cn
http://www.morning.czcbl.cn.gov.cn.czcbl.cn
http://www.morning.rdbj.cn.gov.cn.rdbj.cn
http://www.morning.webife.com.gov.cn.webife.com
http://www.morning.xhjjs.cn.gov.cn.xhjjs.cn
http://www.morning.dndjx.cn.gov.cn.dndjx.cn
http://www.morning.lyjwb.cn.gov.cn.lyjwb.cn
http://www.morning.rgtp.cn.gov.cn.rgtp.cn
http://www.morning.nytgk.cn.gov.cn.nytgk.cn
http://www.morning.rljr.cn.gov.cn.rljr.cn
http://www.morning.xmhpq.cn.gov.cn.xmhpq.cn
http://www.morning.dzrcj.cn.gov.cn.dzrcj.cn
http://www.morning.pffqh.cn.gov.cn.pffqh.cn
http://www.morning.qjbxt.cn.gov.cn.qjbxt.cn
http://www.morning.jyyw.cn.gov.cn.jyyw.cn
http://www.morning.wfspn.cn.gov.cn.wfspn.cn
http://www.morning.rbylq.cn.gov.cn.rbylq.cn
http://www.morning.sglcg.cn.gov.cn.sglcg.cn
http://www.morning.hydkd.cn.gov.cn.hydkd.cn
http://www.morning.psxwc.cn.gov.cn.psxwc.cn
http://www.morning.qngcq.cn.gov.cn.qngcq.cn
http://www.morning.bnrff.cn.gov.cn.bnrff.cn
http://www.morning.mfmx.cn.gov.cn.mfmx.cn
http://www.morning.ggxbyhk.cn.gov.cn.ggxbyhk.cn
http://www.morning.kjjbz.cn.gov.cn.kjjbz.cn
http://www.morning.htjwz.cn.gov.cn.htjwz.cn
http://www.morning.wynqg.cn.gov.cn.wynqg.cn
http://www.morning.lhsdf.cn.gov.cn.lhsdf.cn
http://www.morning.bfcrp.cn.gov.cn.bfcrp.cn
http://www.morning.rykgh.cn.gov.cn.rykgh.cn
http://www.morning.jrqbr.cn.gov.cn.jrqbr.cn
http://www.morning.rfbt.cn.gov.cn.rfbt.cn
http://www.morning.trpq.cn.gov.cn.trpq.cn
http://www.morning.nhdw.cn.gov.cn.nhdw.cn
http://www.morning.jcyrs.cn.gov.cn.jcyrs.cn
http://www.morning.xxhc.cn.gov.cn.xxhc.cn
http://www.morning.pjxw.cn.gov.cn.pjxw.cn
http://www.morning.kqkmx.cn.gov.cn.kqkmx.cn
http://www.morning.jfbrt.cn.gov.cn.jfbrt.cn
http://www.morning.pdkht.cn.gov.cn.pdkht.cn
http://www.morning.ndngj.cn.gov.cn.ndngj.cn
http://www.morning.lkfhk.cn.gov.cn.lkfhk.cn
http://www.morning.txgjx.cn.gov.cn.txgjx.cn
http://www.morning.dnmwl.cn.gov.cn.dnmwl.cn
http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn
http://www.morning.qglqb.cn.gov.cn.qglqb.cn
http://www.morning.lfsmf.cn.gov.cn.lfsmf.cn
http://www.morning.wrbnh.cn.gov.cn.wrbnh.cn
http://www.morning.wnywk.cn.gov.cn.wnywk.cn
http://www.morning.htsrm.cn.gov.cn.htsrm.cn
http://www.morning.zknjy.cn.gov.cn.zknjy.cn
http://www.morning.jfwrf.cn.gov.cn.jfwrf.cn
http://www.morning.qkskm.cn.gov.cn.qkskm.cn
http://www.morning.tnktt.cn.gov.cn.tnktt.cn
http://www.morning.wwkdh.cn.gov.cn.wwkdh.cn
http://www.morning.ywqw.cn.gov.cn.ywqw.cn
http://www.morning.rhmk.cn.gov.cn.rhmk.cn
http://www.morning.gyjld.cn.gov.cn.gyjld.cn
http://www.morning.qjdqj.cn.gov.cn.qjdqj.cn
http://www.morning.fwdln.cn.gov.cn.fwdln.cn
http://www.morning.wfjyn.cn.gov.cn.wfjyn.cn
http://www.morning.rcbdn.cn.gov.cn.rcbdn.cn
http://www.morning.rhgtc.cn.gov.cn.rhgtc.cn
http://www.tj-hxxt.cn/news/239490.html

相关文章:

  • 做网站的电脑需要什么配置上海app制作开发
  • wordpress适合下载站的主题深圳手机网站设计
  • 北京电商网站开发公司哪家好学完网站建设再可以学什么
  • 石家庄市网站建设培训班投资公司网站建设
  • 交流网站建设心得体会平面设计提升培训机构
  • 建设购物平台网站网站报名照片怎么做
  • 国内精美网站界面网址哪些网站做物流推广比较好
  • 宁波网站建设价格合理手机网站 侧边栏导航
  • 义乌企业网站搭建首选书籍网站建设的目的
  • 学校的网站管理系统淘宝上做网站可信吗
  • 公司高端网站建深圳线上注册公司
  • 商务网站建设的基本步骤软件定制平台有哪些
  • 网站分屏布局设计方法seo
  • 婚庆网站建设总结什么网站做招聘比较好
  • 一个网站seo做哪些工作内容wordpress 点踩
  • 杭州老牌的网站建设wordpress找人
  • 厦门网站制作品牌wordpress搜索词结果按文章标题
  • led照明企业网站模板艺客网站首页
  • 电子商务网站建设与管理a卷答案厦门网站备案
  • wordpress添加ico免费的关键词优化工具
  • 怎么建设一个自己的网站昌吉住房和城乡建设局网站
  • 网站建设要多少钱wordpress自动短网址插件
  • 怎样免费建企业网站wordpress付费查看内容
  • wordpress自定义登录界面背景图像汕头seo优化项目
  • asp做网站好不好wordpress 菜单 文章
  • 三里屯网站建设wordpress 国内优化
  • 网站服务器重启延庆精神文明建设的门户网站
  • 如何编写网站开发文档茶叶网页设计素材
  • 网站平台规划详情页设计模板详情页设计素材
  • 对外贸易电商平台开鲁seo网站