#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