/* ================================================================================ Game::Draw Gets called once per frame to draw the current snapshot of the game. ================================================================================ */ void Game::Draw() { // clear the screen SDL_SetRenderDrawColor(mRenderer, 0, 0, 0, 255); SDL_RenderClear(mRenderer); if (mBackground) { Render(mBackground->GetRenderable(), &mBackground->GetRect(), SDL_FLIP_NONE); } if (mForeground) { //Render(mForeground->GetRenderable(), &mForeground->GetRect(), SDL_FLIP_NONE); } if (mFlagPole) { Render(mFlagPole->GetRenderable(), &mFlagPole->GetRect(), SDL_FLIP_NONE); } // // draw the grid // if (mGrid) { int tileWidth = mGrid->TileWidth(); int tileHeight = mGrid->TileHeight(); GG::Rect tileRect(0, 0, tileWidth, tileHeight); for (int y = 0; y < mGrid->NumRows(); y++) { for (int x = 0; x < mGrid->NumCols(); x++) { const GG::Renderable* renderable = mGrid->GetTile(y, x)->GetRenderable(); if (renderable) { Render(renderable, &tileRect, SDL_FLIP_NONE); } tileRect.x += tileWidth; } tileRect.y += tileHeight; tileRect.x = 0; } } // Draw the collision rectangles if (rectVisible) { SDL_SetRenderDrawColor(mRenderer, 255, 0, 0, 255); SDL_RenderFillRect(mRenderer, &mRobot->GetBottomTileRect()); SDL_SetRenderDrawColor(mRenderer, 150, 0, 0, 255); SDL_RenderFillRect(mRenderer, &mRobot->GetTopTileRect()); SDL_SetRenderDrawColor(mRenderer, 255, 255, 0, 255); SDL_RenderFillRect(mRenderer, &mRobot->GetCollisonRect()); for (auto coinIt = mCoins.begin(); coinIt != mCoins.end(); ++coinIt) { Coin* coin = *coinIt; SDL_RenderFillRect(mRenderer, &coin->GetRect()); } for (auto crawlerIt = mCrawlers.begin(); crawlerIt != mCrawlers.end(); ++crawlerIt) { Crawler* crawler = *crawlerIt; SDL_RenderFillRect(mRenderer, &crawler->GetCollisionRect()); } for (auto meteorIt = mMeteors.begin(); meteorIt != mMeteors.end(); ++meteorIt) { Meteor* meteor = *meteorIt; SDL_RenderFillRect(mRenderer, &meteor->GetRect()); } SDL_SetRenderDrawColor(mRenderer, 0, 0, 255, 255); for (auto crawlerIt = mCrawlers.begin(); crawlerIt != mCrawlers.end(); ++crawlerIt) { Crawler* crawler = *crawlerIt; SDL_RenderFillRect(mRenderer, &crawler->GetTileRect()); } } // // draw the robot // if (mRobot) { Render(mRobot->GetRenderable(), &mRobot->GetRect(), mRobot->GetDirection()?SDL_FLIP_HORIZONTAL:SDL_FLIP_NONE); } // // draw the coins // std::list<Coin*>::iterator coinIt = mCoins.begin(); for ( ; coinIt != mCoins.end(); ++coinIt) { Coin* coin = *coinIt; Render(coin->GetRenderable(), &coin->GetRect(), SDL_FLIP_NONE); } // // draw the mushrooms // std::list<Layer*>::iterator mushIter = mMushrooms.begin(); for ( ; mushIter != mMushrooms.end(); ++mushIter) { Layer* mushroom = *mushIter; Render(mushroom->GetRenderable(), &mushroom->GetRect(), SDL_FLIP_NONE); } // // draw the crawlers // for (auto crawlerIt = mCrawlers.begin(); crawlerIt != mCrawlers.end(); ++crawlerIt) { Crawler* crawler = *crawlerIt; if (crawler->GetDirection() == 1) { Render(crawler->GetRenderable(), &crawler->GetRect(), SDL_FLIP_HORIZONTAL); } else { Render(crawler->GetRenderable(), &crawler->GetRect(), SDL_FLIP_NONE); } } // // draw the explosions // std::list<Explosion*>::iterator it = mExplosions.begin(); for ( ; it != mExplosions.end(); ++it) { Explosion* boom = *it; Render(boom->GetRenderable(), &boom->GetRect(), SDL_FLIP_NONE); } // // draw the meteors // std::list<Meteor*>::iterator metIt = mMeteors.begin(); for ( ; metIt != mMeteors.end(); ++metIt) { Meteor* meteor = *metIt; Render(meteor->GetRenderable(), &meteor->GetRect(), SDL_FLIP_NONE); } // Draw the points label if (mPointsLabel) { Render(mPointsLabel->GetRenderable(), &mPointsLabel->GetRect(), SDL_FLIP_NONE); } // Draw the lives label if (mLivesLabel) { Render(mLivesLabel->GetRenderable(), &mLivesLabel->GetRect(), SDL_FLIP_NONE); } // display everything we just drew SDL_RenderPresent(mRenderer); }
/* ================================================================================ Game::Update Gets called once per frame to perform game logic. The parameter dt is the time elapsed since last frame (in seconds). ================================================================================ */ void Game::Update(float dt) { // Update the robot if (mRobot) { // If the robot has reached the last scene // disable its controls and play game over animation if (mScene == 6 && !mRobot->GetJumping() && !mRobot->GetFalling()) { mRobot->SetAutoPilot(true); } mRobot->Update(dt); } // Update the coins std::list<Coin*>::iterator coinIt = mCoins.begin(); while (coinIt != mCoins.end()) { Coin *coin = *coinIt; // Check if the robot collides with the coin if (mRobot->GetCollisonRect().y < coin->GetRect().y + coin->GetRect().h) { if ((mRobot->GetCollisonRect().x < coin->GetRect().x + coin->GetRect().w) && (mRobot->GetCollisonRect().x + mRobot->GetCollisonRect().w > coin->GetRect().x)) { if ((mRobot->GetCollisonRect().y < coin->GetRect().y + coin->GetRect().h) && (mRobot->GetCollisonRect().y + mRobot->GetCollisonRect().h > coin->GetRect().y)) { //I have found that the sound is delayed...So I start it a bit earlier than the actualy delete of the Coin if (coin->GetSoundDelay() == 0) { // You get 5 points! mPoints += 5; Mix_PlayChannel(-1, mCoinSound, 0); coin->SetSoundDelay(1); } //Once it has run through 4 times then it Deletes the coin else if (coin->GetSoundDelay() == 5) { coinIt = mCoins.erase(coinIt); // remove the entry from the list and advance iterator delete coin; coin = NULL; } else { coin->SetSoundDelay(1); } } else { coin->Update(dt); ++coinIt; } } else { coin->Update(dt); ++coinIt; } } else { coin->Update(dt); ++coinIt; } } // update all crawlers std::list<Crawler*>::iterator crawlerIt = mCrawlers.begin(); while (crawlerIt != mCrawlers.end()) { Crawler *crawler = *crawlerIt; if (crawler->GetState() == Crawler::CRAWLER_DEAD) { crawlerIt = mCrawlers.erase(crawlerIt); // remove the entry from the list and advance iterator delete crawler; // delete the object } else { // If the robot is falling from a jump or just falling if (mRobot->GetVerticalVelocity() > 0.0 && (mRobot->GetJumping() || mRobot->GetFalling())) { // Check if the robot has started squashing the poor crawler if (mRobot->GetCollisonRect().x + mRobot->GetCollisonRect().w > crawler->GetCollisionRect().x && mRobot->GetCollisonRect().x < crawler->GetCollisionRect().x + crawler->GetCollisionRect().w) { if (mRobot->GetCollisonRect().y + mRobot->GetCollisonRect().h > crawler->GetCollisionRect().y && mRobot->GetCollisonRect().y < crawler->GetCollisionRect().y) { if (crawler->GetState() != CrawlerWeak::CRAWLER_DYING) { // You get 25 points! mPoints += 25; if (crawler->IsJumpedOn()) { Mix_PlayChannel(-1, mStompSound, 0); mRobot->Bounce(-400, false); crawler->SetState(Crawler::CRAWLER_DYING); } else { Mix_PlayChannel(-1, mStompSoundNoKill, 0); mRobot->Bounce(-400, false); crawler->SetState(Crawler::CRAWLER_DYING); } } } } } // If the robot runs into a crawler, the robot must die (but it should not falling onto it from above) else if (mRobot->GetCollisonRect().x + mRobot->GetCollisonRect().w > crawler->GetCollisionRect().x && mRobot->GetCollisonRect().x < crawler->GetCollisionRect().x + crawler->GetCollisionRect().w) { if (mRobot->GetCollisonRect().y + mRobot->GetCollisonRect().h > crawler->GetCollisionRect().y && mRobot->GetCollisonRect().y < crawler->GetCollisionRect().y + crawler->GetCollisionRect().h) { if (!mRobot->IsDead() && mRobot->GetVerticalVelocity() == -850.0f && crawler->GetState() != CrawlerWeak::CRAWLER_DYING) { // You lose a life:( mRobot->SetLives(mRobot->GetLives() - 1); Mix_PlayChannel(-1, mDieSound, 0); // Stop the background music Mix_HaltMusic(); if (mRobot->GetLives() == 0) { printf("\nGame over music is being played!"); Mix_VolumeMusic(32); Mix_PlayMusic(mBadGameOverMusic, 0); SetEntitiesGrayscale(true); } mRobot->Bounce(-400, true); // kill the robot } } } crawler->Update(dt); ++crawlerIt; } } // // update the explosions // std::list<Explosion*>::iterator it = mExplosions.begin(); while (it != mExplosions.end()) { Explosion* entity = *it; // get a pointer to this explosion if (entity->IsFinished()) { it = mExplosions.erase(it); // remove the entry from the list and advance iterator delete entity; // delete the object } else { entity->Update(dt); // update the entity ++it; // advance list iterator } } // // update the meteors // std::list<Meteor*>::iterator metIt = mMeteors.begin(); while (metIt != mMeteors.end()) { Meteor* entity = *metIt; // get a pointer to this meteor // If the meteor has either reached the ground, destroy it with an explosion if (entity->GetRect().y > mScrHeight-32-64) { if (!mRobot->IsDead()) { Mix_PlayChannel(-1, mThudSound, 0); } Explosion* boom = new Explosion(entity->GetRect().x + entity->GetRect().w / 2, entity->GetRect().y + entity->GetRect().h / 2); mExplosions.push_back(boom); metIt = mMeteors.erase(metIt); // remove the entry from the list and advance iterator delete entity; // delete the object } // If the meteor has hit the robot from the top, destroy it with an explosion and also kill the robot else if (entity->GetRect().y + entity->GetRect().h > mRobot->GetCollisonRect().y && entity->GetRect().y < mRobot->GetCollisonRect().y + mRobot->GetCollisonRect().h && entity->GetRect().x + entity->GetRect().w > mRobot->GetCollisonRect().x && entity->GetRect().x < mRobot->GetCollisonRect().x + mRobot->GetCollisonRect().w && !mRobot->IsDead()) { // You lose a life:( mRobot->SetLives(mRobot->GetLives() - 1); Mix_PlayChannel(-1, mThudSound, 0); Mix_PlayChannel(-1, mDieSound, 0); // Stop the background music Mix_HaltMusic(); if (mRobot->GetLives() == 0) { Mix_VolumeMusic(32); Mix_PlayMusic(mBadGameOverMusic, 0); SetEntitiesGrayscale(true); } mRobot->Bounce(-400, true); // kill the robot Explosion* boom = new Explosion(entity->GetRect().x + entity->GetRect().w / 2, entity->GetRect().y + entity->GetRect().h / 2); mExplosions.push_back(boom); metIt = mMeteors.erase(metIt); // remove the entry from the list and advance iterator delete entity; // delete the object } else { entity->Update(dt); // update the entity ++metIt; // advance list iterator } } // // update the mushrooms // std::list<Layer*>::iterator mushIt = mMushrooms.begin(); while (mushIt != mMushrooms.end()) { Layer* entity = *mushIt; // If the robot collects the mushroom, it gets an extra life! if (entity->GetRect().y + entity->GetRect().h > mRobot->GetCollisonRect().y && entity->GetRect().y < mRobot->GetCollisonRect().y + mRobot->GetCollisonRect().h && entity->GetRect().x + entity->GetRect().w > mRobot->GetCollisonRect().x && entity->GetRect().x < mRobot->GetCollisonRect().x + mRobot->GetCollisonRect().w && !mRobot->IsDead()) { mRobot->SetLives(mRobot->GetLives() + 1); SetFlashesNeeded(2); Mix_PlayChannel(-1, mOneupSound, 0); mushIt = mMushrooms.erase(mushIt); // remove the entry from the list and advance iterator delete entity; // delete the object } else { ++mushIt; // advance list iterator } } // // generates a grayscale flash every 50 ms (if needed) // if (mFlashesNeeded > 0.0f) { if (mTime - mFlashTime > 0.1) { if ((int)mFlashesNeeded % 2) { SetEntitiesGrayscale(false); } else { SetEntitiesGrayscale(true); } mFlashesNeeded--; mFlashTime = mTime; } } // // create a new meteor every 0.2 to 1.2 seconds in scene 5 // if (mTime - mMeteorTime > GG::UnitRandom() + 0.2 && mScene == 5) { int randomX = GG::RandomInt(mScrWidth-64); int randomRotation = GG::RandomInt(90) + 180; randomRotation = (randomRotation % 2) ? randomRotation : -randomRotation; Meteor* meteor = new Meteor(randomX, -64, (double)randomRotation); mMeteors.push_back(meteor); // timestamp this meteor! mMeteorTime = mTime; } // Update the points label mTexMgr->DeleteTexture("PointsLabel"); std::stringstream newLabel; newLabel << "Points = " << mPoints; SDL_Color text_color = {0, 0, 0}; mTexMgr->LoadTexture("PointsLabel", newLabel.str().c_str(), text_color); delete mPointsLabel; mPointsLabel = new Label(10.0f, -5.0f, "PointsLabel"); // Update the lives label mTexMgr->DeleteTexture("LivesLabel"); newLabel.str(std::string()); newLabel << "Lives = " << mRobot->GetLives(); text_color.r = 255; text_color.g = 50; text_color.b = 50; mTexMgr->LoadTexture("LivesLabel", newLabel.str().c_str(), text_color); delete mLivesLabel; mLivesLabel = new Label(140.0f, -5.0f, "LivesLabel"); }