📄 simplescenes_crash.h
字号:
else if(input->isKeyDown(KC_K)) _main_spd -= (_main_response * time);
// Thrust left, right, forward, or back
_thrust_force = Vector3::ZERO;
if(input->isKeyDown(KC_G)) _thrust_force.z += _thrust;
if(input->isKeyDown(KC_B)) _thrust_force.z -= _thrust;
if(input->isKeyDown(KC_V)) _thrust_force.x += _thrust;
if(input->isKeyDown(KC_N)) _thrust_force.x -= _thrust;
// Clamp the main rotor speed
_main_spd = std::max(_main_min,std::min(_main_max,_main_spd));
// Turn left or right or automatically stop the tail rotor
if(input->isKeyDown(KC_J)) _tail_spd += (_tail_response * time);
else if(input->isKeyDown(KC_L)) _tail_spd -= (_tail_response * time);
else
{
if(_tail_spd < 0.0)
{
_tail_spd += (_tail_response * time);
if(_tail_spd > 0.0) _tail_spd = 0.0;
}
else if(_tail_spd > 0.0)
{
_tail_spd -= (_tail_response * time);
if(_tail_spd < 0.0) _tail_spd = 0.0;
}
}
// Clamp the tail rotor speed
_tail_spd = std::max(_tail_min,std::min(_tail_max,_tail_spd));
// Rotate the tail rotor scene node
_tail_rotor_node->rotate(Vector3::UNIT_X,Radian(_tail_spd * time * _rotate_scale));
// If there's some power being applied to the main rotor then...
if((_main_spd > _main_min)||(!input->isKeyDown(KC_K)))
{
// Rotate the main rotor scene node
_main_rotor_node->rotate(Vector3::UNIT_Y,Radian(_main_spd * time * _rotate_scale));
_apply_damping = true;
}
else _apply_damping = false;
// Fire rockets. Woo!
_fire_time += time;
if((_fire_time > _fire_rate)&&(input->isKeyDown(KC_X)))
{
_fire_time = 0.0;
_rockets++;
// Create a rocket node and attach a particle system to it
String name = String("Rocket_") + StringConverter::toString(_rockets);
ParticleSystem* rocket = ParticleSystemManager::getSingleton().createSystem(name,"OgreOdeDemos/Rocket");
SceneNode* rocket_node = _mgr->getRootSceneNode()->createChildSceneNode(name);
rocket_node->attachObject(rocket);
// Alternate firing between the left and right pods and
// convert it from body coordinates to world
// Do the same with the firing "force" vector
Vector3 pos = _apache->getPointWorldPosition(Vector3(1.35 * ((_rockets & 1)?-1.0:1.0),-0.55,0.95));
Vector3 force =_apache->getVectorToWorld(Vector3(0,0,_fire_force));
rocket_node->setPosition(pos);
// Create a sphere for the physical body
OgreOde::Body* rocket_body = new OgreOde::Body();
OgreOde::SphereGeometry* rocket_geom = new OgreOde::SphereGeometry(_fire_size,_apache_space);
rocket_body->setMass(OgreOde::SphereMass(_fire_mass,_fire_size));
rocket_body->setAffectedByGravity(false);
rocket_geom->setBody(rocket_body);
rocket_node->attachObject(rocket_body);
_bodies.push_back(rocket_body);
_geoms.push_back(rocket_geom);
// Fire it off by applying an initial force
rocket_body->addForce(force);
// Initialise the rocket's life span to zero
_rocket_list[rocket_geom] = 0.0;
}
// Check all the rockets
for(std::map<OgreOde::SphereGeometry*,Real>::iterator i = _rocket_list.begin();i != _rocket_list.end();)
{
// Increase the time it's lived
i->second += time;
// If it had it's emitter disabled (see below) more than 2 seconds ago then kill it
if((i->second < 0.0)&&(i->second > -98.0))
{
// Get the geometry's body and kill any particle system attached to the same node
OgreOde::Body* body = i->first->getBody();
killParticleSystem(i->first);
// Manually remove the body from the list of managed bodies
for(std::vector<OgreOde::Body*>::iterator bi = _bodies.begin();bi != _bodies.end();)
{
if((*bi) == body) bi = _bodies.erase(bi);
else ++bi;
}
// Manually delete the geometry from the list of managed geometries
for(std::vector<OgreOde::Geometry*>::iterator gi = _geoms.begin();gi != _geoms.end();)
{
if((*gi) == i->first)gi = _geoms.erase(gi);
else ++gi;
}
// Delete the actual body and geometry
delete body;
delete i->first;
// Erase the rocket from the hashmap
_rocket_list.erase(i++);
}
else
{
// If the rocket has been alive for more than 2 seconds then kill its emitters (so it fades away)
if(i->second > 2.0)
{
killEmitters(i->first,&(i->second));
}
++i;
}
}
}
// Override the base collision callback, 'cos we don't want the "if connected" check doing
bool SimpleScenes_Crash::collision(OgreOde::Contact* contact)
{
// If a rocket's hit something then stop emitting particles
std::map<OgreOde::SphereGeometry*,Real>::iterator li = _rocket_list.find(static_cast<OgreOde::SphereGeometry*>(contact->getFirstGeometry()));
if(li != _rocket_list.end())
{
killEmitters(li->first,&(li->second));
}
else
{
li = _rocket_list.find(static_cast<OgreOde::SphereGeometry*>(contact->getSecondGeometry()));
if(li != _rocket_list.end())
{
killEmitters(li->first,&(li->second));
}
}
// Set the friction at the contact
contact->setCoulombFriction(5.0);
// Yes, this collision is valid
return true;
}
// Will get called just before each time step, since a timestep zeros the force accumulators
void addForcesAndTorques()
{
// Apply the main rotor force
_apache->addForce(Vector3(0,_main_spd * _main_scale,0));
// Apply the tail rotor torque
_apache->addRelativeTorque(Vector3(0,_tail_spd * _tail_scale,0));
// Apply the thrust force
_apache->addRelativeForceAtRelative(_thrust_force,_thrust_offs);
// Apply damping if the engine's not off
if(_apply_damping)
{
// Apply angular damping
Vector3 a_velocity = _apache->getAngularVelocity();
_apache->addTorque(a_velocity * -_angular_damp);
// Apply linear damping
Vector3 l_velocity = _apache->getLinearVelocity();
_apache->addForce(l_velocity * -_linear_damp);
}
}
protected:
// Kill the emitters for any particle systems attached to the same node
// as the body with which the specified geometry is associated (if that makes sense!)
void killEmitters(OgreOde::SphereGeometry* geom,Real* time = 0)
{
// Find the body
OgreOde::Body* body = geom->getBody();
if(body)
{
// Find the associated scene node
SceneNode* node = static_cast<SceneNode*>(body->getParentNode());
if(node)
{
// Kill the emitters of any attached particle systems
for(int i = 0;i < node->numAttachedObjects();i++)
{
MovableObject* obj = node->getAttachedObject(i);
if(obj->getMovableType() == "ParticleSystem")
{
static_cast<ParticleSystem*>(obj)->removeAllEmitters();
}
}
}
// Set the life span value so that we can easily tell
// that its had its emitters deleted
if(time) *time = -100.0;
}
}
// Kill the particle system and scene node associated with this geometry
void killParticleSystem(OgreOde::SphereGeometry* geom)
{
// Find the body
OgreOde::Body* body = geom->getBody();
if(body)
{
// Find the scene node
SceneNode* node = static_cast<SceneNode*>(body->getParentNode());
if(node)
{
MovableObject* obj = 0;
for(int i = 0;i < node->numAttachedObjects();i++)
{
// If this object isn't an OgreOde::Body then it must be
// (in our demo) a particle system that we need to delete
MovableObject* can_obj = node->getAttachedObject(i);
if(can_obj->getMovableType() != "OgreOde::Body") obj = can_obj;
}
// Delete the node
_mgr->getRootSceneNode()->removeAndDestroyChild(node->getName());
// If we found a particle system then delete it
if(obj) ParticleSystemManager::getSingleton().destroySystem(obj->getName());
}
}
}
protected:
// Things we'll control and delete manually
Entity *_apache_body,*_main_rotor,*_tail_rotor;
SceneNode *_apache_body_node,*_main_rotor_node,*_tail_rotor_node;
Real _rotate_scale;
// Physical things we'll need to apply forces to and delete manually
OgreOde::Body *_apache,*_rear_wheel,*_left_front,*_right_front;
OgreOde::SimpleSpace* _apache_space;
bool _apply_damping;
// The worst helicopter flight model in the world!
Real _main_spd,_main_response,_main_scale,_main_min,_main_max;
Real _tail_spd,_tail_response,_tail_scale,_tail_min,_tail_max;
Real _thrust,_linear_damp,_angular_damp;
Vector3 _thrust_offs,_thrust_force;
// Stuff to help us shoot things
Real _fire_rate,_fire_time,_fire_force,_fire_mass,_fire_size;
std::map<OgreOde::SphereGeometry*,Real> _rocket_list;
int _rockets;
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -