Map.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. #include "Teile.h"
  2. #include "Map.h"
  3. #include <InitDatei.h>
  4. #include <Datei.h>
  5. #include <KSGTDatei.h>
  6. #include <Text.h>
  7. #include <TastaturEreignis.h>
  8. #include <Zeit.h>
  9. #include <Rahmen.h>
  10. #include <AsynchronCall.h>
  11. // Inhalt der Map Klasse aus Map.h
  12. // Konstruktor
  13. Map::Map( MinigameKlientV *klient )
  14. {
  15. this->klient = klient;
  16. map = new RCArray< Array< int > >();
  17. feld = new LRahmen();
  18. feld->setFarbe( 0xFFFFFFFF );
  19. t = { 0, 0, 0, 0 };
  20. beendet = 1;
  21. sr = 1;
  22. rend = 0;
  23. gameTime = 0;
  24. rGen = 0;
  25. ref = 1;
  26. }
  27. // Destruktor
  28. Map::~Map()
  29. {
  30. speichern();
  31. map->release();
  32. feld->release();
  33. if( rGen )
  34. rGen->release();
  35. if( klient )
  36. klient->release();
  37. }
  38. // nicht constant
  39. void Map::reset( Text *zOptionen )
  40. {
  41. gameTime = 0;
  42. if( rGen )
  43. rGen = rGen->release();
  44. next = 0;
  45. score = 0;
  46. scoreCheck = score * 11197;
  47. map->leeren();
  48. t = { -1, 0, 0, 0 };
  49. Text *tmp = zOptionen->getTeilText( zOptionen->positionVon( '=' ) + 1, zOptionen->positionVon( ',' ) );
  50. breite = *tmp;
  51. tmp->release();
  52. tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 1 ) + 1, zOptionen->positionVon( ',', 1 ) );
  53. höhe = *tmp;
  54. tmp->release();
  55. tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 2 ) + 1, zOptionen->positionVon( ',', 2 ) );
  56. neuTempo = *tmp;
  57. tmp->release();
  58. tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 3 ) + 1, zOptionen->positionVon( ',', 3 ) );
  59. geschwindigkeit = *tmp;
  60. tmp->release();
  61. tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 4 ) + 1, zOptionen->positionVon( ',', 4 ) );
  62. bool fortsetzen = (int)*tmp != 0;
  63. tmp->release();
  64. if( fortsetzen && DateiExistiert( "data/Minigames/Tetris/data/game.save" ) && klient )
  65. {
  66. if( capture.istOffen() )
  67. capture.close();
  68. capture.setDatei( "data/Minigames/Tetris/data/game.mgc" );
  69. capture.open( Datei::Style::schreiben | Datei::Style::ende | Datei::Style::lesen );
  70. Datei *save = new Datei();
  71. save->setDatei( "data/Minigames/Tetris/data/game.save" );
  72. save->open( Datei::Style::lesen );
  73. int br = 0;
  74. int hö = 0;
  75. __int64 seed;
  76. save->lese( (char*)&seed, 8 );
  77. rGen = new RandomGenerator();
  78. rGen->setSeed( seed );
  79. save->lese( (char*)&gameTime, 8 );
  80. save->lese( (char*)&br, 4 );
  81. save->lese( (char*)&hö, 4 );
  82. if( br == breite && hö == höhe )
  83. {
  84. save->lese( (char*)&score, 4 );
  85. scoreCheck = score * 11197;
  86. save->lese( (char*)&t, sizeof( Tile ) );
  87. for( int y = 0; y < höhe; y++ )
  88. {
  89. map->set( new Array< int >(), y );
  90. for( int x = 0; x < breite; x++ )
  91. {
  92. int f = 0;
  93. save->lese( (char*)&f, 4 );
  94. map->z( y )->set( f, x );
  95. }
  96. }
  97. geschwindigkeit -= score * neuTempo;
  98. if( geschwindigkeit < 100 )
  99. geschwindigkeit = 100;
  100. next = geschwindigkeit / 1000.0;
  101. }
  102. save->close();
  103. save->release();
  104. }
  105. else
  106. {
  107. rGen = new RandomGenerator();
  108. if( klient )
  109. {
  110. if( capture.istOffen() )
  111. capture.close();
  112. DateiRemove( "data/Minigames/Tetris/data/game.mgc" );
  113. capture.setDatei( "data/Minigames/Tetris/data/game.mgc" );
  114. capture.erstellen();
  115. capture.open( Datei::Style::schreiben );
  116. __int64 seed = rGen->getSeed();
  117. capture.schreibe( (char*)&seed, 8 );
  118. }
  119. else
  120. {
  121. tmp = zOptionen->getTeilText( zOptionen->positionVon( '=', 5 ) + 1 );
  122. rGen->setSeed( (__int64)*tmp );
  123. tmp->release();
  124. }
  125. }
  126. if( t.id < 0 )
  127. {
  128. t.id = (int)( rGen->rand() * 7 );
  129. t.grad = (int)( rGen->rand() * 4 );
  130. t.xPos = breite / 2 - 2;
  131. t.yPos = 0;
  132. }
  133. if( !map->getEintragAnzahl() )
  134. {
  135. for( int i = 0; i < höhe; i++ )
  136. {
  137. Array< int > *line = new Array< int >();
  138. for( int j = 0; j < breite; j++ )
  139. line->add( 0 );
  140. map->add( line );
  141. }
  142. }
  143. if( breite < 40 || höhe < 25 )
  144. {
  145. int br = breite * 20;
  146. if( br > 800 )
  147. br = 800;
  148. int hö = höhe * 20;
  149. if( hö > 500 )
  150. hö = 500;
  151. feld->setPosition( 400 - br / 2, 250 - hö / 2 );
  152. feld->setSize( br, hö );
  153. }
  154. beendet = 0;
  155. }
  156. void Map::doMausEreignis( MausEreignis &me )
  157. {
  158. }
  159. void Map::doTastaturEreignis( TastaturEreignis &te )
  160. {
  161. if( beendet )
  162. return;
  163. cs.lock();
  164. bool ok = 1;
  165. if( !beendet && te.id == TE_Press )
  166. {
  167. int g = t.grad;
  168. int xPos = t.xPos;
  169. int yPos = t.yPos;
  170. bool save = 0;
  171. if( te.taste == 'w' || te.taste == 'W' || te.taste == T_Oben )
  172. {
  173. g++;
  174. if( g >= 4 )
  175. g = 0;
  176. save = 1;
  177. }
  178. if( te.taste == 'd' || te.taste == 'D' || te.taste == T_Rechts )
  179. {
  180. xPos++;
  181. save = 1;
  182. }
  183. if( te.taste == 'a' || te.taste == 'A' || te.taste == T_Links )
  184. {
  185. xPos--;
  186. save = 1;
  187. }
  188. if( te.taste == 's' || te.taste == 'S' || te.taste == T_Unten )
  189. {
  190. yPos++;
  191. save = 1;
  192. }
  193. if( save && klient )
  194. {
  195. capture.schreibe( (char*)&gameTime, 8 );
  196. capture.schreibe( (char*)&te.taste, 1 );
  197. }
  198. bool ok = 1;
  199. for( int x = xPos; x < xPos + 4; x++ )
  200. {
  201. for( int y = yPos; y < yPos + 4; y++ )
  202. {
  203. if( tiles[ t.id ][ g ][ y - yPos ][ x - xPos ] )
  204. {
  205. ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
  206. ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
  207. }
  208. }
  209. }
  210. if( ok )
  211. {
  212. t.grad = g;
  213. t.xPos = xPos;
  214. t.yPos = yPos;
  215. rend = 1;
  216. }
  217. }
  218. cs.unlock();
  219. }
  220. bool Map::tick( double tickVal )
  221. {
  222. bool ret = rend;
  223. rend = 0;
  224. if( beendet )
  225. return ret;
  226. cs.lock();
  227. gameTime += tickVal;
  228. next -= tickVal;
  229. if( next < 0 )
  230. {
  231. next = geschwindigkeit / 1000.0;
  232. bool ok = 1;
  233. for( int x = t.xPos; x < t.xPos + 4; x++ )
  234. {
  235. for( int y = t.yPos + 1; y < t.yPos + 5; y++ )
  236. {
  237. if( tiles[ t.id ][ t.grad ][ y - t.yPos - 1 ][ x - t.xPos ] )
  238. {
  239. ok &= x >= 0 && x < breite && y >= 0 && y < höhe;
  240. ok &= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) == 0;
  241. }
  242. }
  243. }
  244. if( ok )
  245. t.yPos++;
  246. else
  247. {
  248. for( int x = t.xPos; x < t.xPos + 4; x++ )
  249. {
  250. for( int y = t.yPos; y < t.yPos + 4; y++ )
  251. {
  252. if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
  253. map->z( y )->set( tileFarbe[ t.id ], x );
  254. }
  255. }
  256. for( int y = 0; y < höhe; y++ )
  257. {
  258. bool rm = 1;
  259. for( int x = 0; x < breite; x++ )
  260. rm &= map->z( y )->get( x ) != 0;
  261. if( rm )
  262. {
  263. Array< int > *line = new Array< int >();
  264. for( int i = 0; i < breite; i++ )
  265. line->add( 0 );
  266. map->remove( y );
  267. map->add( line, 0 );
  268. score++;
  269. scoreCheck = score * 11197;
  270. geschwindigkeit -= neuTempo;
  271. }
  272. }
  273. t.id = (int)( rGen->rand() * 7 );
  274. t.grad = (int)( rGen->rand() * 4 );
  275. t.xPos = breite / 2 - 2;
  276. t.yPos = 0;
  277. for( int x = t.xPos; x < t.xPos + 4; x++ )
  278. {
  279. for( int y = t.yPos; y < t.yPos + 4; y++ )
  280. {
  281. if( tiles[ t.id ][ t.grad ][ y - t.yPos ][ x - t.xPos ] )
  282. beendet |= ( ( x >= 0 && x < breite && y >= 0 && y < höhe ) ? map->z( y )->get( x ) : -1 ) != 0;
  283. }
  284. }
  285. if( score * 11197 != scoreCheck )
  286. {
  287. score = 0;
  288. scoreCheck = 0;
  289. beendet = 1;
  290. }
  291. if( beendet && klient )
  292. {
  293. capture.close();
  294. DateiRemove( "data/Minigames/Tetris/data/upload.mgc" );
  295. DateiUmbenennen( "data/Minigames/Tetris/data/game.mgc", "data/Minigames/Tetris/data/upload.mgc" );
  296. int tmpScore = score;
  297. MinigameKlientV *tmpKlient = klient->getThis();
  298. new AsynchronCall( [ tmpScore, tmpKlient ]()
  299. {
  300. InitDatei *opd = new InitDatei( "data/Minigames/Tetris/data/optionen.ini" );
  301. opd->laden();
  302. Text optionen = "Width=";
  303. optionen += opd->zWert( "Breite" )->getText();
  304. optionen += ",Height=";
  305. optionen += opd->zWert( "Höhe" )->getText();
  306. optionen += ",NSpeed=";
  307. optionen += opd->zWert( "+Geschwindigkeit" )->getText();
  308. optionen += ",Speed=";
  309. optionen += opd->zWert( "Geschwindigkeit" )->getText();
  310. opd->release();
  311. int status = tmpKlient->reportEndOfGame( "Tetris", optionen, tmpScore );
  312. if( status == 2 )
  313. {
  314. Datei d;
  315. d.setDatei( "data/Minigames/Tetris/data/upload.mgc" );
  316. tmpKlient->uploadGameCapture( &d );
  317. }
  318. DateiRemove( "data/Minigames/Tetris/data/upload.mgc" );
  319. tmpKlient->release();
  320. } );
  321. DateiRemove( "data/Minigames/Tetris/data/game.save" );
  322. KSGTDatei *stb = new KSGTDatei( "data/Minigames/Tetris/data/score.ksgt" );
  323. if( !stb->laden() )
  324. DateiPfadErstellen( "data/Minigames/Tetris/data/score.ksgt" );
  325. RCArray< Text > *zeile = new RCArray< Text >();
  326. Zeit *zeit = getZeit();
  327. zeile->add( zeit->getZeit( "y-m-d h:i:s" ) );
  328. zeit->release();
  329. Text *scoreT = new Text();
  330. scoreT->append( score );
  331. zeile->add( scoreT );
  332. Text *breiteT = new Text();
  333. breiteT->append( breite );
  334. zeile->add( breiteT );
  335. Text *höheT = new Text();
  336. höheT->append( höhe );
  337. zeile->add( höheT );
  338. Text *geschwindigkeitT = new Text();
  339. geschwindigkeitT->append( geschwindigkeit );
  340. zeile->add( geschwindigkeitT );
  341. Text *neuTempoT = new Text();
  342. neuTempoT->append( neuTempo );
  343. zeile->add( neuTempoT );
  344. stb->addZeile( 6, zeile );
  345. zeile->release();
  346. stb->speichern();
  347. stb->release();
  348. }
  349. }
  350. ret = 1;
  351. }
  352. cs.unlock();
  353. return ret;
  354. }
  355. void Map::render( Bild &zRObj )
  356. {
  357. int xS = feld->getX();
  358. int yS = feld->getY();
  359. int blockBr = 800 / breite;
  360. if( blockBr > 20 )
  361. blockBr = 20;
  362. int blockHö = 500 / höhe;
  363. if( blockHö > 20 )
  364. blockHö = 20;
  365. for( int x = 0; x < breite; x++ )
  366. {
  367. for( int y = 0; y < höhe; y++ )
  368. zRObj.fillRegion( xS + x * blockBr, yS + y * blockHö, blockBr - 1, blockHö - 1, map->z( y )->get( x ) );
  369. }
  370. for( int x = 0; x < 4; x++ )
  371. {
  372. for( int y = 0; y < 4; y++ )
  373. {
  374. if( tiles[ t.id ][ t.grad ][ y ][ x ] )
  375. zRObj.fillRegion( xS + ( x + t.xPos ) * blockBr, yS + ( y + t.yPos ) * blockHö, blockBr - 1, blockHö - 1, tileFarbe[ t.id ] );
  376. }
  377. }
  378. feld->render( zRObj );
  379. }
  380. void Map::speichern()
  381. {
  382. if( !beendet )
  383. {
  384. if( capture.istOffen() )
  385. capture.close();
  386. Datei *d = new Datei();
  387. d->setDatei( "data/Minigames/Tetris/data/game.save" );
  388. d->erstellen();
  389. d->open( Datei::Style::schreiben );
  390. __int64 seed = rGen->getSeed();
  391. d->schreibe( (char*)&seed, 8 );
  392. d->schreibe( (char*)&gameTime, 8 );
  393. d->schreibe( (char*)&breite, 4 );
  394. d->schreibe( (char*)&höhe, 4 );
  395. d->schreibe( (char*)&score, 4 );
  396. d->schreibe( (char*)&t, sizeof( Tile ) );
  397. for( int y = 0; y < höhe; y++ )
  398. {
  399. for( int x = 0; x < breite; x++ )
  400. {
  401. int f = map->z( y )->get( x );
  402. d->schreibe( (char*)&f, 4 );
  403. }
  404. }
  405. d->close();
  406. d->release();
  407. }
  408. else if( klient )
  409. DateiRemove( "data/Minigames/Tetris/data/game.save" );
  410. }
  411. // constant
  412. int Map::getScore() const
  413. {
  414. return score;
  415. }
  416. bool Map::istBeendet() const
  417. {
  418. return beendet;
  419. }
  420. // Reference Counting
  421. Map *Map::getThis()
  422. {
  423. ref++;
  424. return this;
  425. }
  426. Map *Map::release()
  427. {
  428. ref--;
  429. if( !ref )
  430. delete this;
  431. return 0;
  432. }