예제 #1
0
파일: HUDBase.cpp 프로젝트: apoddubn/cprakt
void HUDBase::getRelativePositions(list<Vertex<float> > &above, list<Vertex<float> > &below)
{
    // Reset the vectors
    above.clear();
    below.clear();

    set<PhysicalObject*>::iterator it;
    m_mutex.lock();
    for(it = m_destroyables.begin(); it != m_destroyables.end(); it++)
    {
        // Calculate the mapping of the difference vector:
        PhysicalObject* obj = *it;
        Vertex<float> diff = obj->getPosition() - m_fighter->getPosition();

        // Project onto current flight axis
        float x = diff * m_fighter->getXAxis();
        float y = diff * m_fighter->getYAxis();
        float z = diff * m_fighter->getZAxis();

        // Create new relative position
        Vertex<float> rel(x,y,z);

        //And add to the relative positions
        if(z<0)
        {
            below.push_back(rel);
        }
        else
        {
            above.push_back(rel);
        }
    }
    m_mutex.unlock();
}
PhysicalObject* PhysicsSim::applyPhysics(SceneObject* object, Shape shape, float mass)
{
	PhysicalObject* phyObject;
	switch(shape)
	{
		case shSphere: phyObject = new Sphere(object, mass);
					break;

		case shBox: phyObject = new Box(object, mass);
					break;

		case shCapsule: phyObject = new Capsule(object, mass);
					break;

		case shCylinder: phyObject = new Cylinder(object, mass);
					break;

		case shCone: phyObject = new Cone(object, mass);
					break;

		case shConvexHull: phyObject = new ConvexHull(object, mass);
					break;

		case shTriMesh: phyObject = new TriMesh(object, mass);
					break;
	}

	objects_list.push_back(phyObject);
	dynamicsWorld->addRigidBody(phyObject->getRigidBody());

	updateObjects();

	return phyObject;
}
예제 #3
0
/** Update the world and the track.
 *  \param dt Time step size. 
 */
void ThreeStrikesBattle::update(float dt)
{
    WorldWithRank::update(dt);
    WorldWithRank::updateTrack(dt);
    
    core::vector3df tire_offset;
    std::string tire;
    float scale = 0.5f;
    float radius = 0.5f;
    PhysicalObject::bodyTypes tire_model;

    // insert blown away tire(s) now if was requested
    while (m_insert_tire > 0)
    {        
        if(m_insert_tire == 1)
        {
            tire_offset = core::vector3df(0.0f, 0.0f, 0.0f);
            tire = file_manager->getModelFile("tire.b3d");
            scale = 0.5f;
            radius = 0.5f;
            tire_model = PhysicalObject::MP_CYLINDER_Y;
        }
        else
        {
            scale = 1.0f;
            tire_model = PhysicalObject::MP_CYLINDER_X;
            radius = m_tire_radius[m_insert_tire-2];
            tire_offset = m_tire_offsets[m_insert_tire-2];
            if     (m_insert_tire == 2)
                tire = m_tire_dir+"/wheel-rear-left.b3d";
            else if(m_insert_tire == 3)
                tire = m_tire_dir+"/wheel-front-left.b3d";
            else if(m_insert_tire == 4)
                tire = m_tire_dir+"/wheel-front-right.b3d";
            else if(m_insert_tire == 5)
                tire = m_tire_dir+"/wheel-rear-right.b3d";
        }

        TrackObjectManager* tom = m_track->getTrackObjectManager();        
        PhysicalObject* obj = 
            tom->insertObject(tire,
                              tire_model,
                              15 /* mass */,
                              radius /* radius */,
                              core::vector3df(800.0f,0,m_tire_rotation 
                                                      / M_PI * 180 + 180) ,
                              m_tire_position + tire_offset,
                              core::vector3df(scale,scale,scale) /* scale */);
        
        // FIXME: orient the force relative to kart orientation
        obj->getBody()->applyCentralForce(btVector3(60.0f, 0.0f, 0.0f));

        m_insert_tire--;
        if(m_insert_tire == 1)
            m_insert_tire = 0;
        
        m_tires.push_back(obj);
    }
}   // update
예제 #4
0
    void Laser::fire()
    {
      InternalMessage("Model","entering fire") ;

      // handle firing rate
      if (m_time_to_fire.Second() > 0)
        return ;

      Positioned* positioned = getObject()->getParent<Positioned>() ;
      Oriented* oriented = getObject()->getParent<Oriented>() ;
      PhysicalObject* object = getObject()->getParent<PhysicalObject>() ;
      PhysicalWorld* world = object ? object->getObject()->getAncestor<PhysicalWorld>() : NULL ;

      if (world && positioned && oriented)
      {
        InternalMessage("Model","firing") ;
        // create a laser beam object
        Kernel::Object* beam = world->getObject()->createObject() ;

        // should apply local rotation to have correct local position..
        Orientation orientation_of_laser = oriented->getOrientation(world->getObject()) ;

        Position position_of_the_beam =
          positioned->getPosition(world->getObject()) + m_out_position*orientation_of_laser ;

        beam->addTrait(new Positioned(position_of_the_beam)) ;

        Orientation orientation_of_the_beam =
          orientation_of_laser*m_out_orientation ;

        beam->addTrait(new Oriented(orientation_of_the_beam)) ;

        // orientation gives speed vector
        // basic_speed(full Z oriented) * orientation
        Speed speed = Speed::MeterPerSecond(0,0,-getLaserSpeedMeterPerSecond())*orientation_of_the_beam ;

        // maybe we should add the object speed ?? (i.e. the speed of the ship)

        beam->addTrait(new Mobile(speed)) ;
        beam->addTrait(new Massive(Mass(m_laser_beam_energy,speed))) ;

        beam->addTrait(new LaserBeam(object->getObject(),m_beam_length,m_beam_radius)) ;
        beam->addTrait(new WithLifetime(getLaserBeamLifeDuration())) ;

        // shot
        Kernel::Object* shot = world->getObject()->createObject() ;
        shot->addTrait(new Positioned(position_of_the_beam)) ;
        shot->addTrait(new Shot()) ;

        // re-init timer
        m_time_to_fire = m_time_between_shots ;
        // done

      }
      // else : not much sense thus do nothing
      InternalMessage("Model","leaving fire") ;
    }
예제 #5
0
		void PhysicalGroup::Render(float minX, float minY, float maxX, float maxY)
		{
			if(m_physicsHandler)
				m_physicsHandler->Render(minX, minY, maxX, maxY);
			else //- TODO: Determine if this is necessary -
			{
				for(vector<Group::Member *>::iterator it = m_members.begin(); it != m_members.end(); it++)
				{
					PhysicalObject *object = (PhysicalObject *)*it;
					object->Render();
				}
			}
		}
void PhysicsSim::shootTestSphere()
{
	removeObject(testSphere);

	testSphere = loadSceneObject("lemon.dae");
	testSphere->setPosition(fpscam->getPosition());
	testSphere->setScale(Vector3D(2,2,2));
	PhysicalObject* phyObj = applyPhysics(testSphere, shSphere, 20);

	vector3df dir = fpscam->getTarget() - fpscam->getPosition();
	dir = 250*dir.normalize();
	phyObj->getRigidBody()->applyCentralImpulse(btVector3(dir.X, dir.Y, dir.Z));

}
예제 #7
0
    const SUCCESS PhysicalObject::collided(PhysicalObject &object, const Radians angle)
    {
        Vector initVec(getVelocity()-object.getVelocity());
        Mag_t<double> initVel(initVec.mag());
        Radians initTheta(initVec.theta());
        
		if(fabs(getX(initVel, initTheta-angle)) < REST_THRESHOLD)
        {
			setVelocity(getVelocity()+initVec/2.0);
			object.setVelocity(object.getVelocity()-initVec/2.0);
            antigravitate(object);
            object.antigravitate(*this);
			return SUCCEEDED;
		}
		
        // Frame of reference with the object at rest with this approaching it with an angle of 0
        Point<double> p2(Vector(Mag_t<double>(2.0*getMass()*getX(initVel, initTheta-angle)/(getMass()+object.getMass())), initTheta-angle));  // Gets the velocity of 2 based on elastic collision equation
        Point<double> p1((initVel*getMass()-p2.x()*object.getMass())/getMass(), -p2.y()*object.getMass()/getMass());   // Gets the velocity of 1 based off of elastic collision rulez
        
        if(fabs(p1.x()) < REST_THRESHOLD && fabs(p2.x()) < REST_THRESHOLD)
        {
            p1.x(0.0);
            p2.x(0.0);
        }
        
        Vector v1(p1);
        Vector v2(p2);
        
        v1.theta(-v1.theta()+initTheta);
        v2.theta(angle);
        
        v1 += object.getVelocity();
        v2 += object.getVelocity();
        
        Point<double> dif(object.getPosition()-*position);
        while(getCollider()->collides(*object.getCollider()))
            acceleration.set(*position-dif/pythagoras<double>(dif));
        
        setVelocity(v1);
        object.setVelocity(v2);
        
        return SUCCEEDED;
    }
