/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Knecht co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY #include "helicopter.h" #include "weapons/weapon_manager.h" #include "weapons/test_gun.h" #include "weapons/turret.h" #include "weapons/cannon.h" #include "factory.h" #include "key_mapper.h" #include "event_handler.h" #include "state.h" #include "graphics_engine.h" using namespace std; CREATE_FACTORY(Helicopter, CL_HELICOPTER); /** * creates the controlable Helicopter */ Helicopter::Helicopter() { this->init(); } /** * destructs the helicopter, deletes alocated memory */ Helicopter::~Helicopter () { } /** * loads a Helicopter information from a specified file. * @param fileName the name of the File to load the helicopter from (absolute path) */ Helicopter::Helicopter(const char* fileName) { this->init(); TiXmlDocument doc(fileName); if(!doc.LoadFile()) { PRINTF(2)("Loading file %s failed for Helicopter.\n", fileName); return; } this->loadParams(doc.RootElement()); } /** * creates a new Spaceship from Xml Data * @param root the xml element containing spaceship data @todo add more parameters to load */ Helicopter::Helicopter(const TiXmlElement* root) { this->init(); if (root != NULL) this->loadParams(root); //weapons: Weapon* wpRight = new TestGun(0); wpRight->setName("testGun Right"); Weapon* wpLeft = new TestGun(1); wpLeft->setName("testGun Left"); Weapon* cannon = dynamic_cast(Factory::fabricate(CL_CANNON)); cannon->setName("BFG"); this->addWeapon(wpLeft, 1, 0); this->addWeapon(wpRight,1 ,1); this->addWeapon(cannon, 0, 6); this->getWeaponManager()->changeWeaponConfig(1); dynamic_cast(this->getWeaponManager()->getFixedTarget())->setVisibility( false); } /** * initializes a Helicopter */ void Helicopter::init() { this->setClassID(CL_HELICOPTER, "Helicopter"); PRINTF(4)("HELICOPTER INIT\n"); this->loadModel("models/ships/helicopter_#.obj", 1.0); EventHandler::getInstance()->grabEvents(true); bUp = bDown = bLeft = bRight = bAscend = bDescend = bRollL = bRollR = false; bFire = false; xMouse = yMouse = 0; mouseSensitivity = 0.05; controlVelocityX = 100; controlVelocityY = 100; // initialization of cameraNode this->cameraNode.setParent(this); this->cameraNode.setParentMode(PNODE_ALL); this->cameraNode.setRelCoor(Vector(0,1,0)); // rotors this->topRotor.addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT); this->tailRotor.addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT); this->topRotor.setParent(this); this->tailRotor.setParent(this); this->topRotor.setRelCoor(Vector(-0.877,0.627,0)); this->tailRotor.setRelCoor(Vector(-4.43,0.297,0.068)); this->tailRotor.setAbsDir(Quaternion(M_PI_2,Vector(1,0,0))); this->loadModel("models/ships/rotor.obj",1.0,3); this->loadModel("models/ships/rotor.obj",0.2,4); this->velocity = Vector(0.0,0.0,0.0); this->velocityDir = Vector(1.0,0.0,0.0); // very, very old stuff // GLGuiButton* button = new GLGuiPushButton(); // button->show(); // button->setLabel("orxonox"); // button->setBindNode(this); //add events to the eventlist registerEvent(KeyMapper::PEV_UP); registerEvent(KeyMapper::PEV_DOWN); registerEvent(KeyMapper::PEV_LEFT); registerEvent(KeyMapper::PEV_RIGHT); registerEvent(SDLK_e); registerEvent(SDLK_c); registerEvent(KeyMapper::PEV_FIRE1); registerEvent(KeyMapper::PEV_NEXT_WEAPON); registerEvent(KeyMapper::PEV_PREVIOUS_WEAPON); registerEvent(EV_MOUSE_MOTION); this->getWeaponManager()->setSlotCount(7); this->getWeaponManager()->setSlotPosition(0, Vector(-2.6, .1, -3.0)); this->getWeaponManager()->setSlotCapability(0, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL); this->getWeaponManager()->setSlotPosition(1, Vector(-2.6, .1, 3.0)); this->getWeaponManager()->setSlotCapability(1, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL); this->getWeaponManager()->setSlotPosition(2, Vector(-1.5, .5, -.5)); this->getWeaponManager()->setSlotDirection(2, Quaternion(-M_PI_4*.5, Vector(1,0,0))); this->getWeaponManager()->setSlotPosition(3, Vector(-1.5, .5, .5)); this->getWeaponManager()->setSlotDirection(3, Quaternion(M_PI_4*.5, Vector(1,0,0))); this->getWeaponManager()->setSlotPosition(4, Vector(-1.5, -.5, .5)); this->getWeaponManager()->setSlotDirection(4, Quaternion(-M_PI_4*.5+M_PI, Vector(1,0,0))); this->getWeaponManager()->setSlotPosition(5, Vector(-1.5, -.5, -.5)); this->getWeaponManager()->setSlotDirection(5, Quaternion(+M_PI_4*.5-M_PI, Vector(1,0,0))); this->getWeaponManager()->setSlotPosition(6, Vector(-1, 0.0, 0)); this->getWeaponManager()->setSlotCapability(6, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL); this->getWeaponManager()->getFixedTarget()->setParent(&(this->cameraNode)); this->getWeaponManager()->getFixedTarget()->setRelCoor(0,0,0); dynamic_cast(this->getWeaponManager()->getFixedTarget())->setVisibility( false); } /** * loads the Settings of a Helicopter from an XML-element. * @param root the XML-element to load the Spaceship's properties from */ void Helicopter::loadParams(const TiXmlElement* root) { WorldEntity::loadParams(root); } void Helicopter::enter() { dynamic_cast(this->getWeaponManager()->getFixedTarget())->setVisibility( true); State::getCamera()->setParentSoft(this->getWeaponManager()->getFixedTarget()); State::getCameraTarget()->setParentSoft(this->getWeaponManager()->getFixedTarget()); } void Helicopter::leave() { dynamic_cast(this->getWeaponManager()->getFixedTarget())->setVisibility( false); this->detachCamera(); } /** * effect that occurs after the Helicopter is spawned */ void Helicopter::postSpawn () { //setCollision(new CollisionCluster(1.0, Vector(0,0,0))); } /** * the action occuring if the helicopter left the game */ void Helicopter::leftWorld () {} /** * this function is called, when two entities collide * @param entity: the world entity with whom it collides * * Implement behaviour like damage application or other miscellaneous collision stuff in this function */ void Helicopter::collidesWith(WorldEntity* entity, const Vector& location) { } /** * the function called for each passing timeSnap * @param time The timespan passed since last update */ void Helicopter::tick (float time) { Playable::tick(time); if( xMouse != 0 || yMouse != 0) { if (xMouse > controlVelocityX) xMouse = controlVelocityX; else if (xMouse < -controlVelocityX) xMouse = -controlVelocityX; if (yMouse > controlVelocityY) yMouse = controlVelocityY; else if (yMouse < -controlVelocityY) yMouse = -controlVelocityY; } // rotorrotation this->topRotor.shiftDir(Quaternion(time*10, Vector(0,1,0))); this->tailRotor.shiftDir(Quaternion(time*10, Vector(0,1,0))); // spaceship controlled movement this->calculateVelocity(time); Vector move = (velocity)*time; // this is the air friction (necessary for a smooth control) if(velocity.len() != 0) velocity -= velocity*0.1; //readjust // if (this->getAbsDirZ().y > 0.1) this->shiftDir(Quaternion(time*0.3, Vector(1,0,0))); // else if (this->getAbsDirZ().y < -0.1) this->shiftDir(Quaternion(-time*0.3, Vector(1,0,0))); this->shiftCoor (move); } /** * calculate the velocity * @param time the timeslice since the last frame */ void Helicopter::calculateVelocity (float time) { Vector accel(0.0, 0.0, 0.0); float rotValX = 0.0; float rotValZ = 0.0; /* FIXME: calculating the direction and orthDirection every timeSlice is redundant! save it somewhere */ /* calculate the direction in which the craft is heading */ if( this->bUp ) { //this->shiftCoor(this->getAbsDirX()); //accel -= this->getAbsDirY(); accel += Vector((this->getAbsDirX()).x,0,(this->getAbsDirX()).z); if((this->getAbsDirX()).y >= -0.1) rotValZ -= time; } else { if(this->getAbsDirX().y < -.02) this->shiftDir(Quaternion(time, Vector(0,0,1))); } if( this->bDown ) { //this->shiftCoor((this->getAbsDirX())*-1); //accel -= this->getAbsDirY(); accel -= Vector((this->getAbsDirX()).x,0,(this->getAbsDirX()).z); rotValZ += time; } else { if(this->getAbsDirX().y > 0.02) this->shiftDir(Quaternion(-time, Vector(0,0,1))); } if( this->bLeft ) { //this->shiftDir(Quaternion(time, Vector(0,1,0))); //accel -= this->getAbsDirY(); //velocityDir.normalize(); accel -= Vector((this->getAbsDirZ()).x,0,(this->getAbsDirZ()).z); rotValX -= time; } else { if(this->getAbsDirZ().y > 0.02) this->shiftDir(Quaternion(time, Vector(1,0,0))); } if( this->bRight ) { //this->shiftDir(Quaternion(-time, Vector(0,1,0))); //accel += this->getAbsDirY(); //velocityDir.normalize(); accel += Vector((this->getAbsDirZ()).x,0,(this->getAbsDirZ()).z); rotValX += time; } else { if(this->getAbsDirZ().y < -0.02) this->shiftDir(Quaternion(-time, Vector(1,0,0))); } if( this->bRollL ) { this->shiftDir(Quaternion(-time, Vector(1,0,0))); } if( this->bRollR ) { this->shiftDir(Quaternion(time, Vector(1,0,0))); } if (this->bAscend ) { accel += this->getAbsDirY(); } if (this->bDescend ) { accel -= this->getAbsDirY(); } velocity += accel*3; if((this->getAbsDirX()).y <= 0.3 && (this->getAbsDirX()).y >= -0.3) this->shiftDir(Quaternion(rotValZ, Vector(0,0,1))); if((this->getAbsDirZ()).y <= 0.3 && (this->getAbsDirZ()).y >= -0.3) this->shiftDir(Quaternion(rotValX, Vector(1,0,0))); } void Helicopter::draw() const { WorldEntity::draw(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* translate */ glTranslatef (this->topRotor.getAbsCoor ().x, this->topRotor.getAbsCoor ().y, this->topRotor.getAbsCoor ().z); Vector tmpRot = this->topRotor.getAbsDir().getSpacialAxis(); glRotatef (this->topRotor.getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z ); this->getModel(3)->draw(); glPopMatrix (); glPushMatrix(); /* translate */ glTranslatef (this->tailRotor.getAbsCoor ().x, this->tailRotor.getAbsCoor ().y, this->tailRotor.getAbsCoor ().z); tmpRot = this->tailRotor.getAbsDir().getSpacialAxis(); glRotatef (this->tailRotor.getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z ); this->getModel(4)->draw(); glPopMatrix (); } /** * @todo switch statement ?? */ void Helicopter::process(const Event &event) { Playable::process(event); if( event.type == KeyMapper::PEV_LEFT) this->bLeft = event.bPressed; else if( event.type == KeyMapper::PEV_RIGHT) this->bRight = event.bPressed; else if( event.type == SDLK_e) this->bAscend = event.bPressed; else if( event.type == SDLK_c) this->bDescend = event.bPressed; else if( event.type == KeyMapper::PEV_UP) this->bUp = event.bPressed; else if( event.type == KeyMapper::PEV_DOWN) this->bDown = event.bPressed; else if( event.type == EV_MOUSE_MOTION) { this->xMouse = event.xRel*mouseSensitivity; this->yMouse = event.yRel*mouseSensitivity; this->shiftDir(Quaternion(-M_PI/4*xMouse*mouseSensitivity, Vector(0,1,0))); Quaternion yDir = Quaternion(-M_PI/4*yMouse*mouseSensitivity, Vector(0,0,1)); if ((this->cameraNode.getAbsDirY()).y < 0.5) { if((this->cameraNode.getAbsDirX()).y > 0) { if(yMouse > 0) this->cameraNode.shiftDir(yDir); } else { if(yMouse < 0) this->cameraNode.shiftDir(yDir); } } else this->cameraNode.shiftDir(yDir);; } }