diff options
Diffstat (limited to 'demos/mobile/quickhit/gameengine.cpp')
-rw-r--r-- | demos/mobile/quickhit/gameengine.cpp | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/demos/mobile/quickhit/gameengine.cpp b/demos/mobile/quickhit/gameengine.cpp new file mode 100644 index 0000000..99e7d53 --- /dev/null +++ b/demos/mobile/quickhit/gameengine.cpp @@ -0,0 +1,592 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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(); + + // For random + QTime time = QTime::currentTime(); + qsrand((uint)time.msec()); + + // Sound engine + m_soundEngine = new CInvSounds(this); + + // Device profile + m_silent = false; + +#ifdef Q_OS_SYMBIAN + iVibrate = CHWRMVibra::NewL(); +#endif + + // Get device profile, is it silent? +#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) +{ + // Random number between low and high + return qrand() % ((high.toInt() + 1) - low.toInt()) + low.toInt(); +} + +void GameEngine::setGameLevel(LevelPluginInterface* level) +{ + // Set used game level + m_gameLevel = level; + + if (m_gameLevel) { + // Set used sound from the level into sound engine + m_soundEngine->enableSounds(m_gameLevel->levelSounds()); + // Invoke QML to take new level in use + 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()"; + + // Find Missiles objects + m_missileList.clear(); + m_enemyMissileList.clear(); + findMissiles(m_GameGml); + + // Set QMLs + setLevelQml(m_GameGml->findChild<QObject*>("level")); + setEnemiesGridQml(m_GameGml->findChild<QObject*>("enemiesGrid")); + setMyShipQml(m_GameGml->findChild<QObject*>("myShip")); + + // Find Enemies objects + 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; + //m_GameGml = 0; // NOTE: Do not delete this +} + + +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") { + //qDebug() << "Enemy children found from: " << item->objectName(); + findEnemies(item); + } else { + if (item->objectName()=="enemy") { + //qDebug() << "Enemy child founds: " << item->objectName(); + 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) { + // Do hit test + doHitTest(); + + m_doEnemyMissile--; + + if (m_gameLevel && m_doEnemyMissile<0) { + m_doEnemyMissile = m_gameLevel->enemyFireSpeed().toInt() / TIMER_SPEED; + // Do emeny missile launch + 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; + + // Find free missile + foreach (missile, m_enemyMissileList) { + if (missile->opacity()==0){ + // Random select enemy who fire + 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(); + } + //qDebug() << "QMetaObject::invokeMethod() - fireEnemyMissile"; + 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; + + // No enemies? + if (m_enemyList.count()==0) { + enableEngineTimer(QVariant(false)); + qDebug() << "No enemies left"; + gameOver(true); + return; + } + + if (!m_myShipGml) { + return; + } + + // Check ship collision + 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())); + // Collision? + if (enemyR.contains(m_myShipGml->pos())) { + enableEngineTimer(QVariant(false)); + + // Collision explosion + 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; + } + // Enemy too deep? + else if (enemyR.bottomLeft().y() > m_myShipGml->pos().y()+m_myShipGml->pos().y()*0.1) { + enableEngineTimer(QVariant(false)); + + // Enemy too deep explosion + 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; + } + } + } + + // Check your missiles hit to enemies + 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)) { + // Hit ! + playSound(0); + //qDebug() << "QMetaObject::invokeMethod() - explode"; + 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); + //fastVibra(); + if (m_enemiesGridGml) { + // Set transparent placeholder for enemy when using GridView + enemy->setProperty("source",QVariant("file:/"+m_gameLevel->pathToTransparentEnemyPic().toString())); + } else { + // Hide enemy after explode + enemy->setOpacity(0); + } + + // Remove enemy from list + m_enemyList.removeAt(e); + e--; + } + enemy = 0; + } + } + } + + // Check enemies missiles hit to you + 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)) { + // Hit ! + playSound(1); + //qDebug() << "QMetaObject::invokeMethod() - explode"; + 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 { + // You was killed + 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())); +} + |