예제 #8
0
 const SUCCESS StaticObject::checkCollision(PhysicalObject &object)
 {
     if(getCollider() == NULL || object.getCollider() == NULL)
     {
         return SUCCEEDED;
     }
     else
     {
         Radians angle;
         if(getCollider()->canCollide(object.getCollider()->getType()))
             if(getCollider()->collides(*object.getCollider(), &angle))
                 return collided(object, angle);   // this ensures that object collider is called by this collided function, likewise a derived class needs to make sure its own derived collided function is called
             else
                  return SUCCEEDED;
         else if(object.getCollider()->canCollide(getCollider()->getType()))
             if(object.getCollider()->collides(*getCollider(), &angle))
                  return collided(object, angle);
             else
                  return SUCCEEDED;
         else
              return FAILED;
     }
 }
예제 #9
0
 const SUCCESS StaticObject::collided(PhysicalObject &object, const Radians angle)
 {
     Vector v(object.getVelocity());
     v.theta() -= angle;
     Point<double> appliedMomentum(v);
     if(fabs(appliedMomentum.x()) < REST_THRESHOLD)
     {
         appliedMomentum.x(0);
     }
     appliedMomentum.x() *= -1;
     v = appliedMomentum;
     v.theta() += angle;
     object.setVelocity(v);
     
     Point<double> dif(getPosition()-object.getPosition());
     while(getCollider()->collides(*object.getCollider()))
         object.setPosition(object.getPosition()-dif/pythagoras<double>(dif));
     
     return SUCCEEDED;
 }
예제 #10
0
void HumanMovementPlugin::Refresh(const float &fDeltaTime)
{
    if (m_vControlledObjects.size() > 0)
    {
        int			dwAlphaInput			= gInput()->GetKeyboardAlphaFlags();

        VECTOR3 vVelocity;

        if (dwAlphaInput & INPUT_CHAR_W)
        {
            vVelocity.y				+= 1.0f;
        }

        if (dwAlphaInput & INPUT_CHAR_S)
        {
            vVelocity.y				-= 1.0f;
        }

        if (dwAlphaInput & INPUT_CHAR_D)
        {
            vVelocity.x				+= 1.0f;
        }

        if (dwAlphaInput & INPUT_CHAR_A)
        {
            vVelocity.x				-= 1.0f;
        }

        float	fMagnitudeSquared	= MagnitudeSquaredVECTOR3(vVelocity);
        bool	bNoChange			= false;

        if (fMagnitudeSquared > 0.0f)
        {
            NormalizeVECTOR3(vVelocity);

            vVelocity.x		*= m_fSpeed;
            vVelocity.y		*= m_fSpeed;
            vVelocity.z		*= m_fSpeed;
        }
        else if (fMagnitudeSquared == 0.0f)
        {
            bNoChange		= true;
        }

        vector<PhysicalObject *>::iterator			iter;
        PhysicalObject								*pPhysObject			= 0;
        for (iter = m_vControlledObjects.begin(); iter != m_vControlledObjects.end(); iter++)
        {
            pPhysObject = *iter;
            if (pPhysObject)
            {
                if (bNoChange)
                {
                    vVelocity.x *= 0.0f;
                    vVelocity.y *= 0.0f;
                    vVelocity.z *= 0.0f;
                }

                pPhysObject->SetVelocity(vVelocity);
            }
        }
    }
}
예제 #11
0
void MapMode::_UpdateExplore()
{
    // First go to menu mode if the user requested it
    if(_menu_enabled && InputManager->MenuPress()) {
        MenuMode *MM = new MenuMode();
        ModeManager->Push(MM);
        return;
    }

    // Only update the status effect supervisor in Exploration mode
    // and if they are allowed.
    if (_status_effects_enabled)
        _status_effect_supervisor.UpdateEffects();

    // Update the running state of the camera object. Check if the character is running and if so,
    // update the stamina value if the operation is permitted
    _camera->is_running = false;
    if(_camera->moved_position && !_running_disabled && InputManager->CancelState() &&
            (InputManager->UpState() || InputManager->DownState() || InputManager->LeftState() || InputManager->RightState())) {
        if(_unlimited_stamina) {
            _camera->is_running = true;
        } else if(_run_stamina > SystemManager->GetUpdateTime() * 2) {
            _run_stamina -= (SystemManager->GetUpdateTime() * 2);
            _camera->is_running = true;
        } else {
            _run_stamina = 0;
        }
    }
    // Regenerate the stamina at 1/2 the consumption rate
    else if(_run_stamina < 10000) {
        _run_stamina += SystemManager->GetUpdateTime();
        if(_run_stamina > 10000)
            _run_stamina = 10000;
    }

    // If the user requested a confirm event, check if there is a nearby object that the player may interact with
    // Interactions are currently limited to dialogue with sprites and opening of treasures
    if(InputManager->ConfirmPress()) {
        MapObject *obj = _object_supervisor->FindNearestInteractionObject(_camera);

        if(obj != NULL) {
            if(obj->GetType() == PHYSICAL_TYPE) {
                PhysicalObject *phs = reinterpret_cast<PhysicalObject *>(obj);

                if(!phs->GetEventIdWhenTalking().empty()) {
                    _camera->moving = false;
                    _camera->is_running = false;
                    if (!_event_supervisor->IsEventActive(phs->GetEventIdWhenTalking()))
                        _event_supervisor->StartEvent(phs->GetEventIdWhenTalking());
                    return;
                }
            }
            else if(obj->GetType() == SPRITE_TYPE) {
                MapSprite *sp = reinterpret_cast<MapSprite *>(obj);

                if(sp->HasAvailableDialogue()) {
                    _camera->moving = false;
                    _camera->is_running = false;
                    sp->InitiateDialogue();
                    return;
                }
            } else if(obj->GetType() == TREASURE_TYPE) {
                TreasureObject *treasure_object = reinterpret_cast<TreasureObject *>(obj);

                if(!treasure_object->GetTreasure()->IsTaken()) {
                    _camera->moving = false;
                    treasure_object->Open();
                }
            } else if(obj->GetType() == SAVE_TYPE && _save_points_enabled) {
                // Make sure the character will be centered in the save point
                SaveMode *save_mode = new SaveMode(true, obj->GetXPosition(), obj->GetYPosition() - 1.0f);
                ModeManager->Push(save_mode, false, false);
            }
        }
    }

    // Detect movement input from the user
    if(InputManager->UpState() || InputManager->DownState() || InputManager->LeftState() || InputManager->RightState()) {
        _camera->moving = true;
    } else {
        _camera->moving = false;
    }

    // Determine the direction of movement. Priority of movement is given to: up, down, left, right.
    // In the case of diagonal movement, the direction that the sprite should face also needs to be deduced.
    if(_camera->moving == true) {
        if(InputManager->UpState()) {
            if(InputManager->LeftState())
                _camera->SetDirection(MOVING_NORTHWEST);
            else if(InputManager->RightState())
                _camera->SetDirection(MOVING_NORTHEAST);
            else
                _camera->SetDirection(NORTH);
        } else if(InputManager->DownState()) {
            if(InputManager->LeftState())
                _camera->SetDirection(MOVING_SOUTHWEST);
            else if(InputManager->RightState())
                _camera->SetDirection(MOVING_SOUTHEAST);
            else
                _camera->SetDirection(SOUTH);
        } else if(InputManager->LeftState()) {
            _camera->SetDirection(WEST);
        } else if(InputManager->RightState()) {
            _camera->SetDirection(EAST);
        }
    } // if (_camera->moving == true)
} // void MapMode::_UpdateExplore()
예제 #12
0
/** Updates the physics simulation and handles all collisions.
 *  \param dt Time step.
 */
