#include "gameengine.h"
#include "plugins/levelplugininterface.h"
#include "InvSounds.h"
#include <QDebug>
#include <QTimerEvent>
#include <QTime>
#include <QDesktopServices>
const int TIMER_SPEED = 80;
GameEngine::GameEngine(QObject* parent)
:QObject(parent)
{
m_timerId = 0;
m_doEnemyMissile = 1500 / TIMER_SPEED;
m_GameGml = 0;
m_gameLevel = 0;
clearQmlObjects();
QTime time = QTime::currentTime();
qsrand((uint)time.msec());
m_soundEngine = new CInvSounds(this);
m_silent = false;
#ifdef Q_OS_SYMBIAN
iVibrate = CHWRMVibra::NewL();
#endif
#if defined Q_OS_SYMBIAN || defined Q_WS_MAEMO_5
m_systemDeviceInfo = new QSystemDeviceInfo(this);
QObject::connect(m_systemDeviceInfo,SIGNAL(currentProfileChanged(QSystemDeviceInfo::Profile)),this,
SLOT(currentProfileChanged(QSystemDeviceInfo::Profile)));
QSystemDeviceInfo::Profile p = m_systemDeviceInfo->currentProfile();
if (p == QSystemDeviceInfo::SilentProfile) {
m_silent = true;
}
#endif
}
GameEngine::~GameEngine()
{
#ifdef Q_OS_SYMBIAN
delete iVibrate;
#endif
}
void GameEngine::gameStartSound()
{
if (!m_silent)
m_soundEngine->gameStartSound();
}
#if defined Q_OS_SYMBIAN || defined Q_WS_MAEMO_5
void GameEngine::currentProfileChanged(QSystemDeviceInfo::Profile p)
{
if (p == QSystemDeviceInfo::SilentProfile) {
enableSounds(QVariant(false));
} else {
enableSounds(QVariant(true));
}
}
#endif
void GameEngine::enableSounds(QVariant enable)
{
m_silent = !enable.toBool();
if (m_silent)
this->m_soundEngine->enableSounds(false);
else
this->m_soundEngine->enableSounds(true);
}
QVariant GameEngine::randInt(QVariant low, QVariant high)
{
return qrand() % ((high.toInt() + 1) - low.toInt()) + low.toInt();
}
void GameEngine::setGameLevel(LevelPluginInterface* level)
{
m_gameLevel = level;
if (m_gameLevel) {
m_soundEngine->enableSounds(m_gameLevel->levelSounds());
QMetaObject::invokeMethod(m_GameGml, "levelReadyForCreation", Qt::AutoConnection);
m_doEnemyMissile = m_gameLevel->enemyFireSpeed().toInt() / TIMER_SPEED;
}
}
void GameEngine::setPluginList(QList<QPluginLoader*> plugins)
{
m_pluginList = plugins;
}
QVariant GameEngine::pluginList()
{
QStringList list;
QPluginLoader* loader;
foreach (loader,m_pluginList) {
QString s = loader->fileName();
s = s.mid(s.lastIndexOf("/")+1);
s = s.left(s.lastIndexOf("."));
s = s.toUpper();
#ifdef Q_WS_MAEMO_5
if (s.contains("LIB")) {
s = s.right(s.length() - (s.indexOf("LIB")+3));
}
#endif
list.append(s);
}
return QVariant(list);
}
void GameEngine::pauseLevel(QVariant doPause)
{
bool enableTimer = !doPause.toBool();
enableEngineTimer(QVariant(enableTimer));
QMetaObject::invokeMethod(m_levelQml, "pause", Qt::AutoConnection,Q_ARG(QVariant, doPause));
}
void GameEngine::findQmlObjects()
{
if (m_GameGml) {
qDebug() << "GameEngine::findQmlObjects()";
m_missileList.clear();
m_enemyMissileList.clear();
findMissiles(m_GameGml);
setLevelQml(m_GameGml->findChild<QObject*>("level"));
setEnemiesGridQml(m_GameGml->findChild<QObject*>("enemiesGrid"));
setMyShipQml(m_GameGml->findChild<QObject*>("myShip"));
m_enemyList.clear();
qDebug() << "GameEngine::findQmlObjects() find enemies from: level QML";
findEnemies(m_levelQml);
} else {
qDebug() << "GameEngine::findQmlObjects() rootObject NULL";
}
}
void GameEngine::clearQmlObjects()
{
m_missileList.clear();
m_enemyMissileList.clear();
m_enemyList.clear();
m_levelQml = 0;
m_enemiesGridGml = 0;
m_myShipGml = 0;
}
void GameEngine::findMissiles(QObject *rootObject)
{
if (rootObject) {
QObjectList list = rootObject->children();
QObject* item;
foreach (item,list) {
if (item->children().count()>0) {
findMissiles(item);
} else {
if (rootObject->objectName()=="missile") {
QDeclarativeItem* missile = static_cast<QDeclarativeItem*>(rootObject);
m_missileList.append(missile);
} else if (rootObject->objectName()=="enemy_missile") {
QDeclarativeItem* enemyMissile = static_cast<QDeclarativeItem*>(rootObject);
m_enemyMissileList.append(enemyMissile);
}
}
}
} else {
qDebug() << "GameEngine::findMissiles() rootObject NULL";
}
}
void GameEngine::findEnemies(QObject *rootObject)
{
if (rootObject) {
QObjectList list = rootObject->children();
QObject* item;
foreach (item,list) {
if (item->children().count()>0 && item->objectName()!="enemy") {
findEnemies(item);
} else {
if (item->objectName()=="enemy") {
QDeclarativeItem* enemy = static_cast<QDeclarativeItem*>(item);
m_enemyList.append(enemy);
}
}
}
} else {
qDebug() << "GameEngine::findEnemies() rootObject NULL";
}
}
void GameEngine::setEnemiesGridQml(QObject* o)
{
m_enemiesGridGml = static_cast<QDeclarativeItem*>(o);
}
void GameEngine::setMyShipQml(QObject* o)
{
m_myShipGml = static_cast<QDeclarativeItem*>(o);
}
void GameEngine::setGameQml(QObject* o)
{
m_GameGml = static_cast<QDeclarativeItem*>(o);
}
void GameEngine::timerEvent(QTimerEvent *e)
{
if (e->timerId()==m_timerId) {
doHitTest();
m_doEnemyMissile--;
if (m_gameLevel && m_doEnemyMissile<0) {
m_doEnemyMissile = m_gameLevel->enemyFireSpeed().toInt() / TIMER_SPEED;
doEnemyMissile();
}
}
}
void GameEngine::enableEngineTimer(QVariant enable)
{
if (m_gameLevel) {
if (m_timerId==0 && enable.toBool()) {
m_timerId = QObject::startTimer(TIMER_SPEED);
}
else if (m_timerId != 0 && !enable.toBool()) {
QObject::killTimer(m_timerId);
m_timerId = 0;
}
}
}
void GameEngine::selectVisibleEnemy(int& start, int& end)
{
QDeclarativeItem* enemy = 0;
for (int i=0 ; i<m_enemyList.count() ; i++) {
enemy = m_enemyList[i];
if (enemy->opacity()==1) {
start = i;
break;
}
}
enemy = 0;
for (int e=m_enemyList.count()-1 ; e>0 ; e--) {
enemy = m_enemyList[e];
if (enemy->opacity()==1) {
end = e;
break;
}
}
}
void GameEngine::doEnemyMissile()
{
QMutexLocker locker(&m_enemyListMutex);
QDeclarativeItem* missile = 0;
QDeclarativeItem* enemy = 0;
foreach (missile, m_enemyMissileList) {
if (missile->opacity()==0){
int start=0; int end=0;
selectVisibleEnemy(start,end);
int whoWillFire = randInt(QVariant(start),QVariant(end)).toInt();
if (m_enemyList.count() < whoWillFire+1)
break;
enemy = m_enemyList.at(whoWillFire);
if (enemy && enemy->opacity()==1) {
QPointF enemyP = enemy->pos();
if (m_enemiesGridGml) {
enemyP += m_enemiesGridGml->pos();
}
QMetaObject::invokeMethod(m_GameGml, "fireEnemyMissile", Qt::AutoConnection,
Q_ARG(QVariant, enemyP.x()+enemy->boundingRect().width()/4),
Q_ARG(QVariant, enemyP.y()+enemy->boundingRect().height()),
Q_ARG(QVariant, m_GameGml->boundingRect().height()));
}
break;
}
}
}
void GameEngine::doHitTest()
{
QMutexLocker locker(&m_enemyListMutex);
QDeclarativeItem* missile = 0;
QDeclarativeItem* enemy = 0;
if (m_enemyList.count()==0) {
enableEngineTimer(QVariant(false));
qDebug() << "No enemies left";
gameOver(true);
return;
}
if (!m_myShipGml) {
return;
}
if (m_myShipGml->opacity()==1) {
for (int e=0; e<m_enemyList.count(); e++) {
enemy = m_enemyList[e];
if (enemy->opacity()==0) {
break;
}
QPointF enemyP = enemy->pos();
if (m_enemiesGridGml) {
enemyP += m_enemiesGridGml->pos();
}
QRectF enemyR(enemyP,QSize(enemy->boundingRect().width(),enemy->boundingRect().height()));
if (enemyR.contains(m_myShipGml->pos())) {
enableEngineTimer(QVariant(false));
QPointF myP = m_myShipGml->pos();
playSound(1);
QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
m_myShipGml->setOpacity(0);
gameOver(false);
qDebug() << "Collision";
return;
}
else if (enemyR.bottomLeft().y() > m_myShipGml->pos().y()+m_myShipGml->pos().y()*0.1) {
enableEngineTimer(QVariant(false));
QPointF myP = m_myShipGml->pos();
playSound(1);
QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
m_myShipGml->setOpacity(0);
gameOver(false);
qDebug() << "Enemy too deep";
return;
}
}
}
foreach (missile, m_missileList) {
if (missile->opacity()==1){
for (int e=0; e<m_enemyList.count(); e++) {
enemy = m_enemyList[e];
if (enemy->opacity()<1) {
break;
}
QPointF missileP = missile->pos();
missileP.setX(missileP.rx() + missile->boundingRect().width()/2);
QPointF enemyP = enemy->pos();
if (m_enemiesGridGml) {
enemyP += m_enemiesGridGml->pos();
}
QRectF r(enemyP,QSize(enemy->boundingRect().width(),enemy->boundingRect().height()));
if (r.contains(missileP)) {
playSound(0);
QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
Q_ARG(QVariant, enemyP.x()+enemy->boundingRect().width()/2),
Q_ARG(QVariant, enemyP.y()+enemy->boundingRect().height()));
missile->setOpacity(0);
if (m_enemiesGridGml) {
enemy->setProperty("source",QVariant("file:/"+m_gameLevel->pathToTransparentEnemyPic().toString()));
} else {
enemy->setOpacity(0);
}
m_enemyList.removeAt(e);
e--;
}
enemy = 0;
}
}
}
if (m_myShipGml->opacity()==1) {
foreach (missile, m_enemyMissileList) {
if (missile->opacity()==1){
QPointF missileP = missile->pos();
missileP.setX(missileP.rx() + missile->boundingRect().width()/2);
QPointF myP = m_myShipGml->pos();
QRectF r(myP,QSize(m_myShipGml->boundingRect().width(),m_myShipGml->boundingRect().height()));
if (r.contains(missileP)) {
playSound(1);
QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
missile->setOpacity(0);
m_myShipGml->setOpacity(0);
break;
}
}
}
} else {
enableEngineTimer(QVariant(false));
gameOver(false);
qDebug() << "You was killed by enemy missile";
}
}
void GameEngine::playSound(QVariant index)
{
if (!m_silent) {
int i = index.toInt();
m_soundEngine->playSound(i);
}
}
void GameEngine::playSounds(QVariant index, QVariant count)
{
if (!m_silent) {
m_soundEngine->playSounds(index.toInt(),count.toInt());
}
}
void GameEngine::playInternalSound(QVariant index)
{
if (!m_silent) {
m_soundEngine->playInternalSound(index.toInt());
}
}
void GameEngine::playInternalSounds(QVariant index, QVariant count)
{
if (!m_silent) {
m_soundEngine->playInternalSounds(index.toInt(),count.toInt());
}
}
void GameEngine::gameOver(bool youWin)
{
qDebug() << "GameEngine::gameOver() "<< youWin;
QMetaObject::invokeMethod(m_GameGml, "gameOver", Qt::AutoConnection,Q_ARG(QVariant, youWin));
}
void GameEngine::pauseGame() {
QMetaObject::invokeMethod(m_GameGml, "pauseGame", Qt::AutoConnection);
}
QVariant GameEngine::isSymbian()
{
#ifdef Q_OS_SYMBIAN
return QVariant(true);
#else
return QVariant(false);
#endif
}
QVariant GameEngine::isMaemo()
{
#ifdef Q_WS_MAEMO_5
return QVariant(true);
#else
return QVariant(false);
#endif
}
QVariant GameEngine::isWindows()
{
#ifdef Q_OS_WIN
return QVariant(true);
#else
return QVariant(false);
#endif
}
void GameEngine::vibra()
{
#ifdef Q_OS_SYMBIAN
if (iVibrate){
TRAPD(err, iVibrate->StartVibraL(4000,KHWRMVibraMaxIntensity));
}
#endif
}
void GameEngine::fastVibra()
{
#ifdef Q_OS_SYMBIAN
if (iVibrate){
TRAPD(err, iVibrate->StartVibraL(100,KHWRMVibraMaxIntensity));
}
#endif
}
void GameEngine::openLink(QVariant link)
{
QDesktopServices::openUrl(QUrl(link.toString()));
}