Qt塔防游戏_xml

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "waypoint.h"
#include "enemy.h"
#include "bullet.h"
#include "audioplayer.h"
#include "plistreader.h"
#include <QPainter>
#include <QMouseEvent>
#include <QtGlobal>
#include <QMessageBox>
#include <QTimer>
#include <QXmlStreamReader>
#include <QtDebug>

static const int TowerCost = 300;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_waves(0)
, m_playerHp(5)
, m_playrGold(1000)
, m_gameEnded(false)
, m_gameWin(false)
{
ui->setupUi(this);

preLoadWavesInfo();
loadTowerPositions();
addWayPoints();

m_audioPlayer = new AudioPlayer(this);
m_audioPlayer->startBGM();

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateMap()));
timer->start(30);

// 设置300ms后游戏启动
QTimer::singleShot(300, this, SLOT(gameStart()));
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::loadTowerPositions(){
QFile file(":/config/TowersPosition.plist");
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this, "TowerDefense", "Cannot Open TowersPosition.plist");
return;
}

PListReader reader;
reader.read(&file);

QList<QVariant> array = reader.data();
foreach (QVariant dict, array)
{
QMap<QString, QVariant> point = dict.toMap();
int x = point.value("x").toInt();
int y = point.value("y").toInt();
m_towerPositionsList.push_back(QPoint(x, y));
}

file.close();
}

void MainWindow::paintEvent(QPaintEvent *)
{
if (m_gameEnded || m_gameWin)
{
QString text = m_gameEnded ? "YOU LOST!!!" : "YOU WIN!!!";
QPainter painter(this);
painter.setPen(QPen(Qt::red));
painter.drawText(rect(), Qt::AlignCenter, text);
return;
}

QPixmap cachePix(":/picture/map.png");
QPainter cachePainter(&cachePix);

foreach (const TowerPosition &towerPos, m_towerPositionsList)
towerPos.draw(&cachePainter);

foreach (const BlueTower *tower, m_BluetowersList)
tower->draw(&cachePainter);
foreach (const RedTower *tower, m_RedtowersList)
tower->draw(&cachePainter);
foreach (const PurpleTower *tower, m_PurpletowersList)
tower->draw(&cachePainter);

foreach (const WayPoint *wayPoint, m_wayPointsList)
wayPoint->draw(&cachePainter);

foreach (const Enemy *enemy, m_enemyList)
enemy->draw(&cachePainter);

foreach (const Bullet *bullet, m_bulletList)
bullet->draw(&cachePainter);

drawWave(&cachePainter);
drawHP(&cachePainter);
drawPlayerGold(&cachePainter);

QPainter painter(this);
painter.drawPixmap(0, 0, cachePix);
}

void MainWindow::removedTower(QPoint pos)
{
for (int i = 0; i >= 0; i++)
{
if (m_BluetowersList[i]->getPos() == pos)
{
delete m_BluetowersList[i];
update();
break;
}
}
for (int i = 0; i >= 0; i++)
{
if (m_RedtowersList[i]->getPos() == pos)
{
delete m_RedtowersList[i];
update();
break;
}
}
for (int i = 0; i >= 0; i++)
{
if (m_PurpletowersList[i]->getPos() == pos)
{
delete m_PurpletowersList[i];
update();
break;
}
}
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
QPoint pressPos = event->pos();
auto it = m_towerPositionsList.begin();
while (it != m_towerPositionsList.end())
{
if (canBuyTower() && it->containPoint(pressPos))
{
m_audioPlayer->playSound(TowerPlaceSound);
m_playrGold -= TowerCost;
if (!it->hasBlueTower())
{
it->setHasBlueTower();
BlueTower *tower1 = new BlueTower(it->centerPos(), this);
m_BluetowersList.push_back(tower1);
}
else if (!it->hasPurpleTower() && it->hasBlueTower())
{
it->setHasPurpleTower();
removedTower(it->centerPos());
PurpleTower *tower2 = new PurpleTower(it->centerPos(), this);
m_PurpletowersList.push_back(tower2);
}
else if (!it->hasRedTower() && it->hasPurpleTower())
{
it->setHasRedTower();
removedTower(it->centerPos());
RedTower *tower3 = new RedTower(it->centerPos(), this);
m_RedtowersList.push_back(tower3);
}
update();
break;
}
++it;
}
}

