void Game::initLevel() { int meteors; switch (Configuration::level) { case 1: meteors = 4; break; case 2: meteors = 5; break; case 3: meteors = 7; break; case 4: meteors = 9; break; default: meteors = 11; break; } for (int i = 0; i < meteors; ++i) { Meteor *meteor = new BigMeteor(_world); do { meteor->setPosition(Utils::random(0.f, (float) _world.getWidth()), Utils::random(0.f, (float) _world.getHeight())); } while (_world.isCollide(*meteor)); _world.add(meteor); } }
void Game::updateBullet(double dt, vector<Node*>::iterator nodeIt) { Bullet* bullet = (Bullet*) (*nodeIt); // Move the bullet up bullet->translate(0.0f, dt * bullet->getSpeed()); // Mark it for deletion if it's out if (bullet->isOut()) { deleted_.push_back(nodeIt - scene_.begin()); } // Detect if bullet hit meteor for (vector<Node*>::iterator node = scene_.begin(); node < scene_.end(); ++node) { enum NodeType type = (*node)->getType(); // And if it hit... if ((type == METEOR || type == SMALL_METEOR) && bullet->isIntersect(*node)) { // Remove the bullet deleted_.push_back(nodeIt - scene_.begin()); // Remove the meteor deleted_.push_back(node - scene_.begin()); // And if it is a big one set flag to spawn small meteors if (type == METEOR) { Meteor* meteor = (Meteor*) (*node); smallMeteorX_ = meteor->getX(); smallMeteorY_ = meteor->getY(); score_++; } else { score_ += 2; } } } }
Meteor::Meteor(const Meteor& s) : Drawable(s), explosion( s.explosion ), zoom( s.zoom ), frame(s.frame), frameWidth(s.getFrame()->getWidth()), frameHeight(s.getFrame()->getHeight()), worldWidth(Gamedata::getInstance().getXmlInt("world/width")), worldHeight(Gamedata::getInstance().getXmlInt("world/height")), hasExploded( s.hasExploded ) { }
void Game::initLevel() { int nb_meteors; switch(Configuration::level) { case 1 : nb_meteors = 4;break; case 2 : nb_meteors = 5;break; case 3 : nb_meteors = 7;break; case 4 : nb_meteors = 9;break; default : nb_meteors = 11;break; } for(int i = 0; i<nb_meteors;++i) { Meteor* meteor = new BigMeteor(_world); do{ meteor->setPosition(random(0.f,(float)_world.getX()),random(0.f,(float)_world.getY())); }while(_world.isCollide(*meteor)); _world.add(meteor); } }
void Game::updateMeteor(double dt, vector<Node*>::iterator nodeIt) { Meteor* meteor = (Meteor*) (*nodeIt); // Move meteor meteor->translate(meteor->getXFallSpeed(), dt * meteor->getYFallSpeed()); // Make it spin meteor->rotate(meteor->getRotateSpeed()); // Mark it for deletion if it's out if (meteor->isOut()) { deleted_.push_back(nodeIt - scene_.begin()); } // If meteor hit shuttle than the game is over if (shuttle_->isIntersect(meteor)) { isOver_ = true; } }
void Game::DoTick() { // Tutorial 3: Walk the meteor list. // This looks really clunky to me...there's probably a better way. // Just be careful not to delete the iterator you are using. std::list< Meteor* >::iterator it = meteorList.begin(); while ( it != meteorList.end() ) { Meteor* meteor = *it; if ( meteor->Done() ) { std::list< Meteor* >::iterator deleteIt = it; ++it; meteorList.erase( deleteIt ); delete meteor; } else { meteor->DoTick(); ++it; } } // Tutorial 4: Weather U32 day, hour, minute, second; Lilith3D::GetTimeClock()->CalcCalendarTime( &day, &hour, &minute, &second ); Weather* weather = lilith->GetTargetWeather(); // This is just so we don't keep calling this withou // significant time change. Look for the 'minute' in // game time to actually be different. if ( weatherMinute != minute ) { const float FOG_MAX = 0.7f; const U32 FOG_START = 2; const U32 FOG_PEAK = 7; const U32 FOG_END = 11; const int RAIN_START = 16; const int RAIN_PEAK = 20; const int RAIN_END = 23; if ( hour >= FOG_START && hour <= FOG_END ) { // Fog in the morning. if ( hour < FOG_PEAK ) weather->SetFog( FOG_MAX * Interpolate( (float)FOG_START*60, (float)0.0f, (float)FOG_PEAK*60, (float)1.0, (float)(hour*60+minute) ) ); else weather->SetFog( FOG_MAX * Interpolate( (float)FOG_PEAK*60, (float)1.0f, (float)FOG_END*60, (float)0.0, (float)(hour*60+minute) ) ); } else if ( hour >= RAIN_START && hour <= RAIN_END ) { // Rain in the evening - be sure to set a little fog too. Rain // looks bad without fog. if ( hour < RAIN_PEAK ) { weather->SetRain( Interpolate( (float)RAIN_START*60, (float)0.0f, (float)RAIN_PEAK*60, (float)1.0, (float)(hour*60+minute) ) ); weather->SetFog( 0.5f * Interpolate( (float)RAIN_START*60, (float)0.0f, (float)RAIN_PEAK*60, (float)1.0, (float)(hour*60+minute) ) ); } else { weather->SetRain( Interpolate( (float)RAIN_PEAK*60, (float)1.0f, (float)RAIN_END*60, (float)0.0, (float)(hour*60+minute) ) ); weather->SetFog( 0.5f * Interpolate( (float)RAIN_PEAK*60, (float)1.0f, (float)RAIN_END*60, (float)0.0, (float)(hour*60+minute) ) ); } } else { weather->SetRain( 0.0f ); weather->SetFog( 0.0f ); } } }
void Game::work(double dt) { dt = fmin(dt, 1.0f); // Clear some buffers glClearColor(0.2353f, 0.2471f, 0.2549f, 1.0f); checkGlError("glClearColor"); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); checkGlError("glClear"); // Use some programs glUseProgram(gProgram_); checkGlError("glUseProgram"); glLineWidth(2.0f); // Randomly generate meteors at approximate rate one per second if ( ((float)rand() / RAND_MAX) < dt ) { Meteor* meteor = new Meteor(); float sky = (float) width_ / (float)height_; float x = ((float)rand() / RAND_MAX) * sky - sky / 2; meteor->translate(x, 1.0f); meteor->updateXSpeed(); scene_.push_back(meteor); } // Render scene loop for (vector<Node*>::iterator node = scene_.begin(); node < scene_.end(); ++node) { // Let's draw it (*node)->draw(dt, gaPositionHandle_, gaColorHandle_, guVeiwProjHandle_, mProj_); enum NodeType type = (*node)->getType(); // If it is a meteor than update it's position and stuff if (type == METEOR || type == SMALL_METEOR) { updateMeteor(dt, node); } // Do the same for bullet if (type == BULLET) { updateBullet(dt, node); } } if (!deleted_.empty()) { // Sort "deleted" array to be able remove elements in right order sort(deleted_.begin(), deleted_.end()); // Remove duplicates deleted_.erase( unique( deleted_.begin(), deleted_.end() ), deleted_.end() ); } // Remove elements in backwards order for (int i = deleted_.size() - 1; i >= 0; --i) { int index = deleted_[i]; delete scene_[index]; scene_.erase(scene_.begin() + index); } // All useless elements are deleted so clear the "deleted array" deleted_.clear(); // If flag is set than it's time to spawn small ones // And if we hit meteor at (0, 0), well.. than it's a lucky shot if (smallMeteorX_ || smallMeteorY_) { for (int i = 0; i < smallMeteors; ++i) { SmallMeteor* smallMeteor = new SmallMeteor(smallMeteorX_, smallMeteorY_); scene_.push_back(smallMeteor); } // Clear the spawn flag smallMeteorX_ = smallMeteorY_ = 0.0f; } }
/* ================================================================================ 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"); }
// Tells the entities to use their grayscale renderables // instead of their colored ones (applies to all entities) void Game::SetEntitiesGrayscale(bool grayscale) { if (mRobot) mRobot->SetGrayscale(grayscale); if (mBackground) mBackground->SetGrayscale(grayscale); if (mForeground) mForeground->SetGrayscale(grayscale); if (mFlagPole) mFlagPole->SetGrayscale(grayscale); 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++) { Tile* tile = mGrid->GetTile(y, x); if (tile->GetRenderable()) { tile->SetGrayscale(grayscale); } tileRect.x += tileWidth; } tileRect.y += tileHeight; tileRect.x = 0; } } std::list<Explosion*>::iterator it = mExplosions.begin(); for ( ; it != mExplosions.end(); ++it) { Explosion* boom = *it; boom->SetGrayscale(grayscale); } std::list<Meteor*>::iterator metIt = mMeteors.begin(); for ( ; metIt != mMeteors.end(); ++metIt) { Meteor* meteor = *metIt; meteor->SetGrayscale(grayscale); } std::list<Crawler*>::iterator crawlerIter = mCrawlers.begin(); for ( ; crawlerIter != mCrawlers.end(); ++crawlerIter) { Crawler* crawler = *crawlerIter; crawler->SetGrayscale(grayscale); } std::list<Coin*>::iterator coinIter = mCoins.begin(); for ( ; coinIter != mCoins.end(); ++coinIter) { Coin* coin = *coinIter; coin->SetGrayscale(grayscale); } std::list<Layer*>::iterator mushIter = mMushrooms.begin(); for ( ; mushIter != mMushrooms.end(); ++mushIter) { Layer* mushroom = *mushIter; mushroom->SetGrayscale(grayscale); } }