/* * 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: * Leo Merholz * Pascal Schärli * Co-authors: * ... * */ /** @file FlappyOrx.cc @brief Implementation of the FlappyOrx class. */ #include "FlappyOrx.h" #include "Highscore.h" #include "core/CoreIncludes.h" #include "core/EventIncludes.h" #include "core/command/Executor.h" #include "core/config/ConfigValueIncludes.h" #include "core/XMLPort.h" #include "gamestates/GSLevel.h" #include "chat/ChatManager.h" // ! HACK #include "infos/PlayerInfo.h" #include "FlappyOrxCenterPoint.h" #include "FlappyOrxShip.h" #include "core/command/ConsoleCommand.h" #include "worldentities/ExplosionPart.h" #include namespace orxonox { RegisterUnloadableClass(FlappyOrx); FlappyOrx::FlappyOrx(Context* context) : Deathmatch(context) { RegisterObject(FlappyOrx); this->center_ = nullptr; point = 0; //number of cleared tubes bIsDead = true; firstGame = true; //needed for the HUD tubeDistance=200; //distance between tubes tubeOffsetX=500; //tube offset (so that we can't see them spawn) circlesUsed=0; setHUDTemplate("FlappyOrxHUD"); } void FlappyOrx::updatePlayerPos(int x){ //Spawn a new Tube when the spawn distance is reached if(this->tubes.size()==0||x-tubes.back()+tubeOffsetX>tubeDistance){ spawnTube(); this->tubes.push(x+tubeOffsetX); } //Delete Tubes when we pass through them if(this->tubes.size()!=0&&x>this->tubes.front()){ this->tubes.pop(); levelUp(); } //Delete Asteroids which are not visible anymore while((this->asteroids.front())->getPosition().xdestroy(); } } //Gets called when we pass through a Tube void FlappyOrx::levelUp(){ point++; tubeDistance = tubeDistanceBase-tubeDistanceIncrease*point; //smaller spawn Distance getPlayer()->setSpeed(speedBase+speedIncrease*point); //increase speed } //Returns our Ship FlappyOrxShip* FlappyOrx::getPlayer(){ if (player == nullptr){ for (FlappyOrxShip* ship : ObjectList()) { player = ship; } } return player; } //Spawn new Tube void FlappyOrx::spawnTube(){ if (getPlayer() == nullptr) return; int space = 120; //vertical space between top and bottom tube int height = (float(rand())/RAND_MAX-0.5)*(280-space); //Randomize height Vector3 pos = player->getPosition(); //create the two Asteroid fields (Tubes) asteroidField(pos.x+tubeOffsetX,height-space/2,0.8); //bottom asteroidField(pos.x+tubeOffsetX,height+space/2,-0.8); //top } //Creates a new asteroid Field void FlappyOrx::asteroidField(int x, int y, float slope){ int r = 20; //Radius of added Asteroids int noadd = 0; //how many times we failed to add a new asteroid clearCircles(); //Delete Circles (we use circles to make sure we don't spawn two asteroids on top of eachother) Circle newAsteroid = Circle(); newAsteroid.x=x; newAsteroid.y=y; newAsteroid.r=r; addIfPossible(newAsteroid); //Add Asteroid at peak //Fill up triangle with asteroids while(noadd<5&&circlesUsed0) newAsteroid.y=float(rand())/RAND_MAX*(150+y)-150; //create asteroid on bottom else newAsteroid.y=float(rand())/RAND_MAX*(150-y)+y; //create asteroid on top newAsteroid.x=x+(float(rand())/RAND_MAX-0.5)*(y-newAsteroid.y)/slope; newAsteroid.r=r; int i = addIfPossible(newAsteroid); //Add Asteroid if it doesn't collide if(i==0) noadd++; else if(i==2) noadd=5; } } //Create a new Asteroid void FlappyOrx::createAsteroid(Circle &c){ MovableEntity* newAsteroid = new MovableEntity(this->center_->getContext()); //Add Model fitting the Size of the Asteroid if(c.r<=5) newAsteroid->addTemplate(Asteroid5[rand()%NUM_ASTEROIDS]); else if(c.r<=10) newAsteroid->addTemplate(Asteroid10[rand()%NUM_ASTEROIDS]); else if(c.r<=15) newAsteroid->addTemplate(Asteroid15[rand()%NUM_ASTEROIDS]); else newAsteroid->addTemplate(Asteroid20[rand()%NUM_ASTEROIDS]); //Set position newAsteroid->setPosition(Vector3(c.x, 0, c.y)); //Randomize orientation newAsteroid->setOrientation(Vector3::UNIT_Z, Degree(rand()%360)); newAsteroid->setOrientation(Vector3::UNIT_Y, Degree(rand()%360)); //add to Queue (so that we can delete it again) asteroids.push(newAsteroid); } //Deletes Asteroids array which stores all the circles used to make sure no asteroids collide when spawning void FlappyOrx::clearCircles(){ circlesUsed=0; for(int i = 0; inCircles; i++){ circles[i].r=0; } } //checks if two circles collide bool FlappyOrx::circleCollision(Circle &c1, Circle &c2){ if(c1.r<=0 || c2.r<=0) return false; int x = c1.x - c2.x; int y = c1.y - c2.y; int r = c1.r + c2.r; return x*x+y*ynCircles && this->circles[i].r!=0 && c.r>0;i++){ while(circleCollision(c,this->circles[i])){ c.r-=5; //when it collides, try to make it smaller } } if(c.r<=0){ return 0; } circlesUsed++; this->circles[i].x=c.x; this->circles[i].y=c.y; this->circles[i].r=c.r; createAsteroid(c); return 1; } void FlappyOrx::setCenterpoint(FlappyOrxCenterPoint* center){ this->center_ = center; } bool FlappyOrx::isDead(){ return bIsDead; } void FlappyOrx::setDead(bool value){ bIsDead = value; if(not value){ point = -1; levelUp(); } } void FlappyOrx::start() { // Set variable to temporarily force the player to spawn. this->bForceSpawn_ = true; if (this->center_ == nullptr) // abandon mission! { orxout(internal_error) << "FlappyOrx: No Centerpoint specified." << endl; GSLevel::startMainMenu(); return; } // Call start for the parent class. Deathmatch::start(); } //RIP void FlappyOrx::death(){ bIsDead = true; firstGame = false; //Set randomized deathmessages if(point<7) sDeathMessage = DeathMessage7[rand()%(DeathMessage7.size())]; else if(point<20) sDeathMessage = DeathMessage20[rand()%(DeathMessage20.size())]; else if(point<30) sDeathMessage = DeathMessage30[rand()%(DeathMessage30.size())]; else sDeathMessage = DeathMessageover30[rand()%(DeathMessageover30.size())]; //Update Highscore if (Highscore::exists()){ int score = this->getPoints(); if(score > Highscore::getInstance().getHighestScoreOfGame("Flappy Orx")) Highscore::getInstance().storeHighscore("Flappy Orx",score); } //Delete all Tubes and asteroids while (!tubes.empty()){ tubes.pop(); } while (!asteroids.empty()){ MovableEntity* deleteMe = asteroids.front(); asteroids.pop(); deleteMe->destroy(); } } void FlappyOrx::end() { if (Highscore::exists()){ int score = this->getPoints(); if(score > Highscore::getInstance().getHighestScoreOfGame("Orxonox Arcade")) Highscore::getInstance().storeHighscore("Orxonox Arcade",score); } GSLevel::startMainMenu(); } }