PongApp.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include <memory.h>
  7. #include <stdlib.h>
  8. #include "PongApp.h"
  9. #include "SpriteBatch.h"
  10. void PongApp::readAudioStream(AUDIO_SAMPLE_TYPE *target, int sampleCount) {
  11. amixer->pullAudio(target, sampleCount);
  12. }
  13. GF::GameApp *GF::createGameApplication( GF::GameEngine *engine ) {
  14. return new PongApp( engine );
  15. }
  16. void PongApp::menuItemRender( void *data, GameMenu *menu, MenuItem *i ) {
  17. PongApp *app = (PongApp*)data;
  18. float scale = MENU_ITEM_HEIGHT/2.0f;
  19. int itemCount = menu->getItemCount();
  20. float ystart = -0.0 + scale*0.65f*itemCount;
  21. float ystep = MENU_ITEM_HEIGHT;
  22. float phase = menu->getLifeTime()*4.0f - (float)i->index;
  23. if (phase > 1.0f) phase = 1.0f;
  24. if (phase<0.0f) phase = 0.0f;
  25. FontWriter *w = app->getFontWriter();
  26. float a = phase*i->alpha;
  27. if (a>1.0f) a = 1.0f;
  28. if (i->selected==false) a -= menu->getDestroyAnimation();
  29. else a = a*(0.5f + cosf( menu->getDestroyAnimation() * 20.0f )*0.49f );
  30. if (i->keysEnabled) {
  31. if (i->keyfocus)
  32. {
  33. w->setColor( 1.0f, 1.0f, 1.0f, a );
  34. scale += 0.02f;
  35. } else w->setColor( 0.7f, 0.7f, 0.7f, a );
  36. } else w->setColor( 1.0f, 1.0f, 1.0f, a );
  37. w->writeText( i->label, -w->getTextWidth(i->label, scale)/2.0f+(1.0f-phase)*2.0f, ystart - ystep * (float)i->index, scale*phase );
  38. }
  39. GF::AudioBuffer *PongApp::loadWavFromResource( const char *name )
  40. {
  41. //qDebug() << "Loading wav from resource " << QString(name);
  42. int bin_res_size;
  43. void *bin_res = engine->loadBinaryResource( name, bin_res_size );
  44. if (bin_res && bin_res_size>0) {
  45. GF::AudioBuffer *rval = GF::AudioBuffer::loadWav( bin_res, bin_res_size );
  46. engine->releaseBinaryResource( bin_res );
  47. return rval;
  48. } else {
  49. return 0;
  50. }
  51. }
  52. PongApp::PongApp( GF::GameEngine *engine ) : GF::GameApp( engine ) {
  53. // read settings
  54. sensorGravity[0] = 0.0f;
  55. sensorGravity[1] = 0.0f;
  56. sensorGravity[2] = 0.0f;
  57. allowMainMenuCreation = true;
  58. currentMenu = 0;
  59. fontTexture = 0;
  60. volumeTexture = 0;
  61. topBarTexture = 0;
  62. playerPadTexture = 0;
  63. computerPadTexture = 0;
  64. ballTexture = 0;
  65. currentGame = 0;
  66. background1 = 0;
  67. highScores = 0;
  68. credits = 0;
  69. #ifdef MY_OS_MEEGO
  70. meegoSwipeTexture=0;
  71. #endif
  72. buttonDown[0] = false;
  73. pointerX[0] = 0.0f;
  74. pointerY[0] = 0.0f;
  75. buttonDown[1] = false;
  76. pointerX[1] = 0.0f;
  77. pointerY[1] = 0.0f;
  78. fontWriter = 0;
  79. pengine = 0;
  80. currentMenu = 0;
  81. musicBinaryResource = 0;
  82. musicBinaryResourceLength = 0;
  83. volumeIndicator = 0;
  84. amixer = new GF::AudioMixer();
  85. amixer->setGeneralVolume( 0.4f );
  86. MusicPlayer *musicPlayer = (MusicPlayer*)amixer->addAudioSource( new MusicPlayer() );
  87. char fullPath[1024];
  88. #ifdef EPONG_DEBUG
  89. sampleLatencyTest = loadWavFromResource( "shorttick.wav" );
  90. #else
  91. #ifdef USE_OGG
  92. //musicPlayer->play(engine->adjustPath("34141__ERH__swell_pad.ogg", fullPath, 1024));
  93. musicBinaryResource = engine->loadBinaryResource( "34141__ERH__swell_pad.ogg", musicBinaryResourceLength );
  94. if (musicBinaryResource) {
  95. musicPlayer->play( (const char*)musicBinaryResource, musicBinaryResourceLength );
  96. }
  97. #endif
  98. #ifdef USE_MP3
  99. musicPlayer->play(engine->adjustPath("34141__ERH__swell_pad.mp3", fullPath, 1024));
  100. #endif
  101. #endif
  102. sampleBallPong = loadWavFromResource( "ballpong.wav" );
  103. sampleMenuTick = loadWavFromResource("menuclick.wav");
  104. sampleGameOver = loadWavFromResource("gameover.wav");
  105. sampleLevelCompleted = loadWavFromResource("level_completed.wav");
  106. #ifdef IAP
  107. engine->getMiniIAPClient()->setMiniIAPReceiver(this);
  108. m_multiplayerPurchased = -1;
  109. #endif
  110. aeffectChannels = new GF::AudioBufferPlayInstance*[ AUDIO_EFFECT_CHANNELS ];
  111. for (int c=0; c<AUDIO_EFFECT_CHANNELS; c++) {
  112. aeffectChannels[c] = new GF::AudioBufferPlayInstance();
  113. aeffectChannels[c]->setDestroyWhenFinished( false );
  114. amixer->addAudioSource( aeffectChannels[c] );
  115. }
  116. background1 = new PongBackground(0, engine, this );
  117. engine->startAudio(AUDIO_FREQUENCY, 2);
  118. }
  119. void PongApp::notifyEvent( GF::NOTIFY_EVENT_TYPE type, int flags ) {
  120. switch (type) {
  121. case GF::NE_PAUSED:
  122. if (currentGame && currentGame->getGameState() == PGS_RUNNING && !currentMenu)
  123. currentMenu = createPauseMenu();
  124. break;
  125. case GF::NE_VOLUME_CHANGED:
  126. amixer->setGeneralVolume( (float)flags/100.0f*0.7f );
  127. if (flags<1)
  128. volumeIndicator = 4;
  129. else volumeIndicator = (flags-1) * 4 / 100;
  130. break;
  131. };
  132. }
  133. GameMenu* PongApp::createMainMenu() {
  134. // create menu
  135. GameMenu *m = new GameMenu( menuItemRender, this );
  136. m->addMenuItem( "start", "start_game" );
  137. #ifdef IAP
  138. if (m_multiplayerPurchased == -1) {
  139. // "Delayed initialisation" of m_multiplayerPurchased
  140. if (engine->getMiniIAPClient()->isProductPurchased(EPongIAP::IAP_ITEM_ID, EPongIAP::IAP_FILE)) {
  141. m_multiplayerPurchased = 3;
  142. }
  143. else {
  144. m_multiplayerPurchased = 0;
  145. }
  146. }
  147. if (m_multiplayerPurchased == 3) {
  148. m->addMenuItem( "start 2 player", "start_mp_game" );
  149. }
  150. else {
  151. m->addMenuItem( "buy 2 player game", "buy_mp_game" );
  152. }
  153. #else
  154. m->addMenuItem( "start 2 player", "start_mp_game" );
  155. #endif
  156. m->addMenuItem( "highscores", "show_scores" );
  157. #ifdef TRIAL_VERSION
  158. m->addMenuItem( "buy now", "buy_now" );
  159. #endif
  160. m->addMenuItem( "credits", "show_credits" );
  161. //MenuItem *i = currentMenu->addMenuItem( "settings", "goto_settings" );
  162. m->addMenuItem( "exit", "exit_query" );
  163. return m;
  164. };
  165. GameMenu* PongApp::createExitQuery() {
  166. GameMenu *m = new GameMenu( menuItemRender, this );
  167. m->addMenuItem( "yes", "exit" );
  168. m->addMenuItem( "no", "void" );
  169. return m;
  170. };
  171. GameMenu* PongApp::createPauseMenu() {
  172. engine->stopSensors();
  173. GameMenu *m = new GameMenu( menuItemRender, this );
  174. m->addMenuItem( "resume", "void" );
  175. m->addMenuItem( "end game", "cancel_game" );
  176. return m;
  177. };
  178. PongApp::~PongApp() {
  179. engine->stopAudio();
  180. if (amixer) delete amixer;
  181. if (background1) delete background1;
  182. if (currentMenu) delete currentMenu;
  183. if (currentGame) delete currentGame;
  184. if (highScores) delete highScores;
  185. if (credits) delete credits;
  186. if (sampleBallPong) delete sampleBallPong;
  187. if (sampleMenuTick) delete sampleMenuTick;
  188. if (sampleGameOver) delete sampleGameOver;
  189. if (sampleLevelCompleted) delete sampleLevelCompleted;
  190. // Release musicBinaryResource
  191. if (musicBinaryResource) {
  192. engine->releaseBinaryResource( musicBinaryResource );
  193. musicBinaryResource = 0;
  194. musicBinaryResourceLength = 0;
  195. }
  196. if (aeffectChannels) delete [] aeffectChannels;
  197. #ifdef EPONG_DEBUG
  198. if (sampleLatencyTest) delete sampleLatencyTest;
  199. #endif
  200. }
  201. void PongApp::playSoundEffect( GF::AudioBuffer *buffer, float volume, float leftright ) {
  202. int c = 0;
  203. while (c<AUDIO_EFFECT_CHANNELS && aeffectChannels[c]->isPlaying() == true) c++;
  204. if (c>=AUDIO_EFFECT_CHANNELS) return; // no free channel
  205. if (leftright<-1.0f) leftright = -1.0f;
  206. if (leftright>1.0f) leftright = 1.0f;
  207. // play with channel c
  208. aeffectChannels[c]->playBuffer( buffer, volume, 1.0f );
  209. aeffectChannels[c]->setLeftVolume( 0.5f - leftright*0.5f);
  210. aeffectChannels[c]->setRightVolume( 0.5 + leftright*0.5f);
  211. }
  212. bool PongApp::prepare() {
  213. fontTexture = engine->loadGLTexture("font.png");
  214. topBarTexture = engine->loadGLTexture("top_bar.png");
  215. volumeTexture = engine->loadGLTexture("control_button.png");
  216. playerPadTexture = engine->loadGLTexture("stick_blue_64x256.png");
  217. computerPadTexture = engine->loadGLTexture("stick_red_64x256.png");
  218. ballTexture = engine->loadGLTexture("ball_64x64.png");
  219. ballShineTexture = engine->loadGLTexture("ball_shine.png");
  220. #ifdef MY_OS_MEEGO
  221. meegoSwipeTexture = engine->loadGLTexture("meego_swipe.png");
  222. #endif
  223. pengine = new ParticleEngine( MAX_PARTICLES );
  224. // Particle types
  225. ballFlyParticleType = new ParticleType( ballShineTexture );
  226. ballFlyParticleType->m_lifeTime = 2000;
  227. ballFlyParticleType->m_lifeTimeRandom = 9000;
  228. ballFlyParticleType->m_size = 6000;
  229. ballFlyParticleType->m_sizeRandom = 10000;
  230. ballFlyParticleType->m_sizeIncRandom = -20000;
  231. ballFlyParticleType->m_additiveParticle = true;
  232. ballHitParticleType = new ParticleType( ballShineTexture );
  233. ballHitParticleType->m_lifeTime = 4000;
  234. ballHitParticleType->m_lifeTimeRandom = 0;
  235. ballHitParticleType->m_size = 1600;
  236. ballHitParticleType->m_sizeInc = 16000*150;
  237. ballHitParticleType->m_sizeIncInc = -2000;
  238. ballHitParticleType->m_additiveParticle = true;
  239. ballHitParticleType->setVisibility(0.0f, 0.3f, 0.6f );
  240. spriteBatch = SpriteBatch::createInstance(currentWidth, currentHeight);
  241. fontWriter = new FontWriter( spriteBatch, fontTexture, 8,6, "abcdefghijklmnopqrstuvwxyz0123456789,.!?()/&%#\"=" );
  242. if (background1) background1->prepare();
  243. if (currentGame && currentGame->getGameState() == PGS_RUNNING) {
  244. engine->startSensors();
  245. }
  246. return true;
  247. }
  248. void PongApp::release() {
  249. if (topBarTexture) engine->releaseTexture(topBarTexture);
  250. if (volumeTexture) engine->releaseTexture(volumeTexture);
  251. if (fontTexture) engine->releaseTexture(fontTexture);
  252. if (computerPadTexture) engine->releaseTexture(computerPadTexture);
  253. if (playerPadTexture) engine->releaseTexture(playerPadTexture);
  254. if (ballTexture) engine->releaseTexture(ballTexture);
  255. if (ballShineTexture) engine->releaseTexture(ballShineTexture);
  256. #ifdef MY_OS_MEEGO
  257. if (meegoSwipeTexture) engine->releaseTexture(meegoSwipeTexture);
  258. meegoSwipeTexture=0;
  259. #endif
  260. topBarTexture=0;
  261. volumeTexture=0;
  262. computerPadTexture = 0;
  263. playerPadTexture = 0;
  264. ballTexture = 0;
  265. ballShineTexture = 0;
  266. fontTexture = 0;
  267. if (pengine) delete pengine;
  268. if (ballFlyParticleType) delete ballFlyParticleType;
  269. if (ballHitParticleType) delete ballHitParticleType;
  270. ballFlyParticleType = 0;
  271. ballHitParticleType = 0;
  272. pengine = 0;
  273. if (fontWriter) delete fontWriter;
  274. fontWriter = 0;
  275. if (background1) background1->release();
  276. engine->stopSensors();
  277. if (spriteBatch) delete spriteBatch;
  278. spriteBatch = 0;
  279. }
  280. void PongApp::resize( int w, int h ) {
  281. float mproj[16] = {
  282. 1.0f, 0, 0, 0,
  283. 0, (float)w / (float)h, 0, 0,
  284. 0, 0, 0, 0,
  285. 0, 0, 0, 1,
  286. };
  287. memcpy( matrixProjection, mproj, sizeof( float ) * 16 );
  288. currentWidth = w;
  289. currentHeight = h;
  290. spriteBatch->setTargetSize(w, h);
  291. #if defined(USE_GLES11) || defined(USE_GLES20)
  292. glViewport(0,0, currentWidth, currentHeight );
  293. #endif
  294. }
  295. void PongApp::update( float realframeTime ) {
  296. static float frameTime = 1/60.0f;
  297. frameTime = frameTime*.75 + .25*realframeTime;
  298. if (!currentMenu && !currentGame && !highScores && !credits && allowMainMenuCreation==true) {
  299. currentMenu = createMainMenu();
  300. };
  301. if (credits) {
  302. if (credits->update( frameTime ) == 0) {
  303. delete credits;
  304. credits = 0;
  305. };
  306. };
  307. if (highScores) {
  308. if (highScores->update( frameTime ) == 0) {
  309. delete highScores;
  310. highScores = 0;
  311. };
  312. }
  313. if (background1) {
  314. if (background1->update( frameTime ) == false) {
  315. delete background1;
  316. background1 = 0;
  317. };
  318. };
  319. if (currentMenu) {
  320. const char *command = currentMenu->run( frameTime );
  321. if (command) {
  322. GameMenu *newMenu = 0;
  323. // command has been triggered from the menu
  324. if (strcmp( command, "exit_query") == 0) {
  325. //newMenu = createExitQuery();
  326. engine->exit();
  327. } else if (strcmp( command, "start_game") == 0) {
  328. restartGame(true);
  329. #ifdef IAP
  330. } else if (strncmp( command, "buy_mp_game", 11) == 0) {
  331. if ((strcmp(command, "buy_mp_game") == 0) && (m_multiplayerPurchased == 0 || m_multiplayerPurchased == 4)) {
  332. engine->setUpdateAndPauseState(false, true);
  333. engine->getMiniIAPClient()->prepare();
  334. engine->setUpdateAndPauseState(false, true);
  335. m_multiplayerPurchased = 1;
  336. newMenu = createWaitingIAPMenu();
  337. }
  338. else if (strcmp(command, "buy_mp_game_waiting") == 0) {
  339. if (m_multiplayerPurchased == 1) {
  340. m_multiplayerPurchased = 2;
  341. engine->setUpdateAndPauseState(true, true);
  342. if (engine->getMiniIAPClient()->purchaseProduct(EPongIAP::IAP_ITEM_ID)) {
  343. engine->setUpdateAndPauseState(true, true);
  344. newMenu = createWaitingIAPMenu();
  345. }
  346. else {
  347. engine->setUpdateAndPauseState(false, false);
  348. }
  349. }
  350. else if (m_multiplayerPurchased == 2) {
  351. newMenu = createWaitingIAPMenu();
  352. }
  353. }
  354. else if (strcmp(command,"buy_mp_game_cancel") == 0) {
  355. m_multiplayerPurchased = 4;
  356. engine->setUpdateAndPauseState(false, false);
  357. // case: "buy_mp_game_ok" -> nothing
  358. // case: "buy_mp_game_bypass" -> nothing
  359. }
  360. //qDebug() << "buy_mp_game..., command" << command << (newMenu == 0? "no new menu":"new menu!");
  361. #endif
  362. } else if (strcmp( command, "start_mp_game") == 0) {
  363. restartGame(false);
  364. } else if (strcmp( command, "show_scores") == 0) {
  365. if (highScores) delete highScores;
  366. highScores = new PongHighScores(this);
  367. } else if (strcmp( command, "buy_now") == 0) {
  368. engine->openUrlInBrowser( "http://store.ovi.com" );
  369. } else if (strcmp( command, "cancel_game") == 0) {
  370. if (currentGame) {
  371. delete currentGame;
  372. currentGame = 0;
  373. }
  374. } else if (strcmp( command, "show_credits") == 0) {
  375. if (credits) delete credits;
  376. credits = new PongCredits(this);
  377. };
  378. delete currentMenu;
  379. if (!newMenu && currentGame && currentGame->getGameState() == PGS_RUNNING) {
  380. // return to game
  381. engine->startSensors();
  382. }
  383. currentMenu = newMenu;
  384. };
  385. }
  386. if (currentGame && !currentMenu) {
  387. if (!currentGame->update( frameTime, buttonDown, pointerX, pointerY)) {
  388. if (currentGame->isSinglePlayer()) {
  389. allowMainMenuCreation =false;
  390. int score = currentGame->getScore();
  391. delete currentGame;
  392. currentGame = 0;
  393. if (highScores) delete highScores;
  394. highScores = new PongHighScores( this, score );
  395. allowMainMenuCreation = true;
  396. } else {
  397. delete currentGame;
  398. currentGame = 0;
  399. }
  400. }
  401. }
  402. if (pengine) {
  403. pengine->setGravity( sensorGravity );
  404. pengine->run( frameTime );
  405. };
  406. }
  407. #define TOP_BAR_HEIGHT 0.06f
  408. void PongApp::render() {
  409. spriteBatch->begin(SpriteBatch::eALPHA, SpriteBatch::eCUSTOMPROJECTION, matrixProjection );
  410. static float ftest = 0.0f;
  411. ftest+=0.01f;
  412. float camx = cosf( ftest );
  413. float camy = sinf( ftest );
  414. if (background1) {
  415. background1->render(camx, camy);
  416. }
  417. if (credits) credits->render();
  418. if (highScores) highScores->render();
  419. if (currentGame) currentGame->render();
  420. if (currentMenu) currentMenu->render();
  421. // top bar
  422. SpriteDrawInfo sdi;
  423. sdi.setScale(2.0f,2.0f*TOP_BAR_HEIGHT);
  424. sdi.setTargetPos(0, getTop()-TOP_BAR_HEIGHT);
  425. sdi.setSourceRect(0,0,1,0.97f);
  426. sdi.textureHandle = topBarTexture;
  427. spriteBatch->draw(&sdi);
  428. // volume button and exit button
  429. sdi.setScale(0.2, 0.1f);
  430. sdi.textureHandle = volumeTexture;
  431. #ifndef MY_OS_MEEGO
  432. // volume button specifics
  433. sdi.setTargetPos( 0.7, getTop() - 0.05f );
  434. sdi.setSourceRect( (float)volumeIndicator/6.0f, 0.0f, 1.0f/6.0f, 1.0f );
  435. spriteBatch->draw( &sdi );
  436. #endif
  437. // Exit button
  438. if (currentGame) {
  439. sdi.setTargetPos( 0.9f, getTop() - 0.05f );
  440. sdi.setSourceRect( (float)5.0f/6.0f, 0.0f, 1.0f/6.0f, 1.0f );
  441. spriteBatch->draw( &sdi );
  442. }
  443. #ifdef MY_OS_MEEGO
  444. if (getGameEngine()->isSwipeEnabled()) {
  445. sdi.setScale(0.5f, 0.25f);
  446. sdi.setTargetPos(-0.75f, -0.40f);
  447. sdi.setSourceRect(0,0,1,1);
  448. sdi.textureHandle = meegoSwipeTexture;
  449. spriteBatch->draw(&sdi);
  450. }
  451. #endif
  452. spriteBatch->end();
  453. if (pengine) {
  454. // Render the two types separetally to maximize the average batchsize.
  455. spriteBatch->begin(SpriteBatch::eADDITIVE, SpriteBatch::eCUSTOMPROJECTION, matrixProjection );
  456. pengine->render( spriteBatch, ballFlyParticleType );
  457. pengine->render( spriteBatch, ballHitParticleType );
  458. spriteBatch->end();
  459. }
  460. #ifdef EPONG_DEBUG
  461. spriteBatch->begin(SpriteBatch::eALPHA, SpriteBatch::eCUSTOMPROJECTION, matrixProjection );
  462. sdi.setScale(0.2, 0.1f);
  463. sdi.textureHandle = volumeTexture;
  464. sdi.setTargetPos( pointerX[0], pointerY[0]);
  465. sdi.setSourceRect( (float)5.0f/6.0f, 0.0f, 1.0f/6.0f, 1.0f );
  466. spriteBatch->draw( &sdi );
  467. spriteBatch->end();
  468. #endif
  469. };
  470. void PongApp::keyEvent( GF::KEY_EVENT_TYPE type, int code ) {
  471. if (highScores && type==GF::KEY_CHARACTER) {
  472. if (highScores->enterCharacter( -code )) return; // will return false when string is completed.
  473. }
  474. if (!currentMenu) return;
  475. if (type!=GF::KEY_DOWN) return;
  476. GF::BUTTONS but = (GF::BUTTONS)code;
  477. switch (but) {
  478. case GF::UP: currentMenu->keyControlUp(); break;
  479. case GF::DOWN: currentMenu->keyControlDown(); break;
  480. case GF::FIRE: currentMenu->keyControlSelect(); break;
  481. }
  482. }
  483. void PongApp::sensorEvent(GF::SENSOR_EVENT_TYPE type, int x, int y, int z) {
  484. if (type == GF::ACCELEROMETER) {
  485. if (x==0 && y==0 && z == 0) return;
  486. #ifndef Q_OS_WIN32
  487. float fx,fy,fz;
  488. fx = (float)y;
  489. fy = (float)-x;
  490. fz = (float)z;
  491. float invlen = 1.0f/sqrtf( fx*fx +fy*fy +fz*fz );
  492. fx *= invlen;
  493. fy *= invlen;
  494. fz *= invlen;
  495. sensorGravity[0] = fx;
  496. sensorGravity[1] = fy;
  497. sensorGravity[2] = fz;
  498. #endif
  499. };
  500. }
  501. void PongApp::mouseEvent( GF::MOUSE_EVENT_TYPE type, int x, int y, int button ) {
  502. if (button>1 || button<0) {
  503. return; // ignore.. cannot fit
  504. }
  505. float worldx = (float)x / (float)currentWidth*2.0f - 1.0f;
  506. float worldy = (float)y / (float)currentHeight*2.0f - 1.0f;
  507. worldy *= -((float)currentHeight/(float)currentWidth);
  508. #ifdef EPONG_DEBUG
  509. if (type==GF::MOUSE_DOWN && y < 24)
  510. {
  511. playSoundEffect( sampleLatencyTest, 1.0f );
  512. }
  513. #endif
  514. if (currentMenu) currentMenu->keyControlEnd();
  515. if (highScores) {
  516. if (type==GF::MOUSE_DOWN) {
  517. highScores->die();
  518. }
  519. return;
  520. };
  521. if (credits) {
  522. if (type==GF::MOUSE_DOWN) {
  523. credits->die();
  524. }
  525. return;
  526. };
  527. if (currentMenu) {
  528. if (currentMenu->alreadyClicked() == false && type==GF::MOUSE_DOWN) {
  529. int itemCount = currentMenu->getItemCount();
  530. // similar as in menuItemRender
  531. float scale = MENU_ITEM_HEIGHT/2.0f;
  532. float ystart = scale*0.65f*itemCount + scale;
  533. float ystep = MENU_ITEM_HEIGHT;
  534. if (worldy<ystart) {
  535. int clickIndex = -(worldy-ystart) / ystep;
  536. if (currentMenu->click( clickIndex ))
  537. playSoundEffect( sampleMenuTick, 1.0f );
  538. }
  539. };
  540. return;
  541. }
  542. switch (type) {
  543. case GF::MOUSE_DOWN:
  544. if (worldy>getTop()-0.1f) {
  545. if (worldx > 0.7f) {
  546. if (worldx > 0.8f) {
  547. if (currentGame && currentGame->getGameState()==PGS_RUNNING && !currentMenu) {
  548. // create pause menu
  549. currentMenu = createPauseMenu();
  550. }
  551. } else {
  552. };
  553. };
  554. return;
  555. };
  556. buttonDown[button] = true;
  557. break;
  558. case GF::MOUSE_UP:
  559. buttonDown[button] = false;
  560. };
  561. pointerX[button] = worldx;
  562. pointerY[button] = worldy;
  563. }
  564. void PongApp::restartGame(bool singlePlayer ) {
  565. engine->startSensors();
  566. if (currentGame) delete currentGame;
  567. currentGame = new PongGame( this, singlePlayer );
  568. }
  569. #ifdef IAP
  570. void PongApp::purchaseCompleted(const char *productId, const char *status) {
  571. if (strcmp(status, "OK") == 0) {
  572. //qDebug() << "PongApp::purchaseCompleted !!!";
  573. m_multiplayerPurchased = 3;
  574. }
  575. else {
  576. m_multiplayerPurchased = 4;
  577. // Nothing
  578. }
  579. //qDebug() << "PongApp::purchaseCompleted" << productId << status;
  580. }
  581. void PongApp::purchaseFlowFinished(const char *productId) {
  582. engine->setUpdateAndPauseState(false, false);
  583. currentMenu->click(0);
  584. playSoundEffect( sampleMenuTick, 1.0f );
  585. (void*)productId;
  586. //qDebug() << "purchaseFlowFinished" << productId;
  587. }
  588. GameMenu * PongApp::createWaitingIAPMenu()
  589. {
  590. static int my_counter = 0;
  591. // create menu
  592. GameMenu *m = new GameMenu( menuItemRender, this );
  593. if (m_multiplayerPurchased == 2) {
  594. my_counter ++;
  595. m->addMenuItem( "waiting iap", "buy_mp_game_waiting" );
  596. if (my_counter > 2) {
  597. //qDebug() << "BYPASS";
  598. m->addMenuItem( "exit iap purchase", "buy_mp_game_bypass" );
  599. my_counter = 0;
  600. }
  601. }
  602. else if (m_multiplayerPurchased == 1){
  603. m->addMenuItem( "start purchase", "buy_mp_game_waiting" );
  604. m->addMenuItem( "cancel", "buy_mp_game_cancel" );
  605. }
  606. else {
  607. m->addMenuItem( "click to finish iap try", "buy_mp_game_bypass" );
  608. }
  609. return m;
  610. }
  611. #endif