/****************************************************************************
**
** 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>constint 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 randomQTime 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 =newQSystemDeviceInfo(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_SYMBIANdelete iVibrate;
#endif
}
void GameEngine::gameStartSound()
{
if (!m_silent)
m_soundEngine->gameStartSound();
}
#if defined Q_OS_SYMBIAN || defined Q_WS_MAEMO_5void GameEngine::currentProfileChanged(QSystemDeviceInfo::Profile p)
{
if (p ==QSystemDeviceInfo::SilentProfile) {
enableSounds(QVariant(false));
} else {
enableSounds(QVariant(true));
}
}
#endifvoid GameEngine::enableSounds(QVariant enable)
{
m_silent =!enable.toBool();
if (m_silent)
this->m_soundEngine->enableSounds(false);
elsethis->m_soundEngine->enableSounds(true);
}
QVariant GameEngine::randInt(QVariant low,QVariant high)
{
// Random number between low and highreturn 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 useQMetaObject::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_5if (s.contains("LIB")) {
s = s.right(s.length() - (s.indexOf("LIB")+3));
}
#endif
list.append(s);
}
returnQVariant(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);
} elseif (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);
}
elseif (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 fireint 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 collisionif (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 explosionQPointF 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?elseif (enemyR.bottomLeft().y() > m_myShipGml->pos().y()+m_myShipGml->pos().y()*0.1) {
enableEngineTimer(QVariant(false));
// Enemy too deep explosionQPointF 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 youif (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_SYMBIANreturnQVariant(true);
#elsereturnQVariant(false);
#endif
}
QVariant GameEngine::isMaemo()
{
#ifdef Q_WS_MAEMO_5returnQVariant(true);
#elsereturnQVariant(false);
#endif
}
QVariant GameEngine::isWindows()
{
#ifdef Q_OS_WINreturnQVariant(true);
#elsereturnQVariant(false);
#endif
}
void GameEngine::vibra()
{
#ifdef Q_OS_SYMBIANif (iVibrate){
TRAPD(err, iVibrate->StartVibraL(4000,KHWRMVibraMaxIntensity));
}
#endif
}
void GameEngine::fastVibra()
{
#ifdef Q_OS_SYMBIANif (iVibrate){
TRAPD(err, iVibrate->StartVibraL(100,KHWRMVibraMaxIntensity));
}
#endif
}
void GameEngine::openLink(QVariant link)
{
QDesktopServices::openUrl(QUrl(link.toString()));
}
Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter
ou par MP !