gameengine.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * Copyright (c) 2010 Nokia Corporation.
  3. */
  4. #include "gameengine.h"
  5. #include "plugins/levelplugininterface.h"
  6. #include "InvSounds.h"
  7. #include <QDebug>
  8. #include <QTimerEvent>
  9. #include <QTime>
  10. #include <QDesktopServices>
  11. const int TIMER_SPEED = 80;
  12. GameEngine::GameEngine(QObject* parent)
  13. :QObject(parent)
  14. {
  15. m_timerId = 0;
  16. m_doEnemyMissile = 1500 / TIMER_SPEED;
  17. m_GameGml = 0;
  18. m_gameLevel = 0;
  19. clearQmlObjects();
  20. // For random
  21. QTime time = QTime::currentTime();
  22. qsrand((uint)time.msec());
  23. // Sound engine
  24. m_soundEngine = new CInvSounds(this);
  25. // Device profile
  26. m_silent = false;
  27. #ifdef Q_OS_SYMBIAN
  28. iVibrate = CHWRMVibra::NewL();
  29. #endif
  30. // Get device profile, is it silent?
  31. #if defined Q_OS_SYMBIAN || defined Q_WS_MAEMO_5
  32. m_systemDeviceInfo = new QSystemDeviceInfo(this);
  33. QObject::connect(m_systemDeviceInfo,SIGNAL(currentProfileChanged(QSystemDeviceInfo::Profile)),this,
  34. SLOT(currentProfileChanged(QSystemDeviceInfo::Profile)));
  35. QSystemDeviceInfo::Profile p = m_systemDeviceInfo->currentProfile();
  36. if (p == QSystemDeviceInfo::SilentProfile) {
  37. m_silent = true;
  38. }
  39. #endif
  40. }
  41. GameEngine::~GameEngine()
  42. {
  43. #ifdef Q_OS_SYMBIAN
  44. delete iVibrate;
  45. #endif
  46. }
  47. void GameEngine::gameStartSound()
  48. {
  49. if (!m_silent)
  50. m_soundEngine->gameStartSound();
  51. }
  52. #if defined Q_OS_SYMBIAN || defined Q_WS_MAEMO_5
  53. void GameEngine::currentProfileChanged(QSystemDeviceInfo::Profile p)
  54. {
  55. if (p == QSystemDeviceInfo::SilentProfile) {
  56. enableSounds(QVariant(false));
  57. } else {
  58. enableSounds(QVariant(true));
  59. }
  60. }
  61. #endif
  62. void GameEngine::enableSounds(QVariant enable)
  63. {
  64. m_silent = !enable.toBool();
  65. if (m_silent)
  66. this->m_soundEngine->enableSounds(false);
  67. else
  68. this->m_soundEngine->enableSounds(true);
  69. }
  70. QVariant GameEngine::randInt(QVariant low, QVariant high)
  71. {
  72. // Random number between low and high
  73. return qrand() % ((high.toInt() + 1) - low.toInt()) + low.toInt();
  74. }
  75. void GameEngine::setGameLevel(LevelPluginInterface* level)
  76. {
  77. // Set used game level
  78. m_gameLevel = level;
  79. if (m_gameLevel) {
  80. // Set used sound from the level into sound engine
  81. m_soundEngine->enableSounds(m_gameLevel->levelSounds());
  82. // Invoke QML to take new level in use
  83. QMetaObject::invokeMethod(m_GameGml, "levelReadyForCreation", Qt::AutoConnection);
  84. m_doEnemyMissile = m_gameLevel->enemyFireSpeed().toInt() / TIMER_SPEED;
  85. }
  86. }
  87. void GameEngine::setPluginList(QList<QPluginLoader*> plugins)
  88. {
  89. m_pluginList = plugins;
  90. }
  91. QVariant GameEngine::pluginList()
  92. {
  93. QStringList list;
  94. QPluginLoader* loader;
  95. foreach(loader,m_pluginList) {
  96. QString s = loader->fileName();
  97. s = s.mid(s.lastIndexOf("/")+1);
  98. s = s.left(s.lastIndexOf("."));
  99. s = s.toUpper();
  100. #ifdef Q_WS_MAEMO_5
  101. if (s.contains("LIB")) {
  102. s = s.right(s.length() - (s.indexOf("LIB")+3));
  103. }
  104. #endif
  105. list.append(s);
  106. }
  107. return QVariant(list);
  108. }
  109. void GameEngine::pauseLevel(QVariant doPause)
  110. {
  111. bool enableTimer = !doPause.toBool();
  112. enableEngineTimer(QVariant(enableTimer));
  113. QMetaObject::invokeMethod(m_levelQml, "pause", Qt::AutoConnection,Q_ARG(QVariant, doPause));
  114. }
  115. void GameEngine::findQmlObjects()
  116. {
  117. if (m_GameGml) {
  118. qDebug() << "GameEngine::findQmlObjects()";
  119. // Find Missiles objects
  120. m_missileList.clear();
  121. m_enemyMissileList.clear();
  122. findMissiles(m_GameGml);
  123. // Set QMLs
  124. setLevelQml(m_GameGml->findChild<QObject*>("level"));
  125. setEnemiesGridQml(m_GameGml->findChild<QObject*>("enemiesGrid"));
  126. setMyShipQml(m_GameGml->findChild<QObject*>("myShip"));
  127. // Find Enemies objects
  128. m_enemyList.clear();
  129. qDebug() << "GameEngine::findQmlObjects() find enemies from: level QML";
  130. findEnemies(m_levelQml);
  131. } else {
  132. qDebug() << "GameEngine::findQmlObjects() rootObject NULL";
  133. }
  134. }
  135. void GameEngine::clearQmlObjects()
  136. {
  137. m_missileList.clear();
  138. m_enemyMissileList.clear();
  139. m_enemyList.clear();
  140. m_levelQml = 0;
  141. m_enemiesGridGml = 0;
  142. m_myShipGml = 0;
  143. //m_GameGml = 0; // NOTE: Do not delete this
  144. }
  145. void GameEngine::findMissiles(QObject *rootObject)
  146. {
  147. if (rootObject) {
  148. QObjectList list = rootObject->children();
  149. QObject* item;
  150. foreach(item,list) {
  151. if (item->children().count()>0) {
  152. findMissiles(item);
  153. } else {
  154. if (rootObject->objectName()=="missile") {
  155. QDeclarativeItem* missile = static_cast<QDeclarativeItem*>(rootObject);
  156. m_missileList.append(missile);
  157. } else if (rootObject->objectName()=="enemy_missile") {
  158. QDeclarativeItem* enemyMissile = static_cast<QDeclarativeItem*>(rootObject);
  159. m_enemyMissileList.append(enemyMissile);
  160. }
  161. }
  162. }
  163. } else {
  164. qDebug() << "GameEngine::findMissiles() rootObject NULL";
  165. }
  166. }
  167. void GameEngine::findEnemies(QObject *rootObject)
  168. {
  169. if (rootObject) {
  170. QObjectList list = rootObject->children();
  171. QObject* item;
  172. foreach(item,list) {
  173. if (item->children().count()>0 && item->objectName()!="enemy") {
  174. //qDebug() << "Enemy childs founds from: " << item->objectName();
  175. findEnemies(item);
  176. } else {
  177. if (item->objectName()=="enemy") {
  178. //qDebug() << "Enemy child founds: " << item->objectName();
  179. QDeclarativeItem* enemy = static_cast<QDeclarativeItem*>(item);
  180. m_enemyList.append(enemy);
  181. }
  182. }
  183. }
  184. } else {
  185. qDebug() << "GameEngine::findEnemies() rootObject NULL";
  186. }
  187. }
  188. void GameEngine::setEnemiesGridQml(QObject* o)
  189. {
  190. m_enemiesGridGml = static_cast<QDeclarativeItem*>(o);
  191. }
  192. void GameEngine::setMyShipQml(QObject* o)
  193. {
  194. m_myShipGml = static_cast<QDeclarativeItem*>(o);
  195. }
  196. void GameEngine::setGameQml(QObject* o)
  197. {
  198. m_GameGml = static_cast<QDeclarativeItem*>(o);
  199. }
  200. void GameEngine::timerEvent(QTimerEvent *e)
  201. {
  202. if (e->timerId()==m_timerId) {
  203. // Do hit test
  204. doHitTest();
  205. m_doEnemyMissile--;
  206. if (m_gameLevel && m_doEnemyMissile<0) {
  207. m_doEnemyMissile = m_gameLevel->enemyFireSpeed().toInt() / TIMER_SPEED;
  208. // Do emeny missile launch
  209. doEnemyMissile();
  210. }
  211. }
  212. }
  213. void GameEngine::enableEngineTimer(QVariant enable)
  214. {
  215. if (m_gameLevel) {
  216. if (m_timerId==0 && enable.toBool()) {
  217. m_timerId = QObject::startTimer(TIMER_SPEED);
  218. }
  219. else if (m_timerId != 0 && !enable.toBool()) {
  220. QObject::killTimer(m_timerId);
  221. m_timerId = 0;
  222. }
  223. }
  224. }
  225. void GameEngine::selectVisibleEnemy(int& start, int& end)
  226. {
  227. QDeclarativeItem* enemy = 0;
  228. for(int i=0 ; i<m_enemyList.count() ; i++) {
  229. enemy = m_enemyList[i];
  230. if (enemy->opacity()==1) {
  231. start = i;
  232. break;
  233. }
  234. }
  235. enemy = 0;
  236. for(int e=m_enemyList.count()-1 ; e>0 ; e--) {
  237. enemy = m_enemyList[e];
  238. if (enemy->opacity()==1) {
  239. end = e;
  240. break;
  241. }
  242. }
  243. }
  244. void GameEngine::doEnemyMissile()
  245. {
  246. QMutexLocker locker(&m_enemyListMutex);
  247. QDeclarativeItem* missile = 0;
  248. QDeclarativeItem* enemy = 0;
  249. // Find free missile
  250. foreach(missile, m_enemyMissileList) {
  251. if (missile->opacity()==0){
  252. // Random select enemy who fire
  253. int start=0; int end=0;
  254. selectVisibleEnemy(start,end);
  255. int whoWillFire = randInt(QVariant(start),QVariant(end)).toInt();
  256. if (m_enemyList.count() < whoWillFire+1)
  257. break;
  258. enemy = m_enemyList.at(whoWillFire);
  259. if (enemy && enemy->opacity()==1) {
  260. QPointF enemyP = enemy->pos();
  261. if (m_enemiesGridGml) {
  262. enemyP += m_enemiesGridGml->pos();
  263. }
  264. //qDebug() << "QMetaObject::invokeMethod() - fireEnemyMissile";
  265. QMetaObject::invokeMethod(m_GameGml, "fireEnemyMissile", Qt::AutoConnection,
  266. Q_ARG(QVariant, enemyP.x()+enemy->boundingRect().width()/4),
  267. Q_ARG(QVariant, enemyP.y()+enemy->boundingRect().height()),
  268. Q_ARG(QVariant, m_GameGml->boundingRect().height()));
  269. }
  270. break;
  271. }
  272. }
  273. }
  274. void GameEngine::doHitTest()
  275. {
  276. QMutexLocker locker(&m_enemyListMutex);
  277. QDeclarativeItem* missile = 0;
  278. QDeclarativeItem* enemy = 0;
  279. // No enemies?
  280. if (m_enemyList.count()==0) {
  281. enableEngineTimer(QVariant(false));
  282. qDebug() << "No enemies left";
  283. gameOver(true);
  284. return;
  285. }
  286. if (!m_myShipGml) {
  287. return;
  288. }
  289. // Check ship collision
  290. if (m_myShipGml->opacity()==1) {
  291. for(int e=0; e<m_enemyList.count(); e++) {
  292. enemy = m_enemyList[e];
  293. if (enemy->opacity()==0) {
  294. break;
  295. }
  296. QPointF enemyP = enemy->pos();
  297. if (m_enemiesGridGml) {
  298. enemyP += m_enemiesGridGml->pos();
  299. }
  300. QRectF enemyR(enemyP,QSize(enemy->boundingRect().width(),enemy->boundingRect().height()));
  301. // Collision?
  302. if (enemyR.contains(m_myShipGml->pos())) {
  303. enableEngineTimer(QVariant(false));
  304. // Collision explosion
  305. QPointF myP = m_myShipGml->pos();
  306. playSound(1);
  307. QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
  308. Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
  309. Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
  310. m_myShipGml->setOpacity(0);
  311. gameOver(false);
  312. qDebug() << "Collision";
  313. return;
  314. }
  315. // Enemy too deep?
  316. else if(enemyR.bottomLeft().y() > m_myShipGml->pos().y()+m_myShipGml->pos().y()*0.1) {
  317. enableEngineTimer(QVariant(false));
  318. // Enemy too deep explosion
  319. QPointF myP = m_myShipGml->pos();
  320. playSound(1);
  321. QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
  322. Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
  323. Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
  324. m_myShipGml->setOpacity(0);
  325. gameOver(false);
  326. qDebug() << "Enemy too deep";
  327. return;
  328. }
  329. }
  330. }
  331. // Check your missiles hit to enemies
  332. foreach(missile, m_missileList) {
  333. if (missile->opacity()==1){
  334. for(int e=0; e<m_enemyList.count(); e++) {
  335. enemy = m_enemyList[e];
  336. if (enemy->opacity()<1) {
  337. break;
  338. }
  339. QPointF missileP = missile->pos();
  340. missileP.setX(missileP.rx() + missile->boundingRect().width()/2);
  341. QPointF enemyP = enemy->pos();
  342. if (m_enemiesGridGml) {
  343. enemyP += m_enemiesGridGml->pos();
  344. }
  345. QRectF r(enemyP,QSize(enemy->boundingRect().width(),enemy->boundingRect().height()));
  346. if (r.contains(missileP)) {
  347. // Hit !
  348. playSound(0);
  349. //qDebug() << "QMetaObject::invokeMethod() - explode";
  350. QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
  351. Q_ARG(QVariant, enemyP.x()+enemy->boundingRect().width()/2),
  352. Q_ARG(QVariant, enemyP.y()+enemy->boundingRect().height()));
  353. missile->setOpacity(0);
  354. //fastVibra();
  355. if (m_enemiesGridGml) {
  356. // Set transparent placeholder for enemy when using GridView
  357. enemy->setProperty("source",QVariant("file:/"+m_gameLevel->pathToTransparentEnemyPic().toString()));
  358. } else {
  359. // Hide enemy after explode
  360. enemy->setOpacity(0);
  361. }
  362. // Remove enemy from list
  363. m_enemyList.removeAt(e);
  364. e--;
  365. }
  366. enemy = 0;
  367. }
  368. }
  369. }
  370. // Check enemies missiles hit to you
  371. if (m_myShipGml->opacity()==1) {
  372. foreach(missile, m_enemyMissileList) {
  373. if (missile->opacity()==1){
  374. QPointF missileP = missile->pos();
  375. missileP.setX(missileP.rx() + missile->boundingRect().width()/2);
  376. QPointF myP = m_myShipGml->pos();
  377. QRectF r(myP,QSize(m_myShipGml->boundingRect().width(),m_myShipGml->boundingRect().height()));
  378. if (r.contains(missileP)) {
  379. // Hit !
  380. playSound(1);
  381. //qDebug() << "QMetaObject::invokeMethod() - explode";
  382. QMetaObject::invokeMethod(m_levelQml, "explode", Qt::AutoConnection,
  383. Q_ARG(QVariant, myP.x()+m_myShipGml->boundingRect().width()/2),
  384. Q_ARG(QVariant, myP.y()+m_myShipGml->boundingRect().height()));
  385. missile->setOpacity(0);
  386. m_myShipGml->setOpacity(0);
  387. break;
  388. }
  389. }
  390. }
  391. } else {
  392. // You was killed
  393. enableEngineTimer(QVariant(false));
  394. gameOver(false);
  395. qDebug() << "You was killed by enemy missile";
  396. }
  397. }
  398. void GameEngine::playSound(QVariant index)
  399. {
  400. if (!m_silent) {
  401. int i = index.toInt();
  402. m_soundEngine->playSound(i);
  403. }
  404. }
  405. void GameEngine::playSounds(QVariant index, QVariant count)
  406. {
  407. if (!m_silent) {
  408. m_soundEngine->playSounds(index.toInt(),count.toInt());
  409. }
  410. }
  411. void GameEngine::playInternalSound(QVariant index)
  412. {
  413. if (!m_silent) {
  414. m_soundEngine->playInternalSound(index.toInt());
  415. }
  416. }
  417. void GameEngine::playInternalSounds(QVariant index, QVariant count)
  418. {
  419. if (!m_silent) {
  420. m_soundEngine->playInternalSounds(index.toInt(),count.toInt());
  421. }
  422. }
  423. void GameEngine::gameOver(bool youWin)
  424. {
  425. qDebug() << "GameEngine::gameOver() "<< youWin;
  426. QMetaObject::invokeMethod(m_GameGml, "gameOver", Qt::AutoConnection,Q_ARG(QVariant, youWin));
  427. }
  428. void GameEngine::pauseGame() {
  429. QMetaObject::invokeMethod(m_GameGml, "pauseGame", Qt::AutoConnection);
  430. }
  431. QVariant GameEngine::isSymbian()
  432. {
  433. #ifdef Q_OS_SYMBIAN
  434. return QVariant(true);
  435. #else
  436. return QVariant(false);
  437. #endif
  438. }
  439. QVariant GameEngine::isMaemo()
  440. {
  441. #ifdef Q_WS_MAEMO_5
  442. return QVariant(true);
  443. #else
  444. return QVariant(false);
  445. #endif
  446. }
  447. QVariant GameEngine::isWindows()
  448. {
  449. #ifdef Q_OS_WIN
  450. return QVariant(true);
  451. #else
  452. return QVariant(false);
  453. #endif
  454. }
  455. void GameEngine::vibra()
  456. {
  457. #ifdef Q_OS_SYMBIAN
  458. if (iVibrate){
  459. TRAPD(err, iVibrate->StartVibraL(4000,KHWRMVibraMaxIntensity));
  460. }
  461. #endif
  462. }
  463. void GameEngine::fastVibra()
  464. {
  465. #ifdef Q_OS_SYMBIAN
  466. if (iVibrate){
  467. TRAPD(err, iVibrate->StartVibraL(100,KHWRMVibraMaxIntensity));
  468. }
  469. #endif
  470. }
  471. void GameEngine::openLink(QVariant link)
  472. {
  473. QDesktopServices::openUrl(QUrl(link.toString()));
  474. }