void Physics::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Maximum of three substeps. This will work for framerate down to
    // 20 FPS (bullet default frequency is 60 HZ).
    m_dynamics_world->stepSimulation(dt, 3);

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            PhysicalObject *obj = p->getUserPointer(0)
                                   ->getPointerPhysicalObject();
            if(obj->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (obj->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
            }
            else if(obj->isSoccerBall())
            {
                int kartId = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }
            continue;
        }

        if(p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            p->getUserPointer(0)->getPointerFlyable()
                ->hit(NULL, p->getUserPointer(1)->getPointerPhysicalObject());
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            if(obj->isSoccerBall())
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                p->getUserPointer(0)->getPointerFlyable()->hit(target_kart);
                if ( type ==PowerupManager::POWERUP_BOWLING )
                    ((SingleAchievement *) AchievementsManager::get()->getActive()->getAchievement(2))->increase(1);
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
예제 #13
0
void VirtualSprite::_SetNextPosition()
{

    // Next sprite's position holders
    float next_pos_x = GetXPosition();
    float next_pos_y = GetYPosition();
    float distance_moved = CalculateDistanceMoved();

    // Move the sprite the appropriate distance in the appropriate Y and X direction
    if(_direction & (NORTH | MOVING_NORTHWEST | MOVING_NORTHEAST))
        next_pos_y -= distance_moved;
    else if(_direction & (SOUTH | MOVING_SOUTHWEST | MOVING_SOUTHEAST))
        next_pos_y += distance_moved;
    if(_direction & (WEST | MOVING_NORTHWEST | MOVING_SOUTHWEST))
        next_pos_x -= distance_moved;
    else if(_direction & (EAST | MOVING_NORTHEAST | MOVING_SOUTHEAST))
        next_pos_x += distance_moved;

    // When not moving, do not check anything else.
    if(next_pos_x == GetXPosition() && next_pos_y == GetYPosition())
        return;

    // We've got the next position, let's check whether the next position
    // should be revised.

    // Used to know whether we could fall back to a straight move
    // in case of collision.
    bool moving_diagonally = (_direction & (MOVING_NORTHWEST | MOVING_NORTHEAST
                                           | MOVING_SOUTHEAST | MOVING_SOUTHWEST));

    // Handle collision with the first object encountered
    MapObject* collision_object = nullptr;
    MapMode* map_mode = MapMode::CurrentInstance();
    ObjectSupervisor* object_supervisor = map_mode->GetObjectSupervisor();
    COLLISION_TYPE collision_type = object_supervisor->DetectCollision(this, next_pos_x,
                     next_pos_y,
                     &collision_object);
    // Try to fall back to straight direction
    if(moving_diagonally && collision_type != NO_COLLISION) {
        // Try on x axis
        if(object_supervisor->DetectCollision(this, _tile_position.x, next_pos_y, &collision_object) == NO_COLLISION) {
            next_pos_x = _tile_position.x;
            collision_type = NO_COLLISION;
        } // and then on y axis
        else if(object_supervisor->DetectCollision(this, next_pos_x, _tile_position.y, &collision_object) == NO_COLLISION) {
            next_pos_y = _tile_position.y;
            collision_type = NO_COLLISION;
        }
    }

    // Handles special collision handling first
    if(_control_event) {
        switch(_control_event->GetEventType()) {
            // Don't stuck the player's character or a sprite being controlled by a prepared path.
            // Plus, it's better not to change a path with encountered beings once started
            // for simplification purpose.
        case PATH_MOVE_SPRITE_EVENT:
            collision_type = NO_COLLISION;
            break;
            // Change the direction whenever something blocking is in the way.
        case RANDOM_MOVE_SPRITE_EVENT:
            if(collision_type != NO_COLLISION) {
                SetRandomDirection();
                return;
            }
        default:
            break;
        }
    }

    // Try to handle wall and physical collisions after a failed straight or diagonal move
    switch(collision_type) {
    case NO_COLLISION:
    default:
        break;
    case WALL_COLLISION:
        // When being blocked and moving diagonally, the npc is stuck.
        if(moving_diagonally)
            return;

        // Don't consider physical objects with an event to avoid sliding on their edges,
        // making them harder to "talk with".
        if (collision_object && this == map_mode->GetCamera()) {
            PhysicalObject *phs = reinterpret_cast<PhysicalObject *>(collision_object);
            if(phs && !phs->GetEventIdWhenTalking().empty())
                return;
        }

        // Fix the direction and destination to walk-around obstacles
        if (_HandleWallEdges(next_pos_x, next_pos_y, distance_moved, collision_object))
            break;
        // We don't do any other checks for the player sprite.
        else if (this == map_mode->GetCamera())
            return;

        // NPC sprites:

        // When it's a true wall, try against the collision grid
        if(!collision_object) {
            // Try a random diagonal to avoid the wall in straight direction
            if(_direction & (NORTH | SOUTH))
                _direction |= vt_utils::RandomBoundedInteger(0, 1) ? EAST : WEST;
            else if(_direction & (EAST | WEST))
                _direction |= vt_utils::RandomBoundedInteger(0, 1) ? NORTH : SOUTH;
            return;
        }
        // Physical and treasure objects are the only other matching "fake" walls
        else {
            // Try a diagonal to avoid the sprite in straight direction by comparing
            // each one coords.
            float diff_x = GetXPosition() - collision_object->GetXPosition();
            float diff_y = GetYPosition() - collision_object->GetYPosition();
            if(_direction & (NORTH | SOUTH))
                _direction |= diff_x >= 0.0f ? EAST : WEST;
            else if(_direction & (EAST | WEST))
                _direction |= diff_y >= 0.0f ? SOUTH : NORTH;
            return;
        }
        // Other cases shouldn't happen.
        break;
    case ENEMY_COLLISION:
        // Check only whether the player has collided with a monster
        if(this == map_mode->GetCamera() &&
                collision_object && collision_object->GetObjectType() == ENEMY_TYPE) {
            EnemySprite* enemy = reinterpret_cast<EnemySprite *>(collision_object);

            // Check whether the player is actually playing. If not, we don't want to start a battle.
            if (map_mode->CurrentState() == STATE_EXPLORE)
                map_mode->StartEnemyEncounter(enemy);
            return;
        }

        break;
    case CHARACTER_COLLISION:
        // Check whether the sprite is tangled with another character, even without moving
        // For instance, when colliding with a path follower npc.
        // And let it through in that case.
        if(object_supervisor->CheckObjectCollision(GetGridCollisionRectangle(), collision_object)) {
            collision_type = NO_COLLISION;
            break;
        }

        // When the sprite is controlled by the camera, let the player handle the position correction.
        if(this == map_mode->GetCamera())
            return;

        // Check whether an enemy has collided with the player
        if(this->GetType() == ENEMY_TYPE && collision_object == map_mode->GetCamera()) {
            EnemySprite* enemy = reinterpret_cast<EnemySprite *>(this);

            // Check whether the player is actually playing. If not, we don't want to start a battle.
            if (map_mode->CurrentState() == STATE_EXPLORE)
                map_mode->StartEnemyEncounter(enemy, false, true); // The enemy gets a boost in stamina.
            return;
        }

        // When being blocked and moving diagonally, the npc is stuck.
        if(moving_diagonally)
            return;

        if(!collision_object)  // Should never happen
            return;

        // Try a diagonal to avoid the sprite in straight direction by comparing
        // each one coords.
        float diff_x = GetXPosition() - collision_object->GetXPosition();
        float diff_y = GetYPosition() - collision_object->GetYPosition();
        if(_direction & (NORTH | SOUTH))
            _direction |= diff_x >= 0.0f ? EAST : WEST;
        else if(_direction & (EAST | WEST))
            _direction |= diff_y >= 0.0f ? SOUTH : NORTH;
        return;
    }

    // Inform the overlay system of the parallax movement done if needed
    if(this == map_mode->GetCamera()) {
        float x_parallax = !map_mode->IsCameraXAxisInMapCorner() ?
                           (GetXPosition() - next_pos_x)
                               / SCREEN_GRID_X_LENGTH
                               * vt_video::VIDEO_STANDARD_RES_WIDTH :
                           0.0f;
        float y_parallax = !map_mode->IsCameraYAxisInMapCorner() ?
                           (GetYPosition() - next_pos_y)
                               / SCREEN_GRID_Y_LENGTH
                               * vt_video::VIDEO_STANDARD_RES_HEIGHT :
                           0.0f;

        map_mode->GetEffectSupervisor().AddParallax(x_parallax, y_parallax);
        map_mode->GetIndicatorSupervisor().AddParallax(x_parallax, y_parallax);
    }

    // Make the sprite advance at the end
    SetPosition(next_pos_x, next_pos_y);
    _moved_position = true;
}
예제 #14
0
/** Updates the physics simulation and handles all collisions.
 *  \param dt Time step.
 */
void Physics::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Maximum of three substeps. This will work for framerate down to
    // 20 FPS (bullet default frequency is 60 HZ).
    m_dynamics_world->stepSimulation(dt, 3);

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction("void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                PlayerController *c = dynamic_cast<PlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && c &&
                    c->getPlayer()->getConstProfile() == PlayerManager::getCurrentPlayer())
                {
                    // Compare the current value of hits with the 'hit' goal value
                    // (otherwise it would be compared with the kart id goal value,
                    // which doesn't exist.
                    PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_ARCH_ENEMY,
                                                       target_kart->getIdent(), 1, "hit");
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_STRIKE,
                                                          "ball", 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
예제 #15
0
파일: Playground.cpp 프로젝트: plsm/enki
	EnkiPlayground(World *world, QWidget *parent = 0) :
		ViewerWidget(world, parent),
		subjectiveView(false)
	{
		#define PROBLEM_GENERIC_TOY
		#define PROBLEM_BALL_LINE
		//#define PROBLEM_LONE_EPUCK
		
		#ifdef PROBLEM_GENERIC_TOY
		{
			const double amount = 9;
			const double radius = 5;
			const double height = 20;
			Polygone p;
			for (double a = 0; a < 2*M_PI; a += 2*M_PI/amount)
				p.push_back(Point(radius * cos(a), radius * sin(a)));
			
			PhysicalObject* o = new PhysicalObject;
			PhysicalObject::Hull hull(Enki::PhysicalObject::Part(p, height));
			o->setCustomHull(hull, -1);
			o->setColor(Color(0.4,0.6,0.8));
			o->pos = Point(100, 100);
			world->addObject(o);
		}
		
		for (int i = 0; i < 20; i++)
		{
			PhysicalObject* o = new PhysicalObject;
			o->pos = Point(UniformRand(20, 100)(), UniformRand(20, 100)());
			o->setCylindric(1, 1, 10);
			o->setColor(Color(0.9, 0.2, 0.2));
			o->dryFrictionCoefficient = 0.01;
			world->addObject(o);
		}
		
		Polygone p2;
		p2.push_back(Point(5,1));
		p2.push_back(Point(-5,1));
		p2.push_back(Point(-5,-1));
		p2.push_back(Point(5,-1));
		for (int i = 0; i < 5; i++)
		{
			PhysicalObject* o = new PhysicalObject;
			PhysicalObject::Hull hull(Enki::PhysicalObject::Part(p2, 3));
			o->setCustomHull(hull, 30);
			o->setColor(Color(0.2, 0.1, 0.6));
			o->collisionElasticity = 0.2;
			o->pos = Point(UniformRand(20, 100)(), UniformRand(20, 100)());
			world->addObject(o);
		}
		
		// cross shape
		{
			PhysicalObject* o = new PhysicalObject;
			PhysicalObject::Hull hull;
			hull.push_back(Enki::PhysicalObject::Part(Polygone() << Point(5,1) << Point(-5,1) << Point(-5,-1) << Point(5,-1), 2));
			hull.push_back(Enki::PhysicalObject::Part(Polygone() << Point(1,5) << Point(-1,5) << Point(-1,-5) << Point(1,-5), 4));
			o->setCustomHull(hull, 60);
			o->setColor(Color(0.2, 0.4, 0.6));
			o->collisionElasticity = 0.2;
			o->pos = Point(UniformRand(20, 100)(), UniformRand(20, 100)());
			world->addObject(o);
		}
		#endif // PROBLEM_GENERIC_TOY
		
		#ifdef PROBLEM_BALL_LINE
		for (double d = 40; d < 60; d += 8)
		{
			PhysicalObject* o = new PhysicalObject;
			o->pos = Point(d, 20);
			o->setCylindric(4, 2, 10);
			o->setColor(Color(0.2, 0.2, 0.6));
			o->dryFrictionCoefficient = 0.;
			world->addObject(o);
		}
		#endif // PROBLEM_BALL_LINE
		
		#ifdef PROBLEM_LONE_EPUCK
		addDefaultsRobots(world);
		#endif // PROBLEM_LONE_EPUCK
		
		Marxbot *marxbot = new Marxbot;
		marxbot->pos = Point(60, 50);
		marxbot->leftSpeed = 8;
		marxbot->rightSpeed = 2;
		world->addObject(marxbot);
		
		#ifdef USE_SDL
		if((SDL_Init(SDL_INIT_JOYSTICK)==-1))
		{
			cerr << "Error : Could not initialize SDL: " << SDL_GetError() << endl;
			addDefaultsRobots(world);
			return;
		}
		
		int joystickCount = SDL_NumJoysticks();
		for (int i = 0; i < joystickCount; ++i)
		{
			SDL_Joystick* joystick = SDL_JoystickOpen(i);
			if (!joystick)
			{
				cerr << "Error: Can't open joystick " << i << endl;
				continue;
			}
			if (SDL_JoystickNumAxes(joystick) < 2)
			{
				cerr << "Error: not enough axis on joystick" << i<< endl;
				SDL_JoystickClose(joystick);
				continue;
			}
			joysticks.push_back(joystick);
			
			EPuck *epuck = new EPuck;
			//epuck->pos = Point(UniformRand(20, 100)(), UniformRand(20, 100)());
			epuck->pos = Point(20, 20);
			epucks.push_back(epuck);
			world->addObject(epuck);
		}
		cout << "Added " << joystickCount << " controlled e-pucks." << endl;
		#else // USE_SDL
		addDefaultsRobots(world);
		#endif // USE_SDL
		camera.altitude = 150;
		camera.pos = QPointF(0,-60);
	}
bool PhysicsSim::loadPhysicalObjects(PhysicalStructure &structure, stringc mesh_filename, Vector3D position, bool lock2d)
{

	stringc physics_filename = mesh_filename;
	physics_filename.remove(".dae");
	physics_filename.append(".bullet");
	physics_filename = mediaDirectory + physics_filename;

	if(smgr->getFileSystem()->existFile(physics_filename))
	{
		stringw collada_filename = smgr->getFileSystem()->getAbsolutePath(mediaDirectory) + mesh_filename;

		if(smgr->getFileSystem()->existFile(collada_filename))
		{
			btBlenderImporter* fileLoader = new btBlenderImporter(position);
			fileLoader->loadFile(physics_filename.c_str());

			smgr->getMesh(collada_filename);

			for(int i = 0; i < fileLoader->getNumRigidBodies(); i++)
			{
				btRigidBody* rb = (btRigidBody*)fileLoader->getRigidBodyByIndex(i);

				if(lock2d)
				{
					rb->setLinearFactor(btVector3(1,0,1));
					rb->setAngularFactor(btVector3(0,1,0));
				}

				stringc meshname(fileLoader->getNameForPointer(rb));

				stringc bodyname = meshname;
				stringc tex_file = meshname;

				s32 underline = tex_file.findFirst('_');
				if(underline < 0)
					underline = tex_file.findFirst('.');
				if(underline > -1)
					tex_file = tex_file.subString(0, underline+1);

				tex_file = mediaDirectory + tex_file + ".jpg";

				if(fileLoader->getNumRigidBodies() > 1)
					meshname = collada_filename + "#" + meshname + "-mesh";
				else
					meshname = collada_filename;
				IAnimatedMesh *mesh = smgr->getMeshCache()->getMeshByName(meshname);

				if(mesh){
					IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh, smgr->getRootSceneNode());
					node->setMaterialFlag(EMF_LIGHTING, true);
					node->setMaterialFlag(EMF_TEXTURE_WRAP, false);
					node->setMaterialFlag(EMF_BACK_FACE_CULLING, false);
					node->addShadowVolumeSceneNode(0,-1,false);

					if(smgr->getFileSystem()->existFile(tex_file))
					{
						node->setMaterialTexture(0, driver->getTexture(tex_file));
					}

					PhysicalObject* pobj = new PhysicalObject(node, rb, bodyname);
					objects_list.push_back(pobj);
					structure.bodies.push_back(pobj);
					dynamicsWorld->addRigidBody(pobj->getRigidBody());

				}

			}


			for(int i = 0; i < fileLoader->getNumConstraints(); i++)
			{
				Joint* jt = new Joint(fileLoader->getConstraintByIndex(i));
				joints_list.push_back(jt);
				structure.joints.push_back(jt);
				btTypedConstraint* constr = jt->getConstraint();
				dynamicsWorld->addConstraint(constr, true);
			}

			delete fileLoader;

			updateObjects();
			return true;
		}
	}

	return false;

}
예제 #17
0
 void PhysicalObject::antigravitate(const PhysicalObject &other)
 {
     Vector distance(getPosition()-other.getPosition());
     force(Vector(Mag_t<double>(Mass::GetGravityForce(getMass(), other.getMass(), distance.mag())/getMass()), distance.theta()));
 }
