/* * 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: * Fabian 'x3n' Landau * Co-authors: * ... * */ /** @file OrxoBloxBall.cc @brief Implementation of the OrxoBloxBall class. */ #include "OrxoBloxBall.h" #include "OrxoBloxStones.h" #include "OrxoBlox.h" #include #include "core/CoreIncludes.h" #include "core/GameMode.h" #include "gametypes/Gametype.h" #include "sound/WorldSound.h" #include "core/XMLPort.h" #include "core/input/InputManager.h" namespace orxonox { RegisterClass(OrxoBloxBall); const float OrxoBloxBall::MAX_REL_Z_VELOCITY = 1.5; /** @brief Constructor. Registers and initializes the object. */ OrxoBloxBall::OrxoBloxBall(Context* context) : Pawn(context) { RegisterObject(OrxoBloxBall); this->speed_ = 0; this->accelerationFactor_ = 1.0f; this->relMercyOffset_ = 0.05f; this->orxoblox_ = this->getOrxoBlox(); this->radius_ = 3; this->registerVariables(); //initialize sound if (GameMode::isMaster()) { this->defScoreSound_ = new WorldSound(this->getContext()); this->defScoreSound_->setVolume(1.0f); this->defBoundarySound_ = new WorldSound(this->getContext()); this->defBoundarySound_->setVolume(0.5f); } else { this->defScoreSound_ = nullptr; this->defBoundarySound_ = nullptr; } } /** @brief Destructor. */ OrxoBloxBall::~OrxoBloxBall() { } //xml port for loading sounds void OrxoBloxBall::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(OrxoBloxBall, XMLPort, xmlelement, mode); XMLPortParam(OrxoBloxBall, "defScoreSound", setDefScoreSound, getDefScoreSound, xmlelement, mode); XMLPortParam(OrxoBloxBall, "defBoundarySound", setDefBoundarySound, getDefBoundarySound, xmlelement, mode); } /** @brief Register variables to synchronize over the network. */ void OrxoBloxBall::registerVariables() { registerVariable( this->fieldWidth_ ); registerVariable( this->fieldHeight_ ); registerVariable( this->speed_ ); registerVariable( this->relMercyOffset_ ); } /** @brief Is called every tick. Handles the movement of the ball and its interaction with the boundaries and bats. @param dt The time since the last tick. */ void OrxoBloxBall::tick(float dt) { SUPER(OrxoBloxBall, tick, dt); // Get the current position, velocity and acceleration of the ball. Vector3 position = this->getPosition(); Vector3 velocity = this->getVelocity(); Vector3 acceleration = this->getAcceleration(); // If the ball has gone over the top or bottom boundary of the playing field (i.e. the ball has hit the top or bottom delimiters). if (position.z > this->fieldHeight_ / 2 || position.z - radius_ < -this->fieldHeight_ / 2) { defBoundarySound_->play(); //play boundary sound // Its velocity in z-direction is inverted (i.e. it bounces off). velocity.z = -velocity.z; // And its position is set as to not overstep the boundary it has just crossed. Remember z axis is reverted!!! if (position.z > this->fieldHeight_ / 2){ // Set the ball to be exactly at the boundary. position.z = this-> fieldHeight_ / 2 - radius_; orxoblox_->LevelUp(); //this->setSpeed(0); // doesn't work here, why??; //Stopping ball orxout() << "Ball stopped" << endl; velocity.x = 0; velocity.y = 0; velocity.z = 0; //ChatManager::message("Waiting for your input"); //Input new speed here: //ChatManager::message("Setting new speed"); //%%%%%%%%%%%% //MAUSPOSITION //%%%%%%%%%%%% //Reads current mouse position //TODO: read Mouse position on click! //int mousex = InputManager::getInstance().getMousePosition().first; //int mousey = InputManager::getInstance().getMousePosition().second; //ChatManager::message("Read mouse position"); //orxout() << "Mouseposition" << endl; //orxout() << mousex << endl; //ChatManager::message(mousex); //ChatManager::message("mousey"); //ChatManager::message(mousey); //Set new speed here!! velocity.x = rnd(-100,100); velocity.z = rnd(-50,-100); } if (position.z - radius_ < -this->fieldHeight_ / 2){ position.z = -this->fieldHeight_ / 2 + radius_; } this->fireEvent(); } //Ball hits the right or left wall and should bounce back. // If the ball has crossed the left or right boundary of the playing field. if (position.x + radius_ > this->fieldWidth_ / 2 || position.x - radius_ < -this->fieldWidth_ / 2) { //Ball hits the right Wall if (position.x + radius_ > this->fieldWidth_ / 2) { // Set the ball to be exactly at the boundary. position.x = this->fieldWidth_ / 2 - radius_; // Invert its velocity in x-direction (i.e. it bounces off). velocity.x = -velocity.x; this->fireEvent(); } //Ball hits the left wall else if (position.x - radius_ < -this->fieldWidth_ / 2) { // Set the ball to be exactly at the boundary. position.x = -this->fieldWidth_ / 2 + radius_; // Invert its velocity in x-direction (i.e. it bounces off). velocity.x = -velocity.x; this->fireEvent(); } } // Set the position, velocity and acceleration of the ball, if they have changed. if (acceleration != this->getAcceleration()) this->setAcceleration(acceleration); if (velocity != this->getVelocity()) this->setVelocity(velocity); if (position != this->getPosition()) this->setPosition(position); //this->Collides((this->orxoblox_->CheckForCollision(this))); } /** @brief Set the speed of the ball (in x-direction). @param speed The speed to be set. */ void OrxoBloxBall::setSpeed(float speed) { if (speed != this->speed_) // If the speed changes { this->speed_ = speed; // Set the speed in the direction of the balls current velocity. Vector3 velocity = this->getVelocity(); if (velocity.x != 0) velocity.x = speed; //velocity.x = sgn(velocity.x) * speed; else // If the balls current velocity is zero, the speed is set in a random direction. velocity.x = speed * sgn(rnd(-1,1)); //velocity.y = this->speed_; velocity.z = speed; this->setVelocity(velocity); } } void OrxoBloxBall::setDefScoreSound(const std::string &OrxoBloxSound) { if( defScoreSound_ ) defScoreSound_->setSource(OrxoBloxSound); else assert(0); // This should never happen, because soundpointer is only available on master } const std::string& OrxoBloxBall::getDefScoreSound() { if( defScoreSound_ ) return defScoreSound_->getSource(); else assert(0); return BLANKSTRING; } void OrxoBloxBall::setDefBoundarySound(const std::string &OrxoBloxSound) { if( defBoundarySound_ ) defBoundarySound_->setSource(OrxoBloxSound); else assert(0); // This should never happen, because soundpointer is only available on master } const std::string& OrxoBloxBall::getDefBoundarySound() { if( defBoundarySound_ ) return defBoundarySound_->getSource(); else assert(0); return BLANKSTRING; } void OrxoBloxBall::Bounce(WorldEntity* Stone) { Vector3 velocity = this->getVelocity(); Vector3 positionStone = Stone->getPosition(); Vector3 myPosition = this->getPosition(); orxout() << "About to Bounce >D" << endl; int distance_X = myPosition.x - positionStone.x; int distance_Z = myPosition.z - positionStone.z; if (distance_X < 0) distance_X = -distance_X; if (distance_Z < 0) distance_Z = -distance_Z; orxout() << distance_X << endl; orxout() << distance_Z << endl; if (distance_X < distance_Z) { velocity.z = -velocity.z; orxout() << "z" << endl; } else if (distance_Z < distance_X) { velocity.x = -velocity.x; orxout() << "x" << endl; } else { velocity.x = -velocity.x; velocity.z = -velocity.z; orxout() << "both" << endl; } this->setVelocity(velocity); this->setPosition(myPosition); } void OrxoBloxBall::Collides(OrxoBloxStones* Stone) { if(Stone == nullptr) return; orxout() << "About to Bounce >D" << endl; Bounce(Stone); //if(otherObject->getHealth() <= 0) { //Stone->destroy(); //} //otherObject->reduceHealth(); } bool OrxoBloxBall::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) { orxout() << "detected collision" << endl; Bounce(otherObject); return true; } OrxoBlox* OrxoBloxBall::getOrxoBlox() { if (this->getGametype() != nullptr && this->getGametype()->isA(Class(OrxoBlox))) { OrxoBlox* orxobloxGametype = orxonox_cast(this->getGametype()); return orxobloxGametype; } else orxout()<<"There is no Gametype for OrxoBlox! ask Anna"<< endl; return nullptr; } float OrxoBloxBall::getRadius() { return this->radius_; } }