bool MainWindow::canBuyTower() const
{
if (m_playrGold >= TowerCost)
return true;
return false;
}

void MainWindow::drawWave(QPainter *painter)
{
painter->setPen(QPen(Qt::red));
painter->drawText(QRect(400, 5, 100, 25), QString("WAVE : %1").arg(m_waves + 1));
}

void MainWindow::drawHP(QPainter *painter)
{
painter->setPen(QPen(Qt::red));
painter->drawText(QRect(30, 5, 100, 25), QString("HP : %1").arg(m_playerHp));
}

void MainWindow::drawPlayerGold(QPainter *painter)
{
painter->setPen(QPen(Qt::red));
painter->drawText(QRect(200, 5, 200, 25), QString("GOLD : %1").arg(m_playrGold));
}

void MainWindow::doGameOver()
{
if (!m_gameEnded)
{
m_gameEnded = true;
// 此处应该切换场景到结束场景
// 暂时以打印替代,见paintEvent处理
}
}

void MainWindow::awardGold(int gold)
{
m_playrGold += gold;
update();
}

AudioPlayer *MainWindow::audioPlayer() const
{
return m_audioPlayer;
}

void MainWindow::addWayPoints()
{
int k;
k = rand()%2;
if(k == 1){
WayPoint *wayPoint1 = new WayPoint(QPoint(630, 340));
m_wayPointsList.push_back(wayPoint1);

WayPoint *wayPoint2 = new WayPoint(QPoint(630, 290));
m_wayPointsList.push_back(wayPoint2);
wayPoint2->setNextWayPoint(wayPoint1);

WayPoint *wayPoint3 = new WayPoint(QPoint(580, 290));
m_wayPointsList.push_back(wayPoint3);
wayPoint3->setNextWayPoint(wayPoint2);

WayPoint *wayPoint4 = new WayPoint(QPoint(580, 220));
m_wayPointsList.push_back(wayPoint4);
wayPoint4->setNextWayPoint(wayPoint3);

WayPoint *wayPoint5 = new WayPoint(QPoint(410, 220));
m_wayPointsList.push_back(wayPoint5);
wayPoint5->setNextWayPoint(wayPoint4);

WayPoint *wayPoint6 = new WayPoint(QPoint(410, 290));
m_wayPointsList.push_back(wayPoint6);
wayPoint6->setNextWayPoint(wayPoint5);

WayPoint *wayPoint7 = new WayPoint(QPoint(210, 290));
m_wayPointsList.push_back(wayPoint7);
wayPoint7->setNextWayPoint(wayPoint6);

WayPoint *wayPoint8 = new WayPoint(QPoint(210, 220));
m_wayPointsList.push_back(wayPoint8);
wayPoint8->setNextWayPoint(wayPoint7);

WayPoint *wayPoint9 = new WayPoint(QPoint(90, 220));
m_wayPointsList.push_back(wayPoint9);
wayPoint9->setNextWayPoint(wayPoint8);

WayPoint *wayPoint10 = new WayPoint(QPoint(90, 330));
m_wayPointsList.push_back(wayPoint10);
wayPoint10->setNextWayPoint(wayPoint9);

WayPoint *wayPoint11 = new WayPoint(QPoint(30, 330));
m_wayPointsList.push_back(wayPoint11);
wayPoint11->setNextWayPoint(wayPoint10);
}else{
WayPoint *wayPoint1 = new WayPoint(QPoint(630, 340));
m_wayPointsList.push_back(wayPoint1);

WayPoint *wayPoint2 = new WayPoint(QPoint(630, 450));
m_wayPointsList.push_back(wayPoint2);
wayPoint2->setNextWayPoint(wayPoint1);

WayPoint *wayPoint3 = new WayPoint(QPoint(90, 450));
m_wayPointsList.push_back(wayPoint3);
wayPoint3->setNextWayPoint(wayPoint2);

WayPoint *wayPoint4 = new WayPoint(QPoint(90, 330));
m_wayPointsList.push_back(wayPoint4);
wayPoint4->setNextWayPoint(wayPoint3);

WayPoint *wayPoint5 = new WayPoint(QPoint(30, 330));
m_wayPointsList.push_back(wayPoint5);
wayPoint5->setNextWayPoint(wayPoint4);
}
}