예제 #18
0
/** Updates the physics simulation and handles all collisions.
 *  \param ticks Number of physics steps to simulate.
 */
void Physics::update(int ticks)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Since the world update (which calls physics update) is called at the
    // fixed frequency necessary for the physics update, we need to do exactly
    // one physic step only.
    double start;
    if(UserConfigParams::m_physics_debug) start = StkTime::getRealTime();

    m_dynamics_world->stepSimulation(stk_config->ticks2Time(1), 1,
                                     stk_config->ticks2Time(1)      );
    if (UserConfigParams::m_physics_debug)
    {
        Log::verbose("Physics", "At %d physics duration %12.8f",
                     World::getWorld()->getTicksSinceStart(),
                     StkTime::getRealTime() - start);
    }

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine =
                                            Scripting::ScriptEngine::getInstance();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction(false, "void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();

            TrackObject* to = obj->getTrackObject();
            TrackObject* library = to->getParentLibrary();
            std::string lib_id;
            std::string* lib_id_ptr = NULL;
            if (library != NULL)
                lib_id = library->getID();
            lib_id_ptr = &lib_id;

            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, const string, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, lib_id_ptr);
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties *kp = kart->getKartProperties();
                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties *kp = kart->getKartProperties();

                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }

            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                LocalPlayerController *lpc =
                    dynamic_cast<LocalPlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && lpc && lpc->canGetAchievements())
                {
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT, 1);
                        if (race_manager->isLinearRaceMode())
                            PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT_1RACE, 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
