unsigned int Forest::onCollideJumper(unsigned int id, Matrix4f* matrix, void* data) { Forest* __this = reinterpret_cast<Forest*>( data ); // determine obb of instance NxBox instanceOBB = calculateOBB( __this->_canopyBatch->getBatchScheme()->lodGeometry[0], *matrix, __this->_desc.collScale ); __this->_debugBoxes.push_back( instanceOBB ); // collide obbs if( NxBoxBoxIntersect( instanceOBB, __this->_jumperOBB ) ) { Jumper* jumper = dynamic_cast<Jumper*>( __this->_currentJumper ); // add impulse to jumper body NxVec3 linearVelocity = __this->_currentJumperActor->getLinearVelocity(); NxVec3 impulse = linearVelocity * getCore()->getRandToolkit()->getUniform( __this->_desc.minImpulseFactor, __this->_desc.maxImpulseFactor ) * -1; NxVec3 localPos( __this->_jumperOBB.extents.x * getCore()->getRandToolkit()->getUniform( -1, 1 ), __this->_jumperOBB.extents.y * getCore()->getRandToolkit()->getUniform( -1, 1 ), __this->_jumperOBB.extents.z * getCore()->getRandToolkit()->getUniform( -1, 1 ) ); __this->_currentJumperActor->addForceAtLocalPos( impulse, localPos, NX_IMPULSE ); // damage jumper jumper->damage( __this->_desc.damageFactor * impulse.magnitude(), 0.0f, linearVelocity.magnitude() ); // play rustle sound __this->playRustleSound( __this->_currentJumperCollision->getFrame()->getPos() ); } return id; }
/** * \brief Notifies this state that the hero is activating a jumper. * \param jumper The jumper activated. */ void Hero::RunningState::notify_jumper_activated(Jumper& jumper) { // Jump immediately. get_hero().start_jumping( jumper.get_direction(), jumper.get_jump_length(), true, true, 0); }
/** * \brief Returns whether a jumper is considered as an obstacle in this state. * \param jumper a jumper * \return true if the sensor is an obstacle in this state */ bool Hero::State::is_jumper_obstacle(Jumper& jumper) { if (hero.overlaps(jumper)) { // The hero may overlap the jumper if he arrived by another direction // and thus did not activate it. // This is allowed and can be used to leave water pools for example. return false; } if (!can_take_jumper()) { // If jumpers cannot be used in this state, consider them as obstacles. return true; } // At this point, we know that the jumper can be activated. if (jumper.is_in_jump_position(hero)) { // If the hero is correctly placed (ready to jump), make the jumper // obstacle so that the player has to move in the jumper's direction // during a small delay before jumping. // This also prevents the hero to be partially inside the jumper when // starting the jump. return true; } // But if the hero is not placed correctly, make the jumper traversable so // that the smooth movement can slide to it. return false; }
/** * \copydoc MapEntity::is_jumper_obstacle */ bool CustomEntity::is_jumper_obstacle(Jumper& jumper, const Rectangle& candidate_position) { const TraversableInfo& info = get_can_traverse_entity_info(jumper.get_type()); if (!info.is_empty()) { return !info.is_traversable(*this, jumper); } return Detector::is_jumper_obstacle(jumper, candidate_position); }
/** * \brief Returns whether a jumper is considered as an obstacle in this state * for the hero at the specified position. * \param jumper A jumper. * \param candidate_position Position of the hero to test. * \return \c true if the jumper is an obstacle in this state with this * hero position. */ bool Hero::BaseState::is_jumper_obstacle( const Jumper& jumper, const Rectangle& candidate_position) const { const Hero& hero = get_entity(); if (jumper.overlaps_jumping_region(hero.get_bounding_box(), false)) { // The hero already overlaps the active part of the jumper. // This is authorized if he arrived from another direction // and thus did not activate it. // This can be used to leave water pools for example. return false; } if (!jumper.overlaps_jumping_region(candidate_position, false)) { // The candidate position is in the inactive region: always accept that. return false; } if (!can_take_jumper()) { // If jumpers cannot be used in this state, consider their active region // as obstacles and their inactive region as traversable. // The active region should be an obstacle. return true; } // At this point, we know that the jumper can be activated. const bool hero_in_jump_position = jumper.is_in_jump_position(hero, hero.get_bounding_box(), false); const bool candidate_in_jump_position = jumper.is_in_jump_position(hero, candidate_position, false); if (candidate_in_jump_position) { // Wants to move to a valid jump position: accept. return false; } if (hero_in_jump_position) { // If the hero is already correctly placed (ready to jump), // make the jumper obstacle so that the player has to move in the // jumper's direction during a small delay before jumping. // This also prevents the hero to get inside the jumper's active region. return true; } const bool candidate_in_extended_jump_position = jumper.is_in_jump_position(hero, candidate_position, true); if (candidate_in_extended_jump_position) { // Wants to get inside the active region from an end of the jumper: // don't accept this. return true; } if (!jumper.is_jump_diagonal() && hero.is_moving_towards(jumper.get_direction() / 2)) { // Special case: make the jumper traversable so // that the smooth movement can slide to it. return false; } if (!jumper.is_jump_diagonal() && get_name() == "swimming" && // TODO use inheritance instead hero.is_moving_towards(((jumper.get_direction() / 2) + 2) % 4) ) { // Other special case: trying to enter the jumper the reverse way while // swimming: we accept this to allow the hero to leave water pools. // TODO I'm not sure this behavior is really a good idea. // This may change in a future version. return false; } return true; }
void Mission::FollowCamera::onUpdateActivity(float dt) { assert( _scene ); _cameraFOV = 80.0f; _positionModeTimeout -= dt; _positionModeTimeout = _positionModeTimeout < 0 ? 0 : _positionModeTimeout; // retrieve action channels ActionChannel* headLeft = Gameplay::iGameplay->getActionChannel( iaHeadLeft ); ActionChannel* headRight = Gameplay::iGameplay->getActionChannel( iaHeadRight ); ActionChannel* headUp = Gameplay::iGameplay->getActionChannel( iaHeadUp ); ActionChannel* headDown = Gameplay::iGameplay->getActionChannel( iaHeadDown ); ActionChannel* zoomIn = Gameplay::iGameplay->getActionChannel( iaZoomIn ); ActionChannel* zoomOut = Gameplay::iGameplay->getActionChannel( iaZoomOut ); switch (_mode) { case FeetLeft: { // target position Matrix4f targetPose( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); if( _target ) targetPose = _target->getPose(); Vector3f targetPos( targetPose[3][0], targetPose[3][1], targetPose[3][2] ); Vector3f targetUp( targetPose[1][0], targetPose[1][1], targetPose[1][2] ); Vector3f targetRight( targetPose[0][0], targetPose[0][1], targetPose[0][2] ); Vector3f targetFront( targetPose[2][0], targetPose[2][1], targetPose[2][2] ); targetUp.normalize(); targetRight.normalize(); targetFront.normalize(); Vector3f cameraPos(targetPos); if( dynamic_cast<Jumper*>( _target ) ) { Jumper* j = dynamic_cast<Jumper*>( _target ); j->getClump()->getFrame()->getLTM(); engine::IFrame* backBone = Jumper::getBackBone( j->getClump() ); targetPos = backBone->getPos(); engine::IFrame* legBone = Jumper::getLeftSmokeJetAnchor(j->getClump()); cameraPos = legBone->getPos(); cameraPos += legBone->getAt() * 0.0f; // right cameraPos += legBone->getUp() * -10.0f; // up cameraPos += legBone->getRight() * -20.0f; // forward targetPos = cameraPos; targetPos += legBone->getAt() * -25.0f; // right targetPos += legBone->getRight() * 40.0f; // forward targetPos += legBone->getUp() * -25.0f; // up targetUp = legBone->getUp() * -8.0f + legBone->getAt() * -2.0f; targetUp.normalize(); } //cameraPos += targetUp * 45.0f - targetRight * 40.0f - targetFront * 100.0f; // camera direction Vector3f cameraAt = cameraPos - targetPos/* + targetFront * 50.0f*/; cameraAt.normalize(); // camera right Vector3f cameraRight; cameraRight.cross( targetUp, cameraAt ); cameraRight.normalize(); // camera up Vector3f cameraUp; cameraUp.cross( cameraAt, cameraRight ); cameraUp.normalize(); // camera matrix _cameraMatrix.set( cameraRight[0], cameraRight[1], cameraRight[2], 0.0f, cameraUp[0], cameraUp[1], cameraUp[2], 0.0f, cameraAt[0], cameraAt[1], cameraAt[2], 0.0f, cameraPos[0], cameraPos[1], cameraPos[2], 1.0f ); break; } case FeetRight: { // target position Matrix4f targetPose( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); if( _target ) targetPose = _target->getPose(); Vector3f targetPos( targetPose[3][0], targetPose[3][1], targetPose[3][2] ); Vector3f targetUp( targetPose[1][0], targetPose[1][1], targetPose[1][2] ); Vector3f targetRight( targetPose[0][0], targetPose[0][1], targetPose[0][2] ); Vector3f targetFront( targetPose[2][0], targetPose[2][1], targetPose[2][2] ); targetUp.normalize(); targetRight.normalize(); targetFront.normalize(); Vector3f cameraPos(targetPos); if( dynamic_cast<Jumper*>( _target ) ) { Jumper* j = dynamic_cast<Jumper*>( _target ); j->getClump()->getFrame()->getLTM(); engine::IFrame* backBone = Jumper::getBackBone( j->getClump() ); targetPos = backBone->getPos(); engine::IFrame* legBone = Jumper::getRightSmokeJetAnchor(j->getClump()); cameraPos = legBone->getPos(); cameraPos += legBone->getAt() * 0.0f; // right cameraPos += legBone->getUp() * -12.0f; // up cameraPos += legBone->getRight() * -20.0f; // forward targetPos = cameraPos; targetPos += legBone->getAt() * -25.0f; // right targetPos += legBone->getRight() * 40.0f; // forward targetPos += legBone->getUp() * -25.0f; // up targetUp = legBone->getUp() * -8.0f + legBone->getAt() * -2.0f; targetUp.normalize(); } //cameraPos += targetUp * 45.0f - targetRight * 40.0f - targetFront * 100.0f; // camera direction Vector3f cameraAt = cameraPos - targetPos/* + targetFront * 50.0f*/; cameraAt.normalize(); // camera right Vector3f cameraRight; cameraRight.cross( targetUp, cameraAt ); cameraRight.normalize(); // camera up Vector3f cameraUp; cameraUp.cross( cameraAt, cameraRight ); cameraUp.normalize(); // camera matrix _cameraMatrix.set( cameraRight[0], cameraRight[1], cameraRight[2], 0.0f, cameraUp[0], cameraUp[1], cameraUp[2], 0.0f, cameraAt[0], cameraAt[1], cameraAt[2], 0.0f, cameraPos[0], cameraPos[1], cameraPos[2], 1.0f ); break; } case Back: { // target position Matrix4f targetPose( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); if( _target ) targetPose = _target->getPose(); Vector3f targetPos( targetPose[3][0], targetPose[3][1], targetPose[3][2] ); Vector3f targetUp( targetPose[1][0], targetPose[1][1], targetPose[1][2] ); Vector3f targetRight( targetPose[0][0], targetPose[0][1], targetPose[0][2] ); Vector3f targetFront( targetPose[2][0], targetPose[2][1], targetPose[2][2] ); targetUp.normalize(); targetRight.normalize(); targetFront.normalize(); Vector3f cameraPos(targetPos); if( dynamic_cast<Jumper*>( _target ) ) { Jumper* j = dynamic_cast<Jumper*>( _target ); j->getClump()->getFrame()->getLTM(); engine::IFrame* backBone = Jumper::getBackBone( j->getClump() ); targetPos = backBone->getPos(); engine::IFrame* head = Jumper::getHelmetEquipAnchor(j->getClump()); cameraPos = head->getPos(); cameraPos += head->getAt() * -28.0f; // down cameraPos += head->getRight() * 0.0f; // left cameraPos += head->getUp() * -1.0f; // forward targetPos = cameraPos; targetPos += head->getAt() * -10.0f; // down targetPos += head->getRight() * 0.0f; // left targetPos += head->getUp() * -10.0f; // forward targetUp = head->getAt() * -1.0f; targetUp.normalize(); } //cameraPos += targetUp * 45.0f - targetRight * 40.0f - targetFront * 100.0f; // camera direction Vector3f cameraAt = cameraPos - targetPos/* + targetFront * 50.0f*/; cameraAt.normalize(); // camera right Vector3f cameraRight; cameraRight.cross( targetUp, cameraAt ); cameraRight.normalize(); // camera up Vector3f cameraUp; cameraUp.cross( cameraAt, cameraRight ); cameraUp.normalize(); // camera matrix _cameraMatrix.set( cameraRight[0], cameraRight[1], cameraRight[2], 0.0f, cameraUp[0], cameraUp[1], cameraUp[2], 0.0f, cameraAt[0], cameraAt[1], cameraAt[2], 0.0f, cameraPos[0], cameraPos[1], cameraPos[2], 1.0f ); break; } } // camera is actual now Gameplay::iEngine->getDefaultCamera()->setFOV( _cameraFOV ); Gameplay::iEngine->getDefaultCamera()->getFrame()->setMatrix( _cameraMatrix ); _scene->getScenery()->happen( this, EVENT_CAMERA_IS_ACTUAL ); if( _scene->getTopMode() ) _scene->getTopMode()->happen( this, EVENT_CAMERA_IS_ACTUAL ); // RT-RS pass bool flares = ( _scene->getLocation()->getWeather() == ::wtSunny ) || ( _scene->getLocation()->getWeather() == ::wtVariable ); Gameplay::iGameplay->getRenderTarget()->render( _scene, _cameraMatrix, _cameraFOV, flares, false ); // GUI Gameplay::iEngine->getDefaultCamera()->beginScene( 0, Vector4f( 0,0,0,0 ) ); if( _scene->isHUDEnabled() ) Gameplay::iGui->render(); Gameplay::iEngine->getDefaultCamera()->endScene(); // present result Gameplay::iEngine->present(); }
void Mission::ThirdPersonCamera::onUpdateActivity(float dt) { assert( _scene ); _positionModeTimeout -= dt; _positionModeTimeout = _positionModeTimeout < 0 ? 0 : _positionModeTimeout; // retrieve action channels ActionChannel* headLeft = Gameplay::iGameplay->getActionChannel( iaHeadLeft ); ActionChannel* headRight = Gameplay::iGameplay->getActionChannel( iaHeadRight ); ActionChannel* headUp = Gameplay::iGameplay->getActionChannel( iaHeadUp ); ActionChannel* headDown = Gameplay::iGameplay->getActionChannel( iaHeadDown ); ActionChannel* zoomIn = Gameplay::iGameplay->getActionChannel( iaZoomIn ); ActionChannel* zoomOut = Gameplay::iGameplay->getActionChannel( iaZoomOut ); if( _positionMode ) { // field of view _cameraFOV = ( 60.0f - 55.0f * ( zoomIn->getAmplitude() ) ) * CAMERA_FOV_MULTIPLIER; // target position Matrix4f targetPose( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); if( _target ) targetPose = _target->getPose(); Vector3f targetPos( targetPose[3][0], targetPose[3][1], targetPose[3][2] ); if( dynamic_cast<Jumper*>( _target ) ) { Jumper* j = dynamic_cast<Jumper*>( _target ); j->getClump()->getFrame()->getLTM(); engine::IFrame* backBone = Jumper::getBackBone( j->getClump() ); targetPos = backBone->getPos(); } // camera direction Vector3f cameraAt = _cameraPos - targetPos; cameraAt.normalize(); // camera right Vector3f cameraRight; cameraRight.cross( Vector3f(0,1,0), cameraAt ); cameraRight.normalize(); // camera up Vector3f cameraUp; cameraUp.cross( cameraAt, cameraRight ); cameraUp.normalize(); // camera matrix _cameraMatrix.set( cameraRight[0], cameraRight[1], cameraRight[2], 0.0f, cameraUp[0], cameraUp[1], cameraUp[2], 0.0f, cameraAt[0], cameraAt[1], cameraAt[2], 0.0f, _cameraPos[0], _cameraPos[1], _cameraPos[2], 1.0f ); } else { // camera offset _cameraDistance -= dt * 500.0f * zoomIn->getAmplitude(); _cameraDistance += dt * 500.0f * zoomOut->getAmplitude(); if( _cameraDistance < TPSM_MINIMAL_DISTANCE ) _cameraDistance = TPSM_MINIMAL_DISTANCE; // rotate camera _cameraTurn += 180 * dt * headLeft->getAmplitude(); _cameraTurn -= 180 * dt * headRight->getAmplitude(); _cameraTilt += 180 * dt * headUp->getAmplitude(); _cameraTilt -= 180 * dt * headDown->getAmplitude(); if( _cameraTilt < -89 ) _cameraTilt = -89; if( _cameraTilt > 89 ) _cameraTilt = 89; Matrix4f targetPose( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); if( _target ) targetPose = _target->getPose(); Vector3f targetPos( targetPose[3][0], targetPose[3][1], targetPose[3][2] ); Vector3f targetOffset( 0,150,0 ); if( dynamic_cast<Jumper*>( _target ) ) { Jumper* j = dynamic_cast<Jumper*>( _target ); j->getClump()->getFrame()->getLTM(); engine::IFrame* backBone = Jumper::getBackBone( j->getClump() ); targetPos = backBone->getPos(); targetOffset.set( 0,75, 0 ); } // calculate camera matrix _cameraMatrix.set( 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 ); _cameraMatrix = Gameplay::iEngine->rotateMatrix( _cameraMatrix, Vector3f( 1,0,0 ), _cameraTilt ); _cameraMatrix = Gameplay::iEngine->rotateMatrix( _cameraMatrix, Vector3f( 0,1,0 ), _cameraTurn ); Vector3f at( _cameraMatrix[2][0], _cameraMatrix[2][1], _cameraMatrix[2][2] ); // possible camera position Vector3f cameraPos = targetPos + targetOffset + at * _cameraDistance; // clip camera distance float clipDistance = _cameraDistance; if( _scene->clipCameraRay( targetPos, cameraPos, clipDistance ) ) { _cameraDistance = clipDistance; cameraPos = targetPos + targetOffset + at * _cameraDistance; } // finalize camera matrix (translation component) _cameraMatrix = Gameplay::iEngine->translateMatrix( _cameraMatrix, cameraPos ); } // camera is actual now Gameplay::iEngine->getDefaultCamera()->setFOV( _cameraFOV ); Gameplay::iEngine->getDefaultCamera()->getFrame()->setMatrix( _cameraMatrix ); _scene->getScenery()->happen( this, EVENT_CAMERA_IS_ACTUAL ); if( _scene->getTopMode() ) _scene->getTopMode()->happen( this, EVENT_CAMERA_IS_ACTUAL ); // RT-RS pass bool flares = ( _scene->getLocation()->getWeather() == ::wtSunny ) || ( _scene->getLocation()->getWeather() == ::wtVariable ); Gameplay::iGameplay->getRenderTarget()->render( _scene, _cameraMatrix, _cameraFOV, flares, false ); // GUI Gameplay::iEngine->getDefaultCamera()->beginScene( 0, Vector4f( 0,0,0,0 ) ); if( _scene->isHUDEnabled() ) Gameplay::iGui->render(); Gameplay::iEngine->getDefaultCamera()->endScene(); // present result Gameplay::iEngine->present(); }
void Forest::simulateInteraction(Actor* actor) { _debugBoxes.clear(); _currentJumper = actor; Jumper* jumper = dynamic_cast<Jumper*>( actor ); if( !jumper ) return; CanopySimulator* canopy = jumper->getDominantCanopy(); _currentCanopy = canopy; _currentCanopyInfo = canopy->getGearRecord(); _jumperCanopyIsOpened = canopy->isOpened(); if( _jumperCanopyIsOpened ) { _currentCanopyCollision = CanopySimulator::getCollisionGeometry( canopy->getClump() ); _currentCanopyActor = canopy->getNxActor(); } else { _currentCanopyCollision = NULL; _currentCanopyActor = NULL; } // obtain collision atomic _currentJumperCollision = NULL; _currentJumperActor = NULL; switch( jumper->getPhase() ) { case ::jpFreeFalling: _currentJumperActor = jumper->getFreefallActor(); _currentJumperCollision = Jumper::getCollisionFF( jumper->getClump() ); assert( _currentJumperCollision ); break; case ::jpFlight: if( _jumperCanopyIsOpened ) { _currentJumperActor = jumper->getFlightActor(); _currentJumperCollision = Jumper::getCollisionFC( jumper->getClump() ); } else { _currentJumperActor = jumper->getFreefallActor(); _currentJumperCollision = Jumper::getCollisionFF( jumper->getClump() ); } assert( _currentJumperCollision ); break; } if( _currentJumperCollision ) { // collide jumper with forest _jumperOBB = calculateOBB( _currentJumperCollision->getGeometry(), _currentJumperCollision->getFrame()->getLTM(), 1.0f ); _jumperOBB.center = _currentJumperActor->getGlobalPosition(); _debugBoxes.push_back( _jumperOBB ); float testBoxSize = 250; Vector3f jumperPos = wrap( _jumperOBB.center ); _canopyBatch->forAllInstancesInAABB( jumperPos - Vector3f( testBoxSize,testBoxSize,testBoxSize ), jumperPos + Vector3f( testBoxSize,testBoxSize,testBoxSize ), onCollideJumper, this ); } if( _currentCanopyCollision && !canopy->isCohesionState() ) { _canopyOBB = calculateOBB( _currentCanopyCollision->getGeometry(), _currentCanopyCollision->getFrame()->getLTM(), 1.0f ); _canopyOBB.center = _currentCanopyActor->getGlobalPosition(); _debugBoxes.push_back( _canopyOBB ); float testBoxSize = 750; Vector3f canopyPos = wrap( _canopyOBB.center ); _canopyBatch->forAllInstancesInAABB( canopyPos - Vector3f( testBoxSize,testBoxSize,testBoxSize ), canopyPos + Vector3f( testBoxSize,testBoxSize,testBoxSize ), onCollideCanopy, this ); } _currentJumper = NULL; _currentJumperCollision = NULL; _currentJumperActor = NULL; _jumperCanopyIsOpened = false; _currentCanopyCollision = NULL; _currentCanopyActor = NULL; }