/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Viviane Yang * Co-authors: * ... * */ /** @file Asteroids2D.cc @brief Implementation of the Asteroids2D class. TODO: - Implement a counting system for the score - HUD can be improved (display health, points, level etc. - Problem: The asteroids spawn randomly on the playing field. During spawn or level up, there is the possibility that they pawn at the position of the ship. ->spawn somewhere with a safty distance/radius - look over collisionshapes of the stones -> sometimes collison with stone is not triggered for bigger stones - modify parameters in data/levels/templates/spaceshipAsteroids2D.oxt for a better playing experience -> mass, damping, rotation etc. IDEAS: - make Asteroids more beautiful! (setting, ship, explosion particles, stones) - particle effect after you got hit -> during bImmune is true - implement shield -> object that can be triggered - Projectiles should also move over the boarders and appear on the other side -> they can also hurt the player */ #include "Asteroids2D.h" #include "Asteroids2DShip.h" // Necessary for getPlayer function. Do NOT include this in Header! #include "Asteroids2DStone.h" #include "core/CoreIncludes.h" #include "Highscore.h" namespace orxonox { RegisterUnloadableClass(Asteroids2D); Asteroids2D::Asteroids2D(Context* context) : Deathmatch(context) { RegisterObject(Asteroids2D); bEndGame = false; lives = 3; level = 1; point = 0; bShowLevel = false; multiplier = 1; b_combo = false; firstTick_ = true; this->numberOfBots_ = 0; //sets number of default bots temporarly to 0 this->center_ = nullptr; this->setHUDTemplate("Asteroids2DHUD"); levelupTimer.setTimer(30.0f, true, createExecutor(createFunctor(&Asteroids2D::levelUp, this))); //level up every 30s } void Asteroids2D::levelUp() { level++; if (getPlayer() != nullptr) { //Do something that indicates a level up for (int i = 0; i < 7; i++) { WeakPtr chunk5 = new ExplosionPart(this->center_->getContext()); chunk5->setPosition(Vector3(600, 0, 100.f * i - 300)); chunk5->setVelocity(Vector3(1000, 0, 0)); //player->getVelocity() chunk5->setScale(10); chunk5->setEffect1("Orxonox/explosion2b"); chunk5->setEffect2("Orxonox/smoke6"); chunk5->Explode(); } } addPoints(multiplier * 20); multiplier *= 2; toggleShowLevel(); showLevelTimer.setTimer(1.0f, false, createExecutor(createFunctor(&Asteroids2D::toggleShowLevel, this))); //After level up -> spawn stones. Modify for different difficulty level for(int i = 0; i < level*2; i++){ spawnStone(); } } void Asteroids2D::tick(float dt) { //Do this only for the first tick, generate 5 stones in the beginning if(this->firstTick_) { getPlayer(); for(int i = 0; i < 5; ++i) { spawnStone(); } //after first tick, firstTick_ will remain false this->firstTick_ = false; } SUPER(Asteroids2D, tick, dt); } void Asteroids2D::spawnStone() { //stones are created with a size -> second constructor in Asteroids2DStone class Asteroids2DStone* newStone = new Asteroids2DStone(this->center_->getContext()); newStone->setAsteroids2DPlayer(player); //look at templates in data/levels/templates/asteroidsAsteroids2D.oxt switch(newStone->getSize()){ case 1: newStone->addTemplate("stone1"); break; case 2: newStone->addTemplate("stone2"); break; case 3: newStone->addTemplate("stone3"); break; default: orxout(internal_error) << "Asteroids2DStone has invalid size and cannot be created" << endl; break; } } Asteroids2DShip* Asteroids2D::getPlayer() { if (player == nullptr) { for (Asteroids2DShip* ship : ObjectList()) { player = ship; } } return player; } void Asteroids2D::costLife() { --lives; if(lives <= 0){ endGameTimer.setTimer(8.0f, false, createExecutor(createFunctor(&Asteroids2D::end, this))); } }; //The first function that will be called void Asteroids2D::start() { //orxout() << "start" << endl; // Set variable to temporarily force the player to spawn. this->bForceSpawn_ = false; if (this->center_ == nullptr) // abandon mission! { orxout(internal_error) << "Asteroids2D: No Centerpoint specified." << endl; GSLevel::startMainMenu(); return; } // Call start for the parent class. Deathmatch::start(); } void Asteroids2D::playerPreSpawn(PlayerInfo* player) { if(lives <= 0) { this->end(); } } //This function will be called from the ship or the stone class (if the stone was hit) void Asteroids2D::addPoints(int numPoints) { if (!bEndGame) { point += numPoints * multiplier; b_combo = true; } } void Asteroids2D::end() { // DON'T CALL THIS! // Deathmatch::end(); // It will misteriously crash the game! // Instead startMainMenu, this won't crash. if (Highscore::exists()){ int score = this->getPoints(); if(score > Highscore::getInstance().getHighestScoreOfGame("Asteroids2D")) Highscore::getInstance().storeHighscore("Asteroids2D",score); } GSLevel::startMainMenu(); } }