예제 #19
0
bool PhysicalObject::isIntersecting(PhysicalObject &physicalObject)
{
    return !(getPolygonShape().intersected(physicalObject.getPolygonShape()).isEmpty());
}
예제 #20
0
파일: Player.cpp 프로젝트: wnr/cprog13-game
void Player::initCommands() {
    std::function<void (std::vector<std::string> commandWords, std::function<bool(const std::vector<std::string> &)>)> addCommands = [this](std::vector<std::string> commandWords, std::function<bool(const std::vector<std::string> &)> operation){
        if(commandWords.size() < 1) {
            throw std::invalid_argument("You must at least have one word associated with the command");
        }
        uniqueCommands.push_back(commandWords.front());
        for(std::string word: commandWords){
            if(commands.find(word) != commands.end()) {
                throw std::invalid_argument("The word: " + word + " is associated with more than one command");
            }
            commands[word] = operation;
        }
        
    };
    
    std::function<bool (const std::vector<std::string> & commands, const std::string & helpText, const std::string & usageCommands)> isHelp = [](const std::vector<std::string> & commands, const std::string & helpText, const std::string & usageCommands){
        if(commands.size() != 2){ return false; };
        if(commands[1] != "help"){ return false; };
        
        std::cout << TEXT_DIVIDER << " HELP: " << commands[0] << " " << TEXT_DIVIDER << std::endl;
        if(helpText != "") {
            std::cout << helpText << std::endl;
        }
        std::cout << "Usage: " << commands[0] << " " << usageCommands << std::endl;
        return true;
    };
    
    addCommands({"go", "move", "goto"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Used for navigating through the world.", "LOCATION")) { return false; }
            
        if(commands.size() != 2) {
            std::cout << "You forgot to write where you wanna go." << std::endl;
            return false;
        }
        
        
        int num = -1; 
        try {
            num = atoi(commands[1].c_str()) - 1;
        } catch(int) {
            std::cout << "That is not an option. Write one of the numbers given as option." << std::endl;
            return false;
        }
        
        auto dirs = getEnvironment()->getDirections();
        
        if(num >= dirs.size()) {
            std::cout << "That is not an option. Write one of the numbers given as option." << std::endl;
            return false;
        }
        
        if(!this->move(dirs[num])) {
                std::cout << "That is not an option. Write one of the numbers given as option." << std::endl;
                return false;
            }
        
        return true;
    });
    
    addCommands({"look"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Look for example at different characters or on items to get more information. You can look at almost anything in the world.", "[CONTAINER] [OBJECT]")) { return false;}
        Environment * env = getEnvironment();
        if(commands.size() == 1) {
            printUpdateInfo();
        } else if(commands.size() == 2) {
            if(isCommandInventory(commands[1])) {
                std::cout << getInventory()->getDescription() << std::endl;
                return false;
            }
            if(isCommandEquipment(commands[1])) {
                std::cout << getEquipment()->getDescription() << std::endl;
                return false;
            }
            PhysicalObject * physicalObject = env->find(commands[1]);
            if(physicalObject == NULL) {
                std::cout << "Found no item named: " << commands[1] << std::endl;
            } else {
                std::cout << physicalObject->getDescription() << std::endl;
            }
            
            
        } else if(commands.size() == 3) {
            Item * item = NULL;
            if(isCommandInventory(commands[1])) {
                Inventory * inv = getInventory();
                item = inv->find(commands[2]);
                if(item == NULL) {
                    std::cout << "Found no item named: " << commands[2] << " in your inventory." << std::endl;
                    return false;
                }
            } else if(isCommandEquipment(commands[1])) {
                Equipment * eq = getEquipment();
                item = eq->find(commands[2]);
                if(item == NULL) {
                    std::cout << "Found no item named: " << commands[2] << " in your equipment." << std::endl;
                    return false;
                }
            } else {
                Container * con = env->find<Container>(OBJECT_TYPE_CONTAINER, commands[2]);
                if(con == NULL) {
                    std::cout << "Found no container named: " <<commands[1] << std::endl;
                    return false;
                } else {
                    item = con->find(commands[2]);
                    if(item == NULL) {
                        std::cout << "Found no item named: " << commands[2] << " in container: " << con->getName() << std::endl;
                        return false;
                    }
                }
            }
            std::cout << item->getDescription() << std::endl;
        }
        
        return false;
    });
    
    addCommands({"stats"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Get information about you.",  "")) { return false;}
        std::cout << getDescription() << std::endl;
        return false;
    });
    
    addCommands({"inventory", "backpack", "inv"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Get information about your inventory that contains items.", "")) { return false;}
        Inventory * inv = getInventory();
        std::cout << inv->getDescription() << std::endl;
        return false;
    });
    
    addCommands({"equipment"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Get information about your current equipment.", "")) { return false;}
        Equipment * eq = getEquipment();
        std::cout << eq->getDescription() << std::endl;
        return false;
    });
    
    addCommands({"pick"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Pick up items from the ground or from containers like for example Chests.", "[CONTAINER] ITEM")) { return false;}
        if(commands.size() < 2) {
            std::cout << "You forgot to write what you wanted to pick up." << std::endl;
            return false;
        }
        
        Environment * env = getEnvironment();
        if(commands.size() == 2) {
            Item * item = env->find<Item>(OBJECT_TYPE_ITEM, commands[1]);
            if(item == NULL) {
                std::cout << "Found no item named: " << commands[1] << std::endl;
                return false;
            }
            
            if(!pickItem(item)) {
                std::cout << "You can't pick up item: " << commands[1] << std::endl;
                return false;
            }
            
            std::cout << "You picked up item: " << commands[1] << std::endl;
            
            return false;
        } else if(commands.size() == 3) {
            Container * container = env->find<Container>(OBJECT_TYPE_CONTAINER, commands[1]);
            if(container == NULL) {
                std::cout << "Found no container named: " <<commands[1] << std::endl;
                return false;
            }
            
            Item * item = container->find<Item>(OBJECT_TYPE_ITEM, commands[2]);
            if(item == NULL) {
                std::cout << "Found no item named: " << commands[2] << " in container: " << commands[1] << std::endl;
                return false;
            }
            
            if(!pickItem(item, container)) {
                std::cout << "You can't pick up item: " << commands[2] << " in container: " << commands[1] << std::endl;
                return false;
            }

            std::cout << "You picked up item: " << commands[2] << " from container: " << commands[1]<< std::endl;
            
            return false;
        }
        
        std::cout << "Invalid command syntax. Usage: pick [CONTAINER] ITEM" << std::endl;
        return false;
    });
    
    addCommands({"drop", "put"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Drop items on the ground or drop them into containers.", "[CONTAINER] ITEM")) { return false;}
        if(commands.size() < 2) {
            std::cout << "You forgot to write what you wanted to drop." << std::endl;
            return false;
        }
        
        Inventory * inv = getInventory();
        if(commands.size() == 2) {
            Item * item = inv->find(commands[1]);
            if(item == NULL) {
                std::cout << "Found no item named: " << commands[1] << " in your inventory." << std::endl;
                return false;
            }
            
            if(!dropItem(item)) {
                std::cout << "You can't drop item: " << commands[1] << " from your inventory. " << std::endl;
                return false;
            }
            
            std::cout << "You dropped item: " << commands[1] << " from your inventory. " << std::endl;
            return false;
            
        } else if(commands.size() == 3) {
            Environment * env = getEnvironment();
            Container * container = env->find<Container>(OBJECT_TYPE_CONTAINER, commands[1]);
            if(container == NULL) {
                std::cout << "Found no container named: " <<commands[1] << std::endl;
                return false;
            }
            
            Item * item = inv->find(commands[2]);
            if(item == NULL) {
                std::cout << "Found no item named: " << commands[2] << " in your inventory." << std::endl;
                return false;
            }
            
            if(!putItem(item, container)) {
                std::cout << "You can't put item: " << commands[2] << " in container: " << commands[1] << std::endl;
                return false;
            }
            
            std::cout << "You put item: " << commands[2] << " in container: " << commands[1] << std::endl;

            return false;
        }
        
        std::cout << "Invalid command syntax. Usage: drop [CONTAINER] ITEM" << std::endl;
        return false;
    });
    
    addCommands({"open"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"The same as 'look CONTAINER'.", "CONTAINER")) { return false;}
        if(commands.size() != 2) {
            std::cout << "You forgot to write what you wanted to open." << std::endl;
            return false;
        }
        
        Environment * env = getEnvironment();
        Container * container = env->find<Container>(OBJECT_TYPE_CONTAINER, commands[1]);
        if(container == NULL) {
            std::cout << "Found no container named: " <<commands[1] << std::endl;
            return false;
        }
        
        int takenSpace = container->getTakenSpace();
        std::string takenSpaceText = unsignedValToString(takenSpace);
        
        std::cout << container->getDescription() << std::endl;
        
        return false;
    });
    
    addCommands({"unlock"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Unlock containers or items using this command.", "[CONTAINER] LOCKED_OBJECT KEY")) { return false;}
        Environment * env = getEnvironment();
        Inventory * inv = getInventory();
        if(commands.size() < 3 || commands.size() > 4) {
            std::cout << "Invalid command syntax. Usage: unlock [CONTAINER] LOCKED_OBJECT KEY" << std::endl;
            return false;
        }
        KeyLock * lock = NULL;
        std::string containerString;
        std::string lockString;
        std::string keyString;
        if(commands.size() == 4) {
            lockString = commands[2];
            keyString = commands[3];
            Container * con;
            if(isCommandInventory(commands[1])) {
                con = inv;
            } else {
                con = env->find<Container>(OBJECT_TYPE_CONTAINER, commands[1]);
            }
            if(con == NULL) {
                std::cout << "Found no container named: " << commands[1] << std::endl;
                return false;
            }
            lock = dynamic_cast<KeyLock *>(con->find(commands[1]));
            
            containerString = " in container named: " + con->getName();

        } else if(commands.size() == 3) {
            containerString = "";
            lockString = commands[1];
            keyString = commands[2];
            lock = dynamic_cast<KeyLock *>(env->find(commands[1]));
        }
        if(lock == NULL) {
            std::cout << "Found no lockable object named: " << lockString << containerString << std::endl;
            return false;
        }
        Key * key = inv->find<Key>(OBJECT_TYPE_ITEM, ITEM_TYPE_KEY, keyString);
        if(key == NULL) {
            std::cout << "Found no key named: " << keyString  << " in your inventory."<< std::endl;
            return false;
        }
        std::string keyName = key->getName();
        PhysicalObject * test = dynamic_cast<PhysicalObject*>(lock); // Needed because not strictly
        if(test == nullptr) {
            throw std::runtime_error("The lockable item was not a PhysicalObject. Should not be possible.");
        }
        std::string lockName = test->getName();
        if(lock->unlock(key, *inv)) {
            std::cout << "You unlocked: " << lockName << containerString << " using key: " << keyName << std::endl;
            return false;
        } else {
            std::cout << "You can't unlock: " << lockName << containerString << " using key: " << keyName << std::endl;
            return false;
        }
    });
    
    addCommands({"eat", "drink"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Use this command to consume items. Tip: Write 'drink' so you don't accidentally chew liquids.", "ITEM")) { return false;}
        if(commands.size() != 2) {
            std::cout << "Invalid command syntax. Usage: eat FOOD" << std::endl;
            return false;
        }
        
        Consumable * cItem = getInventory()->find<Consumable>(OBJECT_TYPE_ITEM, ITEM_TYPE_CONSUMABLE, commands[1]);
        if(cItem == NULL) {
            std::cout << "Found no consumable item named: " << commands[1]  << " in your inventory."<< std::endl;
            return false;
        }
        
        std::string consumableName = cItem->getName();
        std::string response = cItem->consume(this);
        std::cout << "You digested " << consumableName  << " and " << response << std::endl;
        return false;
    });
    
    addCommands({"equip", "eq"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "Used for equipping items. You can only equip one of each type of equippable item.", "[ITEM]")) { return false;}
        if(commands.size() != 2) {
            std::cout << "Invalid command syntax. Usage: equip ITEM" << std::endl;
            return false;
        }
        
        Inventory * inv = getInventory();
        Item * item = inv->find(commands[1]);
        if(item == NULL) {
            std::cout << "Found no equipable item named: " << commands[1] << std::endl;
            return false;
        }
        
        BreakableItem * bItem = dynamic_cast<BreakableItem*>(item);
        if(bItem == nullptr) {
            std::cout << "The item: " << item->getName() << " is not equipable." << std::endl;
            return false;
        }
        
        if(equip(bItem)) {
            std::cout << "You equipeed item: " << bItem->getName() << std::endl;
            return false;
        } else {
            std::cout << "You failed to equip: " << bItem->getName() << std::endl;
            return false;
        }
    });
    
    addCommands({"unequip", "uneq", "ueq"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Used for removing equipped items and putting them back to your inventory, if you have enough space.", "ITEM")) { return false;}
        if(commands.size() != 2) {
            std::cout << "Invalid command syntax. Usage: equip ITEM" << std::endl;
            return false;
        }
        
        Equipment * eq = getEquipment();
        BreakableItem * bItem = eq->find(commands[1]);
        if(bItem == NULL) {
            std::cout << "Found no equiped item named: " << commands[1] << std::endl;
            return false;
        }
        if(unEquip(bItem)) {
            std::cout << "You unequiped item: " << bItem->getName() << std::endl;
            return false;
        } else {
            std::cout << "You failed to unequip: " << bItem->getName() << std::endl;
            return false;
        }
    });
    
    addCommands({"attack", "att"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands, "KILL!", "CHARACTER")) { return false;}
        if(commands.size() != 2) {
            std::cout << "You forgot to write what you wanted to attack." << std::endl;
            return false;
        }
        
        Character * character = getEnvironment()->find<Character>(OBJECT_TYPE_CHARACTER, commands[1], {this});
        
        if(character == NULL) {
            std::cout << "There is no " + commands[1] << " in the area." << std::endl;
            return false;
        }
        
        if(!character->startInteraction(this)) {
            std::cout << "The " << character->getName() << " busy fighting already." << std::endl;
            return false;
        }
        
        std::cout << std::endl << "You are initiating a fight with " << character->getName() << "!" << std::endl;
        
        interact(character);
        
        character->endInteraction(this);
        endInteraction(character);
        
        
        return true;
    });
    
    addCommands({"pass", "wait", "skip"}, [isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Wait a moment and let others take their turn.", "")) { return false;}
        return true;
    });
    
    addCommands({"exit"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Exit the game. No turning back after this.", "")) { return false;}
        this->getEngine()->kill();
        return true;
    });
    
    addCommands({"help"}, [this, isHelp](const std::vector<std::string> & commands) -> bool {
        if(isHelp(commands,"Helpception?", "")) { return false;}
        std::cout << std::endl;
        std::cout << TEXT_DIVIDER << " HELP START " << TEXT_DIVIDER << std::endl;
        std::cout << "For more help on individual commands, write: COMMAND help" << std::endl;
        std::cout << "COMMANDS" << std::endl;
        std::cout << TEXT_DIVIDER << std::endl;
        
        for(auto command : getUniqueCommands()) {
            std::cout << command << std::endl;
        }
        
        std::cout << TEXT_DIVIDER << " HELP END " << TEXT_DIVIDER << std::endl;
        return false;
    });
}
예제 #21
0
파일: Playground.cpp 프로젝트: plsm/enki
	virtual void timerEvent(QTimerEvent * event)
	{
		static int fireCounter = 0;
		#ifdef USE_SDL
		SDL_JoystickUpdate();
		doDumpFrames = false;
		for (int i = 0; i < joysticks.size(); ++i)
		{
			EPuck* epuck = epucks[i];
			
			if (world->hasGroundTexture())
				cout << "Robot " << i << " is on ground of colour " << world->getGroundColor(epuck->pos) << endl;
			
			#define SPEED_MAX 13.
			//cout << "S " << epuck->infraredSensor2.getRayDist(0) << " " << epuck->infraredSensor2.getRayDist(1) << " " << epuck->infraredSensor2.getRayDist(2) << endl;
			#if 0 
			epuck->leftSpeed = - SDL_JoystickGetAxis(joysticks[i], 1) / (32767. / SPEED_MAX);
			epuck->rightSpeed = - SDL_JoystickGetAxis(joysticks[i], 4) / (32767. / SPEED_MAX);
			#else
			double x = SDL_JoystickGetAxis(joysticks[i], 0) / (32767. / SPEED_MAX);
			double y = -SDL_JoystickGetAxis(joysticks[i], 1) / (32767. / SPEED_MAX);
			epuck->leftSpeed = y + x;
			epuck->rightSpeed = y - x;
			#endif
			
			if ((SDL_JoystickGetButton(joysticks[i], 6) || SDL_JoystickGetButton(joysticks[i], 7)) &&
				(++fireCounter % 2) == 0)
			{
				PhysicalObject* o = new PhysicalObject;
				Vector delta(cos(epuck->angle), sin(epuck->angle));
				o->pos = epuck->pos + delta * 6;
				o->speed = epuck->speed + delta * 10;
				o->setCylindric(0.5, 0.5, 10);
				o->dryFrictionCoefficient = 0.01;
				o->setColor(Color(0.4, 0, 0));
				o->collisionElasticity = 1;
				bullets[o] = 300;
				world->addObject(o);
			}
			doDumpFrames |= SDL_JoystickGetButton(joysticks[i], 0);
		}
		if (joysticks.size() > 0 && subjectiveView)
		{
			const EPuck* epuck = epucks[0];
			Vector p(epuck->pos);
			camera.pos.setX(p.x+cos(camera.yaw)*7);
			camera.pos.setY(p.y+sin(camera.yaw)*7);
			camera.yaw = epuck->angle;
			camera.altitude = 11;
		}
		#endif
		QMap<PhysicalObject*, int>::iterator i = bullets.begin();
		while (i != bullets.end())
		{
			QMap<PhysicalObject*, int>::iterator oi = i;
			++i;
			if (oi.value())
			{
				oi.value()--;
			}
			else
			{
				PhysicalObject* o = oi.key();
				world->removeObject(o);
				bullets.erase(oi);
				delete o;
			}
		}
		ViewerWidget::timerEvent(event);
	}
