C:/DevKitPro/!MDuel/source/gameManager.cpp

Go to the documentation of this file.
00001 /*
00002  * Marshmallow Duel DS v2
00003  * Copyright © 2007 Sam Pospischil http://pospi.spadgos.com
00004  * 
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  */
00019 
00020 #include "gameManager.h"
00021 #include "player.h"
00022 #include "pickup.h"
00023 #include "menuGBottom.h"
00024 #include "menuBottom.h"
00025 
00026 gameManager::~gameManager()
00027 {
00028         
00029 }
00030 
00038 void gameManager::resetGame(bool ending)
00039 {
00040         for (u8 i=0; i<3; ++i)
00041                 pickupSpawners[i] = NULL;
00042                                 
00043         //clear the bottom screen first.
00044         //resetting its spawner counters should stop it NULLing while we're resetting.
00045         menuGBottom * bottomScreen = dynamic_cast<menuGBottom*>(gameBottom);
00046         //bottomScreen->deletePickups(); //makes it crash some
00047         for (u8 i=0; i<3; ++i)
00048                 bottomScreen->resetIdleTime(i);
00049         
00050         //clear out old stuff
00051         clearOutSprites();      
00052                 
00053         //handle scores and round counter
00054         if (!(p1RoundScore && p2RoundScore) && !(!p1RoundScore && !p2RoundScore))
00055         {
00056                 p1score += p1RoundScore;
00057                 p2score += p2RoundScore;
00058         }
00059         p1RoundScore = p2RoundScore = 0;
00060         ++roundNumber;
00061         
00062         refreshPalletes();
00063         preloadGFX();
00064         
00065         if (!ending)            //add new stuff for next round
00066         {
00067                 if (player1 == NULL)
00068                 {
00069                         player1 = new Player(this);
00070                         player1->setPallete(player1Sprite.palleteID);
00071                         u16 gfxId = loadGFX(player1Sprite.spriteData, OBJ_SIZE_32X32, 1);
00072                         player1->giveGFX(gfxId, OBJ_SIZE_32X32, 16, 16, 0, 32, 192-32);
00073                         player1->setStartPos(32, 192-32);
00074                         player1->setStartFlipped(false);
00075                         player1->setControls(1);
00076                         player1->setRotSet(0);
00077                         
00078                         #ifdef __WITHSOUND
00079                         player1->playSound(&spawnPuff);
00080                         #endif
00081                 }
00082                 if (player2 == NULL)
00083                 {
00084                         player2 = new Player(this);
00085                         player2->setPallete(player2Sprite.palleteID);
00086                         u16 gfxId = loadGFX(player2Sprite.spriteData, OBJ_SIZE_32X32, 1);
00087                         player2->giveGFX(gfxId, OBJ_SIZE_32X32, 16, 16, 0, 256-32, 192-32);
00088                         player2->setStartPos(256-32, 192-32);
00089                         player2->setStartFlipped(true);
00090                         player2->setControls(2);
00091                         player2->setRotSet(1);
00092                         
00093                         #ifdef __WITHSOUND
00094                         player2->playSound(&spawnPuff);
00095                         #endif
00096                 }
00097                 
00098                 generateRopes();
00099                 generateBricks();
00100                 generateSpawners();
00101                 drawMallow();
00102                 
00103                 u8 f[3] = {21, 22, 23};
00104                 vector<u8> temp(f, f+3);
00105                 createSingleFireSprite(FXSprite.palleteID, spawnGFX[0], temp, spriteObject::TICKSPERFRAME*2, player1->getx(), player1->gety(), OBJ_SIZE_32X32, 16, 16);
00106                 createSingleFireSprite(FXSprite.palleteID, spawnGFX[1], temp, spriteObject::TICKSPERFRAME*2, player2->getx(), player2->gety(), OBJ_SIZE_32X32, 16, 16);
00107         } else {
00108                 //victory dancing guy!!
00109                 spriteObject *dancy = new spriteObject(this);
00110                 dancy->setPallete((p1score > p2score ? player1Sprite.palleteID : player2Sprite.palleteID));
00111                 dancy->giveSprite((p1score > p2score ? player1Sprite.spriteData : player2Sprite.spriteData), OBJ_SIZE_32X32, 16, 16, 0, 127, 95);
00112                 dancy->setLayer(1);
00113                 u8 f[10] = {58, 59, 60, 61, 62, 63, 63, 63, 63, 63};
00114                 vector<u8> temp(f, f+10);
00115                 dancy->setArbitraryAnim(temp, true, spriteObject::TICKSPERFRAME);
00116                 //dancy->makeStatic();
00117                 
00118                 bottomScreen->gameOver = true;
00119         }
00120 }
00121 
00128 bool gameManager::isGamePaused()
00129 { 
00130         return dynamic_cast<menuGBottom*>(gameBottom)->gamePaused;
00131 }
00132 
00137 void gameManager::preloadGFX()
00138 {
00139         //pickup graphics
00140         for (u8 i=0; i < menuBase->numPickups+2; ++i)           //load 2 extra lots of GFX for potential magneted Pickups
00141         {
00142                 pickupGraphics p;
00143                 p.spawnGFX = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32);
00144                 p.dieGFX = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32);
00145                 p.blobGFX = loadGFX(pickupSprite.spriteData, OBJ_SIZE_16X16);
00146                 p.iconGFX = loadGFX(pickupSprite.spriteData, OBJ_SIZE_16X16);
00147                 p.bInUse = false;
00148                 pickupGFX.push_back(p);
00149         }
00150         //player spawn & splash effects
00151         spawnGFX[0] = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32, 1);
00152         spawnGFX[1] = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32, 1);
00153         //player persistent effects (lightning aura, etc)
00154         spawnGFX[2] = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32, 1);
00155         spawnGFX[3] = loadGFX(FXSprite.spriteData, OBJ_SIZE_32X32, 1);
00156         //dunce hats!
00157         dunceGFX[0] = loadGFX(dunceHatSprite.spriteData, OBJ_SIZE_32X32, 1);
00158         dunceGFX[1] = loadGFX(dunceHatSprite.spriteData, OBJ_SIZE_32X32, 1);
00159         //totally awesome boots!
00160         bootsGFX[0] = loadGFX(bootsSprite.spriteData, OBJ_SIZE_32X32, 1);
00161         bootsGFX[1] = loadGFX(bootsSprite.spriteData, OBJ_SIZE_32X32, 1);
00162 }
00163 
00168 void gameManager::unloadGFX()
00169 {
00170         pickupGFX.clear();
00171         //TODO: the above wont actually clear those GFX from memory
00172         PA_DeleteGfx(screen, spawnGFX[0]);
00173         PA_DeleteGfx(screen, spawnGFX[1]);
00174         PA_DeleteGfx(screen, spawnGFX[2]);
00175         PA_DeleteGfx(screen, spawnGFX[3]);
00176         PA_DeleteGfx(screen, dunceGFX[0]);
00177         PA_DeleteGfx(screen, dunceGFX[1]);
00178         PA_DeleteGfx(screen, bootsGFX[0]);
00179         PA_DeleteGfx(screen, bootsGFX[1]);
00180 }
00181 
00186 gameManager::pickupGraphics* gameManager::getNextAvailablePickupGFXSet()
00187 {
00188         vector<pickupGraphics>::iterator it = pickupGFX.begin();
00189         while (it != pickupGFX.end())
00190         {
00191                 if (!(*it).bInUse)
00192                         return &(*it);
00193                 ++it;
00194         }
00195         return NULL;
00196 }
00197 
00198 //==============================================================================
00199 
00206 void gameManager::generateBricks()
00207 {
00208         u16 tileGFX = loadGFX(tileSprite.spriteData, OBJ_SIZE_16X16, 1);
00209         for (int i=0; i < 51; ++i)
00210         {
00211                 floorTile *temp = new floorTile(this);
00212                 temp->setPallete(tileSprite.palleteID);
00213                 temp->giveGFX(tileGFX, OBJ_SIZE_16X16, 8, 8, 0, OFFX, OFFY);
00214                 
00215                 if (i<3)
00216                         temp->setPos(i*16+24, 192-32+8);
00217                 else if (i<6)
00218                         temp->setPos(256-24-((i-3)*16), 192-32+8);
00219                 else if (i>47)
00220                         temp->setPos(256-16-8-((i-47)*16), 192-32+8+4*-32);
00221                 else if (i>44)
00222                         temp->setPos((i-45)*16+16+16+8, 192-32+8+4*-32);
00223                 else {
00224                         u8 j = i-6;
00225                         u8 col = j%13;
00226                         u8 row = j/13;
00227                         if (PA_RandMax(10) < 7 || (
00228                                 (gameSprites.size()-2 > 0 && gameSprites[gameSprites.size()-2]->getx() > 0) && 
00229                                 (gameSprites.size()-3 > 0 && gameSprites[gameSprites.size()-3]->getx() < 0) ))
00230                                 temp->setPos((col+1)*16+16, 192-32+8+((row+1)*-32));
00231                 }
00232                 temp->makeStatic();
00233         }
00234 }
00235 
00239 void gameManager::generateRopes()
00240 {
00241         u16 ropeHeadGFX = loadGFX(tileSprite.spriteData, OBJ_SIZE_16X16, 1);
00242         u16 ropeGFX = loadGFX(tileSprite.spriteData, OBJ_SIZE_16X16, 1);
00243         
00244         Rope *r1 = new Rope(this);
00245         r1->setPallete(tileSprite.palleteID);
00246         r1->giveGFX(ropeHeadGFX, OBJ_SIZE_16X16, 8, 8);
00247         r1->childGFX = ropeGFX;
00248         r1->setPos(56, 3);
00249         r1->setLength(9);
00250         r1->makeStatic();
00251         
00252         Rope *r2 = new Rope(this);
00253         r2->setPallete(tileSprite.palleteID);
00254         r2->giveGFX(ropeHeadGFX, OBJ_SIZE_16X16, 8, 8);
00255         r2->childGFX = ropeGFX;
00256         r2->setPos(256-56, 3);
00257         r2->setLength(9);
00258         r2->makeStatic();
00259 }
00260 
00264 void gameManager::generateSpawners()
00265 {
00266         pickupSpawners[0] = new pickupSpawner(this);
00267         pickupSpawners[0]->setPallete(tileSprite.palleteID);
00268         pickupSpawners[0]->giveSprite(tileSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00269         pickupSpawners[0]->setFrame(1);
00270         pickupSpawners[0]->setPos(8, 96);
00271         pickupSpawners[0]->setDirection(pickupSpawner::SDIR_RIGHT);
00272         //p1->makeStatic();
00273         
00274         pickupSpawners[1] = new pickupSpawner(this);
00275         pickupSpawners[1]->setPallete(tileSprite.palleteID);
00276         pickupSpawners[1]->giveSprite(tileSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00277         pickupSpawners[1]->setFrame(3);
00278         pickupSpawners[1]->setPos(256-8, 96);
00279         pickupSpawners[1]->setDirection(pickupSpawner::SDIR_LEFT);
00280         //p2->makeStatic();
00281         
00282         pickupSpawners[2] = new pickupSpawner(this);
00283         pickupSpawners[2]->setPallete(tileSprite.palleteID);
00284         pickupSpawners[2]->giveSprite(tileSprite.spriteData, OBJ_SIZE_16X16, 8, 8);
00285         pickupSpawners[2]->setFrame(2);
00286         pickupSpawners[2]->setPos(128, 8);
00287         pickupSpawners[2]->setDirection(pickupSpawner::SDIR_DOWN);
00288         //p3->makeStatic();
00289 }
00290 
00294 void gameManager::drawMallow()
00295 {
00296         for (int i=0; i<16; ++i)
00297         {
00298                 spriteObject *goo = new spriteObject(this);
00299                 goo->setPallete(tileSprite.palleteID);
00300                 goo->giveSprite(tileSprite.spriteData, OBJ_SIZE_16X16, 8, 8, 0, i*16+8, 192-8);
00301                 goo->setLayer(1);
00302                 goo->setFrame(6);
00303                 goo->updateSprite();
00304                 goo->setAnim(6,9,PA_RandMax(3)+1);
00305                 goo->makeStatic();
00306         }
00307 }
00308 
00309 //==============================================================================
00310 
00324 void gameManager::gameTick()
00325 {
00326         #ifdef __MDDEBUG
00327         char buffer[40];
00328         sprintf ( buffer, "%d %d %d %d %d ", p1score, p1RoundScore, p2score, p2RoundScore, pointsToWin );
00329         macros::debugMessage("Scores", buffer, 2);
00330                 
00331         sprintf ( buffer, "%d \nTaken  : %d \nNext ID: %d ", gameSprites.size(), getNumSpritesTaken(), getNextSpriteID() );
00332         macros::debugMessage("Sprites", buffer, 6);
00333         #endif
00334         
00335         if (!dynamic_cast<menuGBottom*>(gameBottom)->gamePaused)
00336         {
00337                 //round end timer (set when a player dies)
00338                 if (gameEndTimer == 0)
00339                 {
00340                         if (player1 != NULL)
00341                                 player1->clearWeapon();
00342                         if (player2 != NULL)
00343                                 player2->clearWeapon();
00344                         
00345                         //add this round to stats
00346                         if (p1RoundScore > 0 || p2RoundScore > 0)       //dont want rounds where nobody has died!
00347                         {
00348                                 u8 winner = (p1RoundScore > p2RoundScore ? menuBase->player1id : menuBase->player2id);
00349                                 u8 loser = (p1RoundScore > p2RoundScore ? menuBase->player2id : menuBase->player1id);
00350                                 menuBase->scoreRound(winner, loser, (p1RoundScore == p2RoundScore));
00351                         }
00352                         
00353                         resetGame(((p1score + p1RoundScore >= pointsToWin) || (p2score + p2RoundScore >= pointsToWin)) && ((p1score + p1RoundScore) != (p2score + p2RoundScore)));
00354                         gameEndTimer = -1;
00355                         pauseSpawning = false;
00356                 } else if (gameEndTimer > 0)
00357                 {
00358                         pauseSpawning = true;
00359                         if ((player1->isDisabled() && player2->readyForVictory()) || 
00360                                 (player1->readyForVictory() && player2->isDisabled()) ||
00361                                 (player1->isDisabled() && player2->isDisabled()))
00362                         {
00363                                 //this ternary is ok since you can't see the players at this point anyway
00364                                 if (gameEndTimer == ROUNDENDTIMEOUT && !(player1->isDisabled() && player2->isDisabled()))
00365                                 {
00366                                         //frozen player will be the loser at this point
00367                                         player1->isFrozen() ? player2->playVictory() : player1->playVictory();
00368                                 }
00369                                 gameEndTimer--;
00370                         }
00371                 }
00372                 
00373                 //read player input before screen updates
00374                 if (player1 != NULL)
00375                         player1->checkPad();
00376                 if (player2 != NULL)
00377                         player2->checkPad();
00378                 
00379                 spriteManager::gameTick();
00380                 
00381                 //all are updated to new positions, so run collision detection
00382                 for (vector<spriteObject*>::iterator it = gameSprites.begin(); it != gameSprites.end(); ++it)
00383                         (*it)->checkCollisions();
00384         }
00385         
00386         if (Pad.Newpress.Start)         //escape key!
00387         {
00388                 dynamic_cast<menuGBottom*>(gameBottom)->gamePaused = true;
00389                 
00390                 //stop primary timer
00391                 PauseTimer(statTimerID);
00392                 
00393                 //this stops any animations from sticking (example: player 2 walking right without animating)
00394                 player1->updateAnimation();
00395                 player2->updateAnimation();
00396         }
00397 }
00398 
00399 //==============================================================================
00400 
00410 void gameManager::playerDied(Player *p, u8 weaponID, bool skipKill)
00411 {
00412         if (player1 == p)
00413         {
00414                 player1->freezePlayer();        //stop moving and colliding
00415                 player2->disableControls();     //let gravity take over
00416                 p2RoundScore = 1;
00417                 
00418                 //add this death to stats
00419                 if (!skipKill)
00420                         menuBase->scoreKill(menuBase->player2id, weaponID);
00421                 menuBase->scoreDeath(menuBase->player1id, weaponID);
00422         } else {
00423                 player2->freezePlayer();
00424                 player1->disableControls();
00425                 p1RoundScore = 1;
00426                 
00427                 //add this death to stats
00428                 if (!skipKill)
00429                         menuBase->scoreKill(menuBase->player1id, weaponID);
00430                 menuBase->scoreDeath(menuBase->player2id, weaponID);
00431         }
00432         player1->stopNetted();
00433         player2->stopNetted();
00434         gameEndTimer = ROUNDENDTIMEOUT;
00435 }
00436 
00443 void gameManager::playerDiedSilently(Player *p)
00444 {
00445         player1 == p ? player1->playInvis() : player2->playInvis();
00446         playerDied(p);
00447 }
00448 
00455 void gameManager::playerSkulled(Player *p)
00456 {
00457         player1 == p ? player1->playSkulled() : player2->playSkulled();
00458         
00459         //if other player is using the magnet, attribute this to a magnet kill
00460         //otherwise if you werent hit at all, its your own dumb fault
00461         bool isMagnet = (player1 == p ? player2->usingMagnet() : player1->usingMagnet());
00462         playerDied(p, (isMagnet ? Pickup::PT_MAGNET : Pickup::PT_SKULL), !(p->lastCollision > Player::CS_NONE));
00463 }
00464 
00471 void gameManager::playerSank(Player *p)
00472 {
00473         player1 == p ? player1->playSplashEffect() : player2->playSplashEffect();
00474         
00475         //check last collision state to determine cause of death
00476         if (p->isNetted())
00477                 playerDied(p, Pickup::PT_NET);
00478         else if (p->lastCollision == Player::CS_INVISPLAYER)
00479                 playerDied(p, Pickup::PT_INVIS);
00480         else if (p->lastCollision == Player::CS_TNTFALL)
00481                 playerDied(p, Pickup::PT_TNT);
00482         else if (p->lastCollision == Player::CS_GRENFALL)
00483                 playerDied(p, Pickup::PT_GRENADE);
00484         else if (p->lastCollision == Player::CS_WARPEDPLAYER)
00485                 playerDied(p, Pickup::PT_WARP);
00486         else if (p->lastCollision == Player::CS_SHIELDPLAYER)
00487                 playerDied(p, Pickup::PT_SHIELD);
00488         else if (p->lastCollision == Player::CS_BOOMERANG)
00489                 playerDied(p, Pickup::PT_BOOMERANG);
00490         else if (p->lastCollision == Player::CS_BASICHIT)
00491                 playerDied(p, 18);
00492         else
00493                 playerDied(p, 18, true);
00494 }
00495 
00501 void gameManager::playerLightningd(Player *p)
00502 {
00503         playerDied(p, Pickup::PT_1000V);
00504         player1 == p ? player1->play1000VHitEffect() : player2->play1000VHitEffect();
00505 }
00506 
00512 void gameManager::playerMined(Player *p)
00513 {
00514         playerDied(p, Pickup::PT_MINE);
00515         player1 == p ? player1->playMineHitEffect() : player2->playMineHitEffect();
00516 }
00517 
00523 void gameManager::playerDisintegrated(Player *p)
00524 {
00525         player1 == p ? player1->playDisintegrated() : player2->playDisintegrated();
00526         playerDied(p, Pickup::PT_GUN);
00527 }
00528 
00534 void gameManager::playerWeaseled(Player *p)
00535 {
00536         player1 == p ? player1->playDisintegrated() : player2->playDisintegrated();
00537         playerDied(p, Pickup::PT_WEASEL);
00538 }
00539 
00545 void gameManager::playerPucked(Player *p)
00546 {
00547         playerDied(p, Pickup::PT_PUCK);
00548         player1 == p ? player1->playMineHitEffect() : player2->playMineHitEffect();
00549 }
00550 
00551 //==============================================================================
00552 
00554 void gameManager::loadPlayer1SpriteSet(const unsigned short *p, const unsigned char *s)
00555 {
00556         loadSpriteSet(&player1Sprite, p, s);
00557 }
00558 
00560 void gameManager::loadPlayer2SpriteSet(const unsigned short *p, const unsigned char *s)
00561 {
00562         loadSpriteSet(&player2Sprite, p, s);
00563 }
00564 
00566 void gameManager::loadEnvSpriteSet(const unsigned short *p, const unsigned char *s)
00567 {
00568         loadSpriteSet(&tileSprite, p, s);
00569 }
00570 
00572 void gameManager::loadPickupSpriteSet(const unsigned short *p, const unsigned char *s)
00573 {
00574         loadSpriteSet(&pickupSprite, p, s);
00575 }
00576 
00578 void gameManager::loadFXSpriteSet(const unsigned short *p, const unsigned char *s)
00579 {
00580         loadSpriteSet(&FXSprite, p, s);
00581 }
00582 
00584 void gameManager::loadDunceSpriteSet(const unsigned short *p, const unsigned char *s)
00585 {
00586         loadSpriteSet(&dunceHatSprite, p, s);
00587 }
00588 
00590 void gameManager::loadBootsSpriteSet(const unsigned short *p, const unsigned char *s)
00591 {
00592         loadSpriteSet(&bootsSprite, p, s);
00593 }
00594 
00600 void gameManager::refreshPalletes()
00601 {
00602         loadPlayer1SpriteSet(player1Sprite.palleteData, player1Sprite.spriteData);
00603         loadPlayer2SpriteSet(player2Sprite.palleteData, player2Sprite.spriteData);
00604         loadEnvSpriteSet(tileSprite.palleteData, tileSprite.spriteData);
00605         loadPickupSpriteSet(pickupSprite.palleteData, pickupSprite.spriteData);
00606         loadFXSpriteSet(FXSprite.palleteData, FXSprite.spriteData);
00607         loadDunceSpriteSet(dunceHatSprite.palleteData, dunceHatSprite.spriteData);
00608         loadBootsSpriteSet(bootsSprite.palleteData, bootsSprite.spriteData);
00609         
00610         player1000VPallete = loadPallete((void*)player1000VPalleteData);
00611 }
00612 
00619 void gameManager::clearOutSprites(bool keepSound)
00620 {
00621         player1Sprite.palleteID = -1;
00622         player2Sprite.palleteID = -1;
00623         tileSprite.palleteID = -1;
00624         pickupSprite.palleteID = -1;
00625         FXSprite.palleteID = -1;
00626         dunceHatSprite.palleteID = -1;
00627         bootsSprite.palleteID = -1;
00628         
00629         pickups.clear();
00630         dynamic_cast<menuGBottom*>(gameBottom)->pickupsActive = 0;
00631         
00632         player1 = NULL;
00633         player2 = NULL;
00634         
00635         //unloadGFX();  //<- spriteManager resets sprite system to clean out GFX
00636         //however we still need to clear preloaded GFX indices array
00637         pickupGFX.clear();
00638         
00639         spriteManager::clearOutSprites(keepSound);
00640 }
00641 
00642 //==============================================================================
00643 
00649 void gameManager::addPickup(Pickup *p)
00650 {
00651         pickups.push_back(p);
00652 }
00653 
00659 void gameManager::removePickup(Pickup *p)
00660 {
00661         vector<Pickup*>::iterator it = pickups.begin();
00662         
00663         while (it != pickups.end())
00664         {
00665                 if ((*it) == p)
00666                 {
00667                         pickups.erase(it);
00668                         break;
00669                 }
00670                 ++it;
00671         }
00672 }

Generated on Tue Mar 13 23:27:52 2007 for MDuel DS by  doxygen 1.5.1-p1