void MainWindow::getHpDamage(int damage/* = 1*/)
{
m_audioPlayer->playSound(LifeLoseSound);
m_playerHp -= damage;
if (m_playerHp <= 0)
doGameOver();
}

void MainWindow::removedEnemy(Enemy *enemy)
{
Q_ASSERT(enemy);
m_enemyList.removeOne(enemy);
delete enemy;

if (m_enemyList.empty())
{
++m_waves;
if (!loadWave())
{
m_gameWin = true;
// 游戏胜利转到游戏胜利场景
// 这里暂时以打印处理
}
}
}

void MainWindow::removedBullet(Bullet *bullet)
{
Q_ASSERT(bullet);

m_bulletList.removeOne(bullet);
delete bullet;
}

void MainWindow::addBullet(Bullet *bullet)
{
Q_ASSERT(bullet);

m_bulletList.push_back(bullet);
}

void MainWindow::updateMap()
{
foreach (Enemy *enemy, m_enemyList)
enemy->move();
foreach (BlueTower *tower, m_BluetowersList)
tower->checkEnemyInRange();
foreach (RedTower *tower, m_RedtowersList)
tower->checkEnemyInRange();
foreach (PurpleTower *tower, m_PurpletowersList)
tower->checkEnemyInRange();
update();
}

void MainWindow::preLoadWavesInfo()
{
QFile file(":/config/Waves.plist");
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this, "TowerDefense", "Cannot Open TowersPosition.plist");
return;
}

PListReader reader;
reader.read(&file);

// 获取波数信息
m_wavesInfo = reader.data();

file.close();
}

bool MainWindow::loadWave()
{
if (m_waves >= m_wavesInfo.size())
return false;

WayPoint *startWayPoint = m_wayPointsList.back();
QList<QVariant> curWavesInfo = m_wavesInfo[m_waves].toList();

for (int i = 0; i < curWavesInfo.size(); ++i)
{
QMap<QString, QVariant> dict = curWavesInfo[i].toMap();
int spawnTime = dict.value("spawnTime").toInt();

Enemy *enemy = new Enemy(startWayPoint, this);
m_enemyList.push_back(enemy);
QTimer::singleShot(spawnTime, enemy, SLOT(doActivate()));
}

return true;
}

QList<Enemy *> MainWindow::enemyList() const
{
return m_enemyList;
}

void MainWindow::gameStart()
{
loadWave();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QList>
#include "towerposition.h"
#include "tower.h"
#include "waypoint.h"
#include "enemy.h"

namespace Ui {
class MainWindow;
}

class WayPoint;
class Enemy;
class Bullet;
class AudioPlayer;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

void getHpDamage(int damage = 1);
void removedEnemy(Enemy *enemy);
void removedTower(QPoint pos);
void removedBullet(Bullet *bullet);
void addBullet(Bullet *bullet);
void awardGold(int gold);

AudioPlayer* audioPlayer() const;
QList<Enemy *> enemyList() const;

protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *);

private slots:
void updateMap();
void gameStart();

private:
void loadTowerPositions();
void addWayPoints();
bool loadWave();
bool canBuyTower() const;
void drawWave(QPainter *painter);
void drawHP(QPainter *painter);
void drawPlayerGold(QPainter *painter);
void doGameOver();
void preLoadWavesInfo();

private:
Ui::MainWindow * ui;
int m_waves;
int m_playerHp;
int m_playrGold;
bool m_gameEnded;
bool m_gameWin;
AudioPlayer * m_audioPlayer;
QList<QVariant> m_wavesInfo;
QList<TowerPosition> m_towerPositionsList;
QList<BlueTower *> m_BluetowersList;
QList<RedTower *> m_RedtowersList;
QList<PurpleTower *> m_PurpletowersList;
QList<WayPoint *> m_wayPointsList;
QList<Enemy *> m_enemyList;
QList<Bullet *> m_bulletList;
};

#endif // MAINWINDOW_H