예제 #22
0
void SimObjectRenderer::draw()
{
  // update a moving camera
  if(moving)
  {
    unsigned int now = System::getTime();
    int x = 0;
    int y = 0;
    if(movingLeftStartTime)
    {
      x -= now - movingLeftStartTime;
      movingLeftStartTime = now;
    }
    if(movingRightStartTime)
    {
      x += now - movingRightStartTime;
      movingRightStartTime = now;
    }
    if(movingUpStartTime)
    {
      y -= now - movingUpStartTime;
      movingUpStartTime = now;
    }
    if(movingDownStartTime)
    {
      y += now - movingDownStartTime;
      movingDownStartTime = now;
    }
    moveCamera(float(x) * 0.001f, float(y) * 0.002f);
  }

  // set flags
  if(renderFlags & enableLights)
    glEnable(GL_LIGHTING);
  else
    glDisable(GL_LIGHTING);
  if(renderFlags & enableMultisample)
    glEnable(GL_MULTISAMPLE);
  else
    glDisable(GL_MULTISAMPLE);
  if(renderFlags & enableTextures)
    glEnable(GL_TEXTURE_2D);
  else
    glDisable(GL_TEXTURE_2D);

  // clear
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // load camera position
  glLoadMatrixf(cameraTransformation);

  // make sure transformations of movable bodies are up-to-date
  // note: a not-physical-object has a constant offset pose relative its parent. hence there is no transformation update required to draw not-physical-objects
  PhysicalObject* physicalObject = dynamic_cast<PhysicalObject*>(&simObject);
  GraphicalObject* graphicalObject = dynamic_cast<GraphicalObject*>(&simObject);
  if(physicalObject)
    Simulation::simulation->scene->updateTransformations();

  // since each object will be drawn relative to its parent we need to shift the coordinate system when we want the object to be in the center
  if(&simObject != Simulation::simulation->scene && !(renderFlags & showAsGlobalView))
  {
    const float* transformation = simObject.transformation;
    Pose3<> pose(Matrix3x3<>(Vector3<>(transformation[0], transformation[1], transformation[2]),
      Vector3<>(transformation[4], transformation[5], transformation[6]),
      Vector3<>(transformation[8], transformation[9], transformation[10])),
      Vector3<>(transformation[12], transformation[13], transformation[14]));
    float invTrans[16];
    OpenGLTools::convertTransformation(pose.invert(), invTrans);
    glMultMatrixf(invTrans);
  }

  // draw origin
  if(renderFlags & showCoordinateSystem)
  {
    Simulation::simulation->scene->defaultSurface->set();

    glBegin(GL_LINES);
      glNormal3f (0,0,1);
      glColor3f(1, 0, 0); glVertex3f(0, 0, 0); glVertex3f(1, 0, 0);
      glColor3f(0, 1, 0); glVertex3f(0, 0, 0); glVertex3f(0, 1, 0);
      glColor3f(0, 0, 1); glVertex3f(0, 0, 0); glVertex3f(0, 0, 1);
    glEnd();

    Simulation::simulation->scene->defaultSurface->unset();
  }

  // draw object / scene appearance
  if(graphicalObject && surfaceShadeMode != noShading)
  {
    switch(surfaceShadeMode)
    {
      case flatShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_FLAT);
        break;
      case wireframeShading:
        glPolygonMode(GL_FRONT, GL_LINE);
        glShadeModel(GL_FLAT);
        break;
      case smoothShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_SMOOTH);
        break;
      default:
        ASSERT(false);
        break;
    }
    graphicalObject->drawAppearances();

    // check matrix stack size
