QT./代表的当前目录位置 项目结构 效果图 GameMap.h #ifndef GAMEMAP_H #define GAMEMAP_H #include <QObject> #include <QPainter> enum MapElement { Road, Wall, Box, Point, InPoint }; ...
QT./代表的当前目录位置 项目结构 效果图 GameMap.h
#ifndef GAMEMAP_H
#define GAMEMAP_H
#include <QObject>
#include <QPainter>
enum MapElement
{
Road,
Wall,
Box,
Point,
InPoint
};
class GameMap : public QObject
{
Q_OBJECT
public:
explicit GameMap(QObject *parent = nullptr);
~GameMap();
bool InitByFile(QString fileName);
void Clear();
void Paint(QPainter* _p,QPoint _Pos);
int mRow;
int mCol;
int** mPArr;//用于开辟二维数组 2D地图元素
signals:
public slots:
};
#endif // GAMEMAP_H
GameMap.cpp
#include "GameMap.h"
#include <QFile>
#include <QDebug>
GameMap::GameMap(QObject *parent) : QObject(parent)
{
mRow = 0;
mCol = 0;
mPArr = nullptr;
}
GameMap::~GameMap()
{
Clear();
}
void GameMap::Clear()
{
if(mPArr != nullptr)
{
for(int i = 0;i < mRow;i++)
{
delete[] mPArr[i];
}
delete[] mPArr;
}
}
bool GameMap::InitByFile(QString fileName)
{
QFile file(fileName);//创建文件对象
if(!file.open(QIODevice::ReadOnly))
{
return false;//打开失败
}
//读取所有内容
QByteArray arrAll = file.readAll();
arrAll.replace("\r\n","\n");//将 "\r\n" 替换成 “\n”
QList<QByteArray> lineList = arrAll.split('\n');//以“\n” 分割子串
mRow = lineList.size();//确定行
mPArr = new int*[mRow];
for(int i = 0;i < mRow;i++)
{
QList<QByteArray> colList = lineList[i].split(',');
mCol = colList.size();//确定列
mPArr[i] = new int[mCol];//开辟列
for(int j = 0;j < mCol;j++)//遍历列
{
mPArr[i][j] = colList[j].toInt();
}
}
}
void GameMap::Paint(QPainter* _p, QPoint _Pos)
{
for(int i = 0;i <mRow;i++)
{
for(int j = 0;j < mCol;j++)
{
QString imgUrl;
switch (mPArr[i][j])
{
case Road: imgUrl = "://Image/sky.png";break;
case Wall: imgUrl = "://Image/wall.png";break;
case Box: imgUrl = "://Image/case.png";break;
case Point: imgUrl = "://Image/end.png";break;
case InPoint: imgUrl = "://Image/win.png";break;
}
QImage img(imgUrl);
_p->drawImage(QRect(_Pos.x() + j*img.width(),_Pos.y() +i*img.height(),img.width(),img.height()),img);
// _p->drawImage(_Pos,img);
}
}
}
Role.h
#ifndef ROLE_H
#define ROLE_H
#include <QObject>
#include <QPoint>
#include <QImage>
class Role : public QObject
{
Q_OBJECT
public:
explicit Role(QObject *parent = nullptr);
//对应在地图的映射行列
int mRow;
int mCol;
//画图位置
//人在二维数组里的x,y和显示的x,y坐标轴是反过来的
QPoint mPaintPos;
//人物图片
QImage mImg;
void Move(int _dRow,int _dCol);//移动函数
void Paint(QPainter* _p,QPoint _pos);//自己的绘制函数
signals:
public slots:
};
#endif // ROLE_H
Role.cpp
#include "Role.h"
#include <QPainter>
Role::Role(QObject *parent) : QObject(parent)
{
mRow = 1;
mCol = 1;
mImg = QImage("://Image/people.png");
//显示位置
mPaintPos = QPoint(mCol,mRow) * mImg.width();
}
void Role::Move(int _dRow,int _dCol)
{
mRow += _dRow;
mCol += _dCol;
mPaintPos = QPoint(mCol,mRow) * mImg.width();
}
void Role::Paint(QPainter* _p,QPoint _pos)
{
_p->drawImage(mPaintPos + _pos,mImg);
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "GameMap.h"
#include "Role.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
virtual void paintEvent(QPaintEvent* event);//绘图事件函数
virtual void keyPressEvent(QKeyEvent* event);//键盘按下事件
void Collision(int _dRow,int _dCol);
~Widget();
private:
Ui::Widget *ui;
GameMap* mPMap;
//画家
QPainter* mMapPainter;
//角色
Role* mRole;
//游戏更新定时器 解决paintEvent不定时更新问题
QTimer* mTimer;
};
#endif // WIDGET_H
Widget.cpp
#include "Widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QPainter>
#include <QMessageBox>
#include <QKeyEvent>
#include <QtDebug>
#include <QTimer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化地图元素
mPMap = new GameMap(this);
// QString fileName =QFileDialog::getOpenFileName(this,"打开地图","./","*.txt");
if(!mPMap->InitByFile("./Map/lv1.txt"))
{
QMessageBox::warning(this,"警告","文件打开失败");
}
mMapPainter = new QPainter(this);//创建画家
mRole = new Role(this);
//定时调用更新函数
mTimer = new QTimer(this);
mTimer->start(100);
//定时调用更新函数
connect(mTimer,&QTimer::timeout,[this](){this->update();});
setFixedSize(1024,768);//固定窗口大小
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
mMapPainter->begin(this);//设置画布
//画背景
QPainter bgPainter(this);
bgPainter.drawImage(QRect(0,0,1024,768),QImage("://Image/ground.png"));
//画地图
mPMap->Paint(mMapPainter,QPoint(10,200));
//画人物
mRole->Paint(mMapPainter,QPoint(10,200));
mMapPainter->end();//结束
}
void Widget::keyPressEvent(QKeyEvent* event)
{
switch (event->key())
{
case Qt::Key_W:
case Qt::Key_Up:
{
//逻辑碰撞检测函数
Collision(-1,0);
break;
}
case Qt::Key_S:
case Qt::Key_Down:
{
//逻辑碰撞检测函数
Collision(1,0);
break;
}
case Qt::Key_A:
case Qt::Key_Left:
{
//逻辑碰撞检测函数
Collision(0,-1);
break;
}
case Qt::Key_D:
case Qt::Key_Right:
{
//逻辑碰撞检测函数
Collision(0,1);
break;
}
}
}
void Widget::Collision(int _dRow,int _dCol)
{
//判断位置定义
int newRow = mRole->mRow + _dRow;
int newCol = mRole->mCol + _dCol;
if(mPMap->mPArr[newRow][newCol] == Wall)//判断前方是墙
{
return;
}
else if(mPMap->mPArr[newRow][newCol] == Box)//判断前方是箱子
{
//判断箱子前方
if(mPMap->mPArr[newRow+_dRow][newCol + _dCol] == Road)
{
//改变地图元素
mPMap->mPArr[newRow+_dRow][newCol + _dCol] = Box;//箱子前方变成箱子
mPMap->mPArr[newRow][newCol] = Road;
}
else if(mPMap->mPArr[newRow+_dRow][newCol + _dCol] == Point)
{
//改变地图元素
mPMap->mPArr[newRow+_dRow][newCol + _dCol] = InPoint;//箱子前方变成进目标点
mPMap->mPArr[newRow][newCol] = Road;
}
else
{
return;//无法推动箱子
}
}
else if(mPMap->mPArr[newRow][newCol] == InPoint)//前方是进目标点(箱子与目标重合)
{
//判断目标点前方
if(mPMap->mPArr[newRow+_dRow][newCol + _dCol] == Road)
{
//改变地图元素
mPMap->mPArr[newRow+_dRow][newCol + _dCol] = Box;//目标点前方变成箱子
mPMap->mPArr[newRow][newCol] = Point;
}
else if(mPMap->mPArr[newRow+_dRow][newCol + _dCol] == Point)
{
//改变地图元素
mPMap->mPArr[newRow+_dRow][newCol + _dCol] = InPoint;//箱子进点
mPMap->mPArr[newRow][newCol] = Point;
}
else
{
return;//无法推动箱子
}
}
//否则移动
mRole->Move(_dRow,_dCol);
qDebug() << "人物绘制位置:" << mRole->mPaintPos;
}
如何制作合适的图片 p48集12:40开始看 子弹位置的设计
添加音乐注意事项 导入资源 继承体系
程序运行结果图 bullet.h
#ifndef BULLET_H
#define BULLET_H
#include "gameobject.h"
class Bullet : public GameObject
{
public:
//子弹类型
enum BulletType
{
BT_Player,//我方
BT_Enemy//地方
};
explicit Bullet(QObject *parent = nullptr);
Bullet(QPoint _pos,QPixmap _pixmap,int _type);
//移动函数
void BulletMove(QPoint _dir = QPoint(0,-1));
//初始化函数
void Init(QPoint _pos,QPixmap _pixmap);
~Bullet()
{
qDebug() << "子弹被释放";
}
protected:
int mBulletType;
int mSpeed;
QMediaPlayer mMedia;
};
#endif // BULLET_H
bullet.cpp
#include "bullet.h"
Bullet::Bullet(QObject *parent)
{
mObjectType = GameObject::OT_BulletPlayer;
}
Bullet::Bullet(QPoint _pos, QPixmap _pixmap, int _type)
{
this->setPos(_pos);
this->setPixmap(_pixmap);
this->mBulletType = _type;
mSpeed = 6;
}
void Bullet::BulletMove(QPoint _dir)
{
this->moveBy(_dir.x()*mSpeed,_dir.y()*mSpeed);
}
void Bullet::Init(QPoint _pos, QPixmap _pixmap)
{
this->setPos(_pos);
this->setPixmap(_pixmap);
//----子弹微调整
this->setScale(0.5);//缩放
this->setX(this->x() - this->scale() * pixmap().width()/2);
}
enemy.h
#ifndef ENEMY_H
#define ENEMY_H
#include "plane.h"
class Enemy : public Plane
{
public:
Enemy()
{
mObjectType = GameObject::OT_Enemy;//标识对象
}
Enemy(QPoint _pos,QPixmap _pixmap);
void EnemyMove(QPoint _dir = QPoint(0,1));
void Init(QPoint _pos,QPixmap _pixmap);
};
#endif // ENEMY_H
enemy.cpp
#include "enemy.h"
Enemy::Enemy(QPoint _pos, QPixmap _pixmap)
{
this->mMoveSpeed = 3;
this->mShootSpeed = 1000;
this->setPos(_pos);
this->setPixmap(_pixmap);
}
void Enemy::EnemyMove(QPoint _dir)
{
this->moveBy(_dir.x()*mMoveSpeed ,_dir.y()*mMoveSpeed);
}
void Enemy::Init(QPoint _pos, QPixmap _pixmap)
{
this->setPos(_pos);
this->setPixmap(_pixmap);
this->mMoveSpeed = 3;
this->mShootSpeed = 1000;
}
enemybullet.h
#ifndef ENEMYBULLET_H
#define ENEMYBULLET_H
#include "bullet.h"
class EnemyBullet : public Bullet
{
public:
explicit EnemyBullet(QObject *parent = nullptr);
void PlaySound();
};
#endif // ENEMYBULLET_H
-enemybullet.cpp
#include "enemybullet.h"
EnemyBullet::EnemyBullet(QObject *parent)
{
mObjectType = GameObject::OT_EnemyBullet;
}
void EnemyBullet::PlaySound()
{
mMedia.setMedia(QUrl("qrc:/sound/music/weapon_enemy.wav"));
mMedia.play();
}
gamecontrol.h
#ifndef GAMECONTROL_H
#define GAMECONTROL_H
#include "gamedefine.h"
#include "widget.h"
class GameControl : public QObject
{
//单例
GameControl(QWidget* parent = nullptr);
static GameControl* instance;
public:
//获取单例
static GameControl* Instance()
{
if(instance == nullptr)
{
return instance = new GameControl(Widget::widget);
}
return instance;
}
//析构
~GameControl()
{
qDebug() << "游戏控制释放";
}
//游戏初始化
void GameInit();
void LoadStartScene();//加载开始场景
void LoadGameScene();//游戏场景加载
//游戏逻辑定时器开启 (游戏开始)
void GameStart();
//游戏逻辑定时器关闭 (游戏结束)
void GameOver();
//背景移动
void BGMove();
//飞机移动函数
void PlaneMove();
//我机子弹生成函数
void PlaneBulletShoot();
//敌机生成
void CreateEnemy();
//碰撞检测
void Collision();
QList<int> mKeyList;//按键组合
protected:
QGraphicsView mGameView;//游戏视图
QGraphicsScene mGameScene;//游戏场景
QGraphicsScene mStartScene;//开始游戏场景
//场景元素
QGraphicsPixmapItem mBackGround1;//背景元素
QGraphicsPixmapItem mBackGround2;
Player mPlane;
//定时器
QTimer* mBGMoveTimer;//背景移动
QTimer* mPlaneMoveTimer;//飞机移动
QTimer* mPlaneShootTimer;//飞机发射定时器
QTimer* mBulletMoveTimer;//子弹移动定时器
QTimer* mEnemyCreateTimer;//敌机创建定时器
QTimer* mEnemyMoveTimer;//敌机创建定时器
//容器
QList<Bullet*> mBulletList;//子弹容器
QList<Enemy*> mEnemyList;//敌机容器
//背景音乐
QMediaPlayer* mMediaBG;
};
#endif // GAMECONTROL_H
gamecontrol.cpp
#include "gamecontrol.h"
#include "gamedefine.h"
#include "gameobjectpool.h"
GameControl* GameControl::instance = nullptr;
GameControl::GameControl(QWidget* parent) : QObject (parent)
{
// this->setParent(Widget::widget);
}
void GameControl::BGMove()
{
mBackGround2.moveBy(0,2);
mBackGround1.moveBy(0,2);//moveBy 移动量 dx--x方向移动量 dy---y方向移动量
if(mBackGround1.y() >= mBackGround1.pixmap().height())
{
mBackGround1.setY(-mBackGround1.pixmap().height());
}
else if(mBackGround2.y() >= mBackGround2.pixmap().height())
{
mBackGround2.setY(-mBackGround2.pixmap().height());
}
}
void GameControl::GameInit()
{
//对象池初始化
GameObjectPool::Instance()->Init();
//设置视图的父亲为窗口
mGameView.setParent(Widget::widget);
//开始场景初始化
LoadStartScene();
//定时器初始化
mBGMoveTimer = new QTimer(Widget::widget);
mPlaneMoveTimer = new QTimer(Widget::widget);
mPlaneShootTimer = new QTimer(Widget::widget);
mBulletMoveTimer = new QTimer(Widget::widget);
mEnemyCreateTimer = new QTimer(Widget::widget);
mEnemyMoveTimer = new QTimer(Widget::widget);
//绑定定时器处理函数
connect(mBGMoveTimer,&QTimer::timeout,this,&GameControl::BGMove);
connect(mPlaneMoveTimer,&QTimer::timeout,this,&GameControl::PlaneMove);
connect(mPlaneShootTimer,&QTimer::timeout,this,&GameControl::PlaneBulletShoot);
connect(mEnemyCreateTimer,&QTimer::timeout,this,&GameControl::CreateEnemy);
connect(mBulletMoveTimer,&QTimer::timeout,[this](){
//子弹移动
for(auto bullet : mBulletList)
{
bullet->BulletMove();
//判断越界回收子弹
if(bullet->y() < -200)
{
//移除场景 并回收对象
bullet->GameObjectDelete(&mGameScene);
//移除容器
mBulletList.removeOne(bullet);
}
}
//碰撞检测
Collision();
});
connect(mEnemyMoveTimer,&QTimer::timeout,[this](){
for(auto enemy : mEnemyList)
{
enemy->EnemyMove();
if(enemy->y() > GameDefine::ScreenHeight + enemy->pixmap().height())
{
//移除场景 对象池回收对象
enemy->GameObjectDelete(&mGameScene);
//移除容器
mEnemyList.removeOne(enemy);
}
}
});
}
void GameControl::LoadStartScene()
{
mStartScene.setSceneRect(QRect(0,0,512,768));//游戏开始场景大小
mStartScene.addPixmap(QPixmap(":/img/Image/img_bg_logo.jpg"));
auto startBtn = new QToolButton();
startBtn->setAutoRaise(true);
startBtn->setIcon(QIcon(":/img/Image/startBtn.fw.png"));
startBtn->setIconSize(QSize(171,45));
startBtn->move(256-171/2,384);
//开始游戏点击
connect(startBtn,&QToolButton::clicked,[this](){
//加载游戏场景
this->LoadGameScene();
//开始游戏
this->GameStart();
});
mStartScene.addWidget(startBtn);
//设置当前场景为 开始场景
mGameView.setScene(&mStartScene);
mGameView.show();
}
void GameControl::LoadGameScene()
{
mGameScene.setSceneRect(QRect(0,0,512,768));//游戏进行场景大小
mBackGround1.setPixmap(QPixmap(":/img/Image/img_bg_level_2.jpg"));//于QImage用法类似
mBackGround2.setPixmap(QPixmap(":/img/Image/img_bg_level_2.jpg"));
mPlane.setPixmap(QPixmap(":/img/Image/MyPlane1.fw.png"));
//设置元素位置
mBackGround2.setPos(0,-mBackGround2.pixmap().height());
//图片元素添加到场景
mGameScene.addItem(&mBackGround1);
mGameScene.addItem(&mBackGround2);
mGameScene.addItem(&mPlane);
//设置当前场景为游戏场景
mGameView.setScene(&mGameScene);
mGameView.show();
//-------------播放音效
this->mMediaBG = new QMediaPlayer(Widget::widget);
//注意 QUrl路径对象 字符串格式 "qrc:/ + 前缀名+ /路径"
this->mMediaBG->setMedia(QUrl("qrc:/sound/music/starwars.mp3"));
this->mMediaBG->play();
}
void GameControl::GameStart()
{
//开启定时器
mBGMoveTimer->start(GameDefine::BackgroundUpdateTime);
mPlaneMoveTimer->start(GameDefine::PlayerMoveUpdateTime);
mPlaneShootTimer->start(GameDefine::PlaneShootUpdateTime);
mBulletMoveTimer->start(GameDefine::BulletMoveUpdateTime);
mEnemyCreateTimer->start(GameDefine::EnemyCreateTime);
mEnemyMoveTimer->start(GameDefine::EnemyMoveUpdateTime);
}
void GameControl::GameOver()
{
//结束逻辑
//...
}
void GameControl::PlaneMove()
{
for(int keyCode : mKeyList)
{
switch (keyCode)
{
case Qt::Key_W: mPlane.moveBy(0,-1 * mPlane.MoveSpeed());break;
case Qt::Key_S: mPlane.moveBy(0,1*mPlane.MoveSpeed());break;
case Qt::Key_A: mPlane.moveBy(-1*mPlane.MoveSpeed(),0);break;
case Qt::Key_D: mPlane.moveBy(1*mPlane.MoveSpeed(),0);break;
}
}
//*******************************边界判断
if(mPlane.x() < 0)
{
mPlane.setX(0);
}
if(mPlane.y() < 0)
{
mPlane.setY(0);
}
if(mPlane.x() > GameDefine::ScreenWidth - mPlane.pixmap().width())
{
mPlane.setX(GameDefine::ScreenWidth - mPlane.pixmap().width());
}
if(mPlane.y() > GameDefine::ScreenHeight - mPlane.pixmap().height())
{
mPlane.setY(GameDefine::ScreenHeight - mPlane.pixmap().height());
}
}
void GameControl::PlaneBulletShoot()
{
//对象池构建子弹
QPixmap bulletImg(":/img/Image/bulletPlane.fw.png");
QPoint pos(mPlane.x() + mPlane.pixmap().width()/2,mPlane.y());
GameObject* obj = GameObjectPool::Instance()->GetGameObject(GameObject::OT_BulletPlayer);
PlayerBullet* bullet = (PlayerBullet*)obj;
bullet->Init(pos,bulletImg);
bullet->PlaySound();//播放音效
//添加到场景
mGameScene.addItem(bullet);
//添加到子弹管理器
mBulletList.append(bullet);
}
void GameControl::CreateEnemy()
{
// Enemy* enemy = new Enemy(QPoint(randX,-200),pixmap);
//对象池获取对象
QPixmap pixmap(":/img/Image/enemy1.fw.png");
int randX = qrand()%(512-pixmap.width());// [0,32768)
GameObject* obj = GameObjectPool::Instance()->GetGameObject(GameObject::OT_Enemy);
Enemy* enemy = (Enemy*)obj;
enemy->Init(QPoint(randX,-200),pixmap);
//添加到场景
mGameScene.addItem(enemy);
//添加到管理器
mEnemyList.append(enemy);
}
void GameControl::Collision()
{
//遍历子弹
for(int i = 0;i < mBulletList.size();i++)
{
//遍历敌机
for(int j = 0;j < mEnemyList.size();j++)
{
if(mBulletList[i]->collidesWithItem(mEnemyList[j]))//碰撞检测
{
//移除场景 (实际的对象并没有被删除)
// mGameScene.removeItem(mBulletList[i]);
// mGameScene.removeItem(mEnemyList[j]);
//移除场景并回收到对象池
mBulletList[i]->GameObjectDelete(&mGameScene);
mEnemyList[j]->GameObjectDelete(&mGameScene);
//移除管理器
mBulletList.removeOne(mBulletList[i]);
mEnemyList.removeOne(mEnemyList[j]);
}
}
}
}
gamedefine.h
#ifndef GAMEDEFINE_H
#define GAMEDEFINE_H
#include <QtDebug>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QTimer>
#include <QList>
#include <QToolButton>
#include <QMediaPlayer>
#include "bullet.h"
#include "enemy.h"
#include "player.h"
#include "playerbullet.h"
#include "enemybullet.h"
//游戏定义类 定义游戏相关属性
class GameDefine
{
public:
GameDefine();
static const int PlaneShootUpdateTime = 500;
static const int PlayerMoveUpdateTime = 20;
static const int EnemyMoveUpdateTime = 20;
static const int BulletMoveUpdateTime = 10;
static const int BackgroundUpdateTime = 50;
static const int EnemyCreateTime = 2000;
//屏幕宽高
static const int ScreenWidth = 512;
static const int ScreenHeight = 768;
};
#endif // GAMEDEFINE_H
gamedefine.cpp
#include "gamedefine.h"
GameDefine::GameDefine()
{
}
gameobject.h
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
#include <QGraphicsPixmapItem>
#include <QDebug>
#include <QMediaPlayer>
class GameObject : public QGraphicsPixmapItem
{
public:
enum ObjectType
{
OT_BulletPlayer,
OT_Enemy,
OT_Player,
OT_EnemyBullet
};
explicit GameObject(QObject *parent = nullptr);
int GetType()
{
return mObjectType;
}
//对象回收
void GameObjectDelete(QGraphicsScene* _scene);
//统计对象构造 和析构
static int createCount;
~GameObject()
{
qDebug() << "当前释放第" + QString::number(createCount--) + "个对象";
}
protected:
int mObjectType;
};
#endif // GAMEOBJECT_H
gameobject.cpp`
#include "gameobject.h"
#include <QGraphicsScene>
#include "gameobjectpool.h"
#include <QDebug>
int GameObject::createCount = 0;
GameObject::GameObject(QObject *parent)
{
createCount++;
qDebug() << "当前创建" + QString::number(createCount) + "个对象";
}
void GameObject::GameObjectDelete(QGraphicsScene* _scene)
{
_scene->removeItem(this);//移除场景
GameObjectPool::Instance()->RecoveryGameObject(this);//回收对象
}
gameobjectpool.h
#ifndef GAMEOBJECTPOOL_H
#define GAMEOBJECTPOOL_H
#include <QObject>
#include "gamedefine.h"
#include "widget.h"
/*
*
* 当对象被频繁创建 或 删除时 大量使用 new 和 delete 关键字
处理堆内存 如果该对象比较大 则对计算机的消耗就越大 很有可以在创建大量
对象时出现卡顿情况 频繁的创建和删除对计算机消耗比较大。
对象缓存池:对象缓存池 预先缓存一定数量的对象 对象需要被
使用时 直接从对象池中获取对象 能有效的解决在创建时导致的卡顿问题。在对象
需要被消耗时 不销毁对象将其回收到对象缓存池中 循环利用从而解决对计算机的
销毁。
(简单来说 就是游戏对象的循环利用)
*/
class GameObjectPool : public QObject
{
GameObjectPool(QObject *parent = nullptr);
static GameObjectPool* instance;
public:
static GameObjectPool* Instance()
{
if(instance == nullptr)
{
return instance = new GameObjectPool(Widget::widget);
}
return instance;
}
//对象池初始化 缓存对象
void Init();
//获取对象
GameObject* GetGameObject(int _objectType);
//对象回收
void RecoveryGameObject(GameObject* _object);
//内存清除
void Clear();
~GameObjectPool();
protected:
//玩家子弹对象池容器
QList<PlayerBullet*> mBulletPool;
//敌机对象池容器
QList<Enemy*> mEnemyPool;
};
#endif // GAMEOBJECTPOOL_H
gameobjectpool.cpp
#include "gameobjectpool.h"
GameObjectPool* GameObjectPool::instance = nullptr;
GameObjectPool::GameObjectPool(QObject *parent) : QObject(parent)
{
}
void GameObjectPool::Init()
{
//预先生产对象
for (int i = 0;i < 20; i++)
{
//子弹生产
PlayerBullet* bullet = new PlayerBullet();
mBulletPool.append(bullet);
//敌机生产
Enemy* enemy = new Enemy();
mEnemyPool.append(enemy);
}
}
GameObject *GameObjectPool::GetGameObject(int _objectType)
{
switch (_objectType)
{
case GameObject::OT_BulletPlayer://子弹
{
PlayerBullet* bullet = mBulletPool.first();
mBulletPool.pop_front();
return bullet;
}
case GameObject::OT_Enemy://敌机
{
Enemy* enemy = mEnemyPool.first();
mEnemyPool.pop_front();
return enemy;
}
}
}
void GameObjectPool::RecoveryGameObject(GameObject *_object)
{
switch (_object->GetType())
{
case GameObject::OT_BulletPlayer://子弹
{
mBulletPool.append((PlayerBullet*)_object);
break;
}
case GameObject::OT_Enemy://敌机
{
mEnemyPool.append((Enemy*)_object);
break;
}
}
}
void GameObjectPool::Clear()
{
//清除子弹容器
for(auto pBullet : mBulletPool)
{
delete pBullet;
}
//清除敌机容器
for(auto pEnemy :mEnemyPool)
{
delete pEnemy;
}
}
GameObjectPool::~GameObjectPool()
{
Clear();//内存清除
}
plane.h
#ifndef PLANE_H
#define PLANE_H
#include "gameobject.h"
class Plane : public GameObject
{
public:
explicit Plane(QObject *parent = nullptr);
float MoveSpeed()
{
return mMoveSpeed;
}
protected:
float mMoveSpeed;
int mShootSpeed;
};
#endif // PLANE_H
plane.cpp
#include "plane.h"
Plane::Plane(QObject *parent)
{
mObjectType = GameObject::OT_Player;
}
player.h
#ifndef MYPLANE_H
#define MYPLANE_H
#include "plane.h"
class Player : public Plane
{
// Q_OBJECT QGraphicsItem的派生类 不支持 Q_OBJECT(老式 信号和槽 宏)
public:
Player();
};
#endif // MYPLANE_H
player.cpp
#include "player.h"
Player::Player()
{
this->setPixmap(QPixmap(":/img/Image/MyPlane1.fw.png"));
this->setPos(256,500);
mMoveSpeed = 5;
mShootSpeed = 500;
}
playerbullet.h
#ifndef PLAYERBULLET_H
#define PLAYERBULLET_H
#include "bullet.h"
class PlayerBullet : public Bullet
{
public:
explicit PlayerBullet(QObject *parent = nullptr);
//玩家子弹音效
void PlaySound();
signals:
public slots:
};
#endif // PLAYERBULLET_H
playerbullet.cpp
#include "playerbullet.h"
PlayerBullet::PlayerBullet(QObject *parent)
{
mObjectType = GameObject::OT_BulletPlayer;
mSpeed = 6;
}
void PlayerBullet::PlaySound()
{
mMedia.setMedia(QUrl("qrc:/sound/music/weapon_player.wav"));
mMedia.play();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QGraphicsPixmapItem>//图形元素
#include <QGraphicsView>//视图
#include <QGraphicsScene>//场景
#include <QList>//链表
#include "enemy.h"
#include "player.h"
#include "bullet.h"
#include <QMediaPlayer>//媒体播放器类
// 图形元素组成 ---> 场景 --> 视图 --> 窗口
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
static Widget* widget;
//按键事件 widget才能检测到这两个函数
void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "gamecontrol.h"
#include "student.h"
Widget* Widget::widget = nullptr;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setFixedSize(512,768);
widget = this;//拿到widget,防止使用this报错
GameControl::Instance()->setParent(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
//添加按键到按键组合
switch (event->key())
{
case Qt::Key_W:
case Qt::Key_S:
case Qt::Key_A:
case Qt::Key_D:
GameControl::Instance()->mKeyList.append(event->key());
break;
}
}
void Widget::keyReleaseEvent(QKeyEvent *event)
{
//移除对应按键组合
if(GameControl::Instance()->mKeyList.contains(event->key()))
{
GameControl::Instance()->mKeyList.removeOne(event->key());
}
}
main.cpp
#include <QApplication>
#include "gamecontrol.h"
#include "student.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
//游戏加载
GameControl::Instance()->GameInit();
return a.exec();
}
快速判断xml文件是否写错 将文件直接拖入浏览器中,如果能正常打开就是没错的 HeroInfo.xml
Config.xml
目录结构
Hero.h
#ifndef HERO_H
#define HERO_H
#include <QObject>
class Hero
{
public:
Hero();
Hero(QString name,int atk,int def,int hp,QString des)
{
mName = name;
mAtk =atk;
mHp = hp;
mDef = def;
mDescript = des;
}
QString mName;
int mAtk;
int mDef;
int mHp;
QString mDescript;
};
#endif // HERO_H
Hero.cpp
#include "Hero.h"
Hero::Hero()
{
}
-Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_LoadBtn_clicked();
void on_SaveBtn_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
Widget.cpp
#include "Widget.h"
#include "ui_widget.h"
#include <QtXML> //需导入QtXML,并且执行qmake
#include "Hero.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->textEdit->setReadOnly(true);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_LoadBtn_clicked()
{
//构建文件对象 QFile
QFile file("HeroInfo.xml");
if(!file.open(QIODevice::ReadOnly))//打开文件用于读取
return;
//**************XML文件读取*************
QDomDocument doc;//创建文档对象
doc.setContent(&file);//设置文档内容,将file和doc绑定起来
// doc.setContent(file.readAll());//设置文档内容
QDomElement root = doc.firstChildElement("Root");//获取第一个子标签
QDomElement hero = root.firstChildElement("Hero");//获取hero子标签
QString text;
while (!hero.isNull())//判断hero标签是否存在
{
text += "Name:" + hero.attribute("name");//读取属性
text += " Atk:" + hero.attribute("atk");
text += " Def:" + hero.attribute("def");
text += " HP:" + hero.attribute("hp");
//读取标签内容
text += " Des:" + hero.text()+"\n";
hero = hero.nextSiblingElement("Hero");//获取下一个Hero兄弟标签
}
ui->textEdit->setText(text);
file.close();
}
void Widget::on_SaveBtn_clicked()
{
QVector<Hero> vec;
vec.push_back(Hero("曹操",100,25,2000,"曹孟德"));
vec.push_back(Hero("曹丕",100,25,2000,"曹子桓"));
vec.push_back(Hero("曹植",100,25,2000,"曹子建"));
vec.push_back(Hero("曹彰",100,25,2000,"曹xx"));
vec.push_back(Hero("曹真",100,25,2000,"曹xx"));
//创建xml文档对象
QDomDocument doc;
QDomElement root = doc.createElement("Root");//创建root标签
for(int i =0;i < vec.count();i++)
{
QDomElement hero = doc.createElement("Hero");//创建hero标签
root.appendChild(hero);
hero.setAttribute("Name",vec[i].mName);//设置属性 Name
hero.setAttribute("Atk",vec[i].mAtk);
hero.setAttribute("Def",vec[i].mDef);
hero.setAttribute("HP",vec[i].mHp);
QDomText text = doc.createTextNode(vec[i].mDescript);
hero.appendChild(text);
}
doc.appendChild(root);//将root节点添加到文档对象
//创建文件对象
QFile file("./Config.xml"); //采用相对路径
if(!file.open(QIODevice::WriteOnly))
return;
QTextStream outStream(&file);//创建文本流对象
doc.save(outStream,4);
file.close();
}
本站为非盈利网站,如果您喜欢这篇文章,欢迎支持我们继续运营!
本站主要用于日常笔记的记录和生活日志。本站不保证所有内容信息可靠!(大多数文章属于搬运!)如有版权问题,请联系我立即删除:“abcdsjx@126.com”。
QQ: 1164453243
邮箱: abcdsjx@126.com