#ifdef _DEBUG
    int stackDepth;
    glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stackDepth);
    ASSERT(stackDepth == 1);
#endif
  }

  // draw object / scene physics
  if(physicalObject && (physicsShadeMode != noShading || renderFlags & showSensors))
  {
    Simulation::simulation->scene->defaultSurface->set();

    unsigned int renderFlags = (this->renderFlags | showPhysics) & ~showControllerDrawings;
    switch(physicsShadeMode)
    {
      case noShading:
        glPolygonMode(GL_FRONT, GL_LINE);
        glShadeModel(GL_FLAT);
        renderFlags &= ~showPhysics;
        break;
      case flatShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_FLAT);
        break;
      case wireframeShading:
        glPolygonMode(GL_FRONT, GL_LINE);
        glShadeModel(GL_FLAT);
        break;
      case smoothShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_SMOOTH);
        break;
      default:
        ASSERT(false);
        break;
    }
    physicalObject->drawPhysics(renderFlags);

    Simulation::simulation->scene->defaultSurface->unset();

    // check matrix stack size
#ifdef _DEBUG
    int stackDepth;
    glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stackDepth);
    ASSERT(stackDepth == 1);
#endif
  }

  // draw drag plane
  if(dragging && dragSelection)
  {
    Simulation::simulation->scene->defaultSurface->set();

    glPolygonMode(GL_FRONT, GL_FILL);
    glShadeModel(GL_FLAT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);

    glPushMatrix();
    if(dragType == dragRotate || dragType == dragNormalObject)
      glMultMatrixf(dragSelection->transformation);
    else
      glTranslatef(dragSelection->pose.translation.x, dragSelection->pose.translation.y, dragSelection->pose.translation.z);

    switch(dragPlane)
    {
      case xyPlane:
        break; // do nothing
      case xzPlane:
        glRotatef(90.f, 1.f, 0.f, 0.f);
        break;
      case yzPlane:
        glRotatef(90.f, 0.f, 1.f, 0.f);
        break;
    }

    GLUquadricObj* q = gluNewQuadric();
    glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
    glNormal3f(0,0,1);
    gluDisk(q, 0.003f, 0.5f, 30, 1);
    glRotatef(180.f, 1.f, 0.f, 0.f);
    gluDisk(q, 0.003f, 0.5f, 30, 1);
    gluDeleteQuadric(q);
    glPopMatrix();

    glDisable(GL_BLEND);

    Simulation::simulation->scene->defaultSurface->unset();
  }

  // draw controller drawings
  if(physicalObject && drawingsShadeMode != noShading)
  {
    Simulation::simulation->scene->defaultSurface->set();

    switch(drawingsShadeMode)
    {
      case flatShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_FLAT);
        break;
      case wireframeShading:
        glPolygonMode(GL_FRONT, GL_LINE);
        glShadeModel(GL_FLAT);
        break;
      case smoothShading:
        glPolygonMode(GL_FRONT, GL_FILL);
        glShadeModel(GL_SMOOTH);
        break;
      default:
        ASSERT(false);
        break;
    }

    if(renderFlags & (enableDrawingsTransparentOcclusion | enableDrawingsOcclusion))
    {
      physicalObject->drawPhysics(showControllerDrawings);
      if(renderFlags & enableDrawingsTransparentOcclusion)
      {
        glAccum(GL_LOAD, 0.5f);
        glClear(GL_DEPTH_BUFFER_BIT);
        physicalObject->drawPhysics(showControllerDrawings);
        glAccum(GL_ACCUM, 0.5f);
        glAccum(GL_RETURN, 1.f);
      }
    }
    else
    {
      glClear(GL_DEPTH_BUFFER_BIT);
      physicalObject->drawPhysics(showControllerDrawings);
    }

    Simulation::simulation->scene->defaultSurface->unset();

    // check matrix stack size
#ifdef _DEBUG
    int stackDepth;
    glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stackDepth);
    ASSERT(stackDepth == 1);
#endif
  }
}
예제 #23
0
파일: Weapon.cpp 프로젝트: scottrick/dgame
void Weapon::Fire()
{
	if (m_fCurrentCooldown <= 0.0f)
	{
		m_fCurrentCooldown = m_fCooldown;

		PhysicalObject *pOwner = GetOwner();
		
		if (pOwner)
		{
			Node			*pSourceNode = pOwner->GetNode();
			
			if (pSourceNode)
			{
				Projectile *pNewProjectile = new Projectile(GetNode());
				VECTOR3 vDirection;

				Matrix44 mat = pSourceNode->m_PosQuat.quat.ToMatrix();

				float yDisp = -(pSourceNode->m_vScale.y / 2.0f + pNewProjectile->GetNode()->m_vScale.y / 2.0f);

				if (pSourceNode->GetNodeFlags() & NODE_RENDER_UPSIDEDOWN)
				{
					yDisp *= -1.0f;
				}

				pNewProjectile->GetNode()->m_PosQuat.pos.x = mat.m[4] * yDisp + pSourceNode->m_PosQuat.pos.x;
				pNewProjectile->GetNode()->m_PosQuat.pos.y = mat.m[5] * yDisp + pSourceNode->m_PosQuat.pos.y;
				pNewProjectile->GetNode()->m_PosQuat.pos.z = mat.m[6] * yDisp + pSourceNode->m_PosQuat.pos.z;

				//calculate actual firing direction based on aim, and weapon spread
				int dwRandom = GenerateRandomInt(9);
				float fSpread = 0.0f;
				if (dwRandom < 7)
				{
					fSpread = GenerateRandomFloat(0.05f);
				}
				else if (dwRandom < 9)
				{
					fSpread = GenerateRandomFloat(0.15f) + 0.05f;
				}
				else
				{
					fSpread = GenerateRandomFloat(0.30f) + 0.2f;
				}
				
				if (GenerateRandomInt(1))
				{
					fSpread = -fSpread;
				}
				
				fSpread = fSpread * m_fFiringSpread;
				float fCos = cos(fSpread);
				float fSin = sin(fSpread);
				
				//vDirection.x = fCos * m_vAim.x + fSin * m_vAim.x;
				//vDirection.y = fCos * m_vAim.y - fSin * m_vAim.y;
				vDirection.x = fCos * m_vAim.x - fSin * m_vAim.y;
				vDirection.y = fSin * m_vAim.x + fCos * m_vAim.y;
				vDirection.z = 0.0f;

				NormalizeVECTOR3(vDirection);

				pNewProjectile->GetNode()->m_PosQuat.pos.z = pSourceNode->m_PosQuat.pos.z;
				pNewProjectile->SetMaxSpeed(m_fSpeed);

				pNewProjectile->SetVelocity(VECTOR3(m_fSpeed * vDirection.x, m_fSpeed * vDirection.y, m_fSpeed * vDirection.z));
				pNewProjectile->SetCreator(pOwner);
				pNewProjectile->SetWeapon(this);

				Quat *quat = &(pNewProjectile->GetNode()->m_PosQuat.quat);
				Quat rotation;
				rotation.CreateFromRotationRADIANS(fSpread, 0.0f, 0.0f, 1.0f);
				*quat = rotation * *quat;

				TestFireEvent *pTestFireEvent = new TestFireEvent();
				pTestFireEvent->SetProjectile(pNewProjectile);
				gEventManager()->AddEvent(pTestFireEvent);
				pTestFireEvent->Release();
				pNewProjectile->Release();	
			}
		}
	}
}