ekku@197: #ifndef PHYSICS_OBJECT_HH ekku@197: #define PHYSICS_OBJECT_HH ekku@197: ekku@197: ekku@197: // Forward declares ekku@197: class PhysicsObject; ekku@197: struct Derivative; ekku@197: ekku@197: #include "PhysicsWorld.hh" ekku@197: #include "Vector.hh" terom@205: #include "Timer.hh" ekku@197: #include "Config.hh" ekku@197: terom@423: #include terom@423: #include terom@423: ekku@197: // Type definitions ekku@197: typedef Vector Force; saiam@320: saiam@320: /** Specifies possible object types. */ ekku@265: enum ObjectType { PLAYER, PROJECTILE, ROPE }; ekku@197: saiam@320: /** Specifies possible facing directions for objects. */ terom@264: enum FacingDirection { terom@264: FACING_LEFT, terom@264: FACING_RIGHT terom@264: }; ekku@197: ekku@197: /** saiam@321: * PhysicsObject class. Represents an object in the physics simulation. ekku@197: */ ekku@197: class PhysicsObject { terom@428: protected: saiam@320: /** Reference to PhysicsWorld. */ terom@282: PhysicsWorld &world; terom@282: terom@428: private: terom@428: /** Position */ ekku@197: Vector position; terom@427: terom@428: /** Position at previous tick */ ekku@285: Vector previousPosition; terom@427: terom@428: /** Velocity */ ekku@197: Vector velocity; terom@427: terom@428: /** Mass */ terom@428: float mass; terom@428: terom@428: /** Object's shape, polygon vertices */ terom@428: std::vector shape; terom@427: terom@428: /** Force queue, emptied on every physics tick */ terom@428: std::queue > forceq; terom@428: terom@428: terom@428: protected: saiam@320: /** Tells if the object is "on the ground" */ saiam@320: bool inAir; terom@427: terom@428: /** Object elasticity */ ekku@197: float collision_elasticity; ekku@197: terom@428: /** Aim angle in radians */ saiam@320: float aim; terom@427: terom@428: /** Player facing */ saiam@320: FacingDirection facing; ekku@197: terom@427: /** Specifies if the object should be simulated */ ekku@222: bool alive; terom@427: terom@427: /** True if !alive, and the object can be delete'd */ ekku@225: bool shouldDelete; ekku@265: saiam@320: /** Type of the object */ ekku@265: ObjectType type; ekku@222: terom@427: /** Pivot object for this object */ ekku@228: PhysicsObject *pivot; ekku@228: saiam@320: /** saiam@320: * Class constructor saiam@320: * saiam@320: * @param world Reference to PhysicsWorld saiam@320: * @param mass Object mass saiam@320: * @param position Object position saiam@320: * @param velocity Object velocity saiam@320: * @param type Object type saiam@320: * @param collision_elasticity Object elasticity saiam@320: * @param enabled Is the object currently part of the simulation saiam@320: */ terom@279: PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity, ObjectType type, terom@279: float collision_elasticity, bool enabled = true); terom@427: terom@427: /** terom@427: * Virtual destructor terom@427: */ ekku@222: virtual ~PhysicsObject (void); ekku@197: ekku@197: /** saiam@320: * Apply a force to the object. The force is applied to the object saiam@320: * on the next physics tick. ekku@197: * ekku@197: * @param force Force vector ekku@197: */ terom@427: void applyForce (Force force, TimeMS dt = PHYSICS_TICK_MS); ekku@197: ekku@197: /** saiam@320: * Change player aim. This function takes care that aim angle saiam@320: * stays inside limits. ekku@197: * saiam@320: * @param da Aim angle change in radians ekku@197: */ terom@427: void changeAim (float da); ekku@197: ekku@197: /** ekku@197: * Set player facing. ekku@197: * ekku@197: * @param facingRight True if player is facing right. ekku@197: */ terom@428: void setFacing (FacingDirection facing) { terom@428: this->facing = facing; terom@428: } ekku@197: ekku@197: /** ekku@197: * Makes the player jump in the air. saiam@320: * ekku@197: * @param direction -1: jump left, 0: jump up, 1: jump right ekku@197: */ terom@299: void jump (int direction); ekku@197: ekku@197: /** saiam@320: * Handle object bounce. ekku@197: * ekku@197: * @param normal Normal vector relative to which to bounce ekku@197: */ terom@299: void bounce (Vector normal); ekku@197: ekku@197: /** ekku@197: * Called on network clients to sync state from server ekku@197: * ekku@197: * @param position New position ekku@197: * @param velocity New velocity ekku@197: * @param inAir New inAir value terom@200: * @param facingRight New facingRight value terom@200: * @param aim New aim ekku@197: */ terom@299: virtual void updatePhysics (Vector position, Vector velocity, bool inAir, FacingDirection facing, float aim); ekku@197: ekku@225: /** saiam@320: * Put the object in the physics simulation. When the object is in saiam@320: * the physics simulation it's movements will be calculated. ekku@225: */ ekku@225: void enable (void); ekku@225: ekku@225: /** saiam@320: * Remove object from the objects physics simulation. When the saiam@320: * object isn't in the physics simulation it won't be deleted but saiam@320: * its movements will not be calculated. ekku@225: */ ekku@225: void disable (void); ekku@225: ekku@197: private: ekku@197: /** ekku@197: * Handle player movement and apply forces. saiam@320: * saiam@320: * @param dt Time intervall ekku@197: */ terom@299: void updatePosition (TimeMS dt); ekku@197: ekku@197: /** ekku@197: * Use RK4 to integrate the effects of force over a time interwall. ekku@197: * ekku@197: * @param force Force to integrate ekku@197: * @param dt Time intervall saiam@320: * @param posAfterTick Reference to object postition after integration. saiam@320: * @param velAfterTick Reference to object velocity after integration. ekku@197: */ terom@299: void integrate (Force force, TimeMS dt, Vector &posAfterTick, Vector &velAfterTick); ekku@197: ekku@197: /** ekku@197: * Evaluate the value of the derivative at given time ekku@197: * ekku@197: * @param force Force ekku@197: * @param dt Time ekku@197: * @param d Previous derivative saiam@320: * @return Derivative ekku@197: */ terom@428: Derivative evaluate (Force force, TimeMS dt, const Derivative &d, const Vector &posAfterTick, const Vector &velAfterTick); ekku@197: ekku@197: /** ekku@197: * Return object acceleration with given force. ekku@197: * ekku@197: * @param force Force ekku@197: * @return Acceleration ekku@197: */ terom@299: Vector acceleration (const Force &force); ekku@197: saiam@249: /** ekku@197: * Handle ground movement. ekku@197: * ekku@197: * @param right Boolean describing the movement direction. ekku@197: * @return New position ekku@197: */ terom@299: void walk (TimeMS, bool right); terom@427: terom@427: /* terom@427: * Undocumented private method terom@427: */ terom@299: Vector walk_one_step (float, bool); ekku@197: nireco@288: public: saiam@249: /** saiam@249: * Define object behaviour on collisions. terom@282: * saiam@320: * @param collisionPoint Point of collision. saiam@320: * @param other The other object we have collided with. ekku@197: */ nireco@288: virtual void onCollision (Vector collisionPoint, PhysicsObject *other = NULL); saiam@272: saiam@249: /** saiam@320: * Get object type. saiam@320: * saiam@320: * @return Object type ekku@287: */ terom@428: ObjectType getType (void) const { terom@428: return type; terom@428: } ekku@287: ekku@287: /** saiam@249: * Checks if it is possible for the object to be in the given saiam@249: * location. saiam@320: * saiam@320: * @param loc Location ekku@197: */ terom@299: bool possibleLocation (Vector loc); ekku@197: ekku@197: /** ekku@197: * Get current object position. ekku@197: * terom@427: * @return position vector ekku@197: */ terom@428: Vector getPosition (void) const { terom@428: return position; terom@428: } terom@255: terom@255: /** ekku@285: * Get previous object position. ekku@285: * terom@427: * @return position vector ekku@285: */ terom@428: Vector getPreviousPosition (void) const { terom@428: return previousPosition; terom@428: } ekku@285: ekku@285: /** terom@255: * Get current object screen coordinates terom@255: * terom@255: * @return PixelCoordinate position terom@255: */ terom@257: PixelCoordinate getCoordinate (void) const; ekku@197: ekku@197: /** ekku@222: * Get current object velocity. ekku@222: * ekku@222: * @return Velocity vector ekku@222: */ terom@428: Vector getVelocity (void) const { terom@428: return velocity; terom@428: } ekku@197: ekku@197: /** ekku@197: * Return object facing. ekku@197: * ekku@197: * @return Object facing (true if facing right) ekku@197: */ terom@428: FacingDirection getFacing (void) const { terom@428: return facing; terom@428: } ekku@197: ekku@197: /** ekku@197: * Return object aim angle. ekku@197: * ekku@197: * @return Object aim angle ekku@197: */ terom@428: float getAim (void) const { terom@428: return aim; terom@428: } ekku@197: ekku@197: /** saiam@320: * Get object direction. saiam@320: * saiam@320: * @return Unit vector to facing+aim terom@235: */ terom@257: Vector getDirection (void) const; terom@235: terom@235: /** ekku@222: * Mark object as destroyed, it will be delete'd later ekku@222: */ ekku@222: void destroy (void); ekku@222: saiam@320: /** saiam@320: * Check if the object is alive. saiam@320: * saiam@320: * @return Is the object alive? ekku@222: */ terom@428: bool isAlive (void) const { terom@428: return alive; terom@428: } ekku@222: ekku@222: /** saiam@320: * Tells the state of the object. saiam@320: * saiam@320: * @return True if object has been destroyed. ekku@222: */ ekku@222: bool removeIfDestroyed (void); ekku@222: ekku@222: /** saiam@320: * Set object pivot. saiam@320: * saiam@320: * @param pivot Pivot object ekku@228: */ terom@428: void setPivot (PhysicsObject *pivot) { terom@428: this->pivot = pivot; terom@428: } ekku@228: ekku@228: /** ekku@322: * Return the pivot object pointer. ekku@322: */ terom@428: PhysicsObject *getPivot (void) { terom@428: return pivot; terom@428: } terom@428: terom@428: /** terom@428: * Compute the force that this object (as a pivot) exerts on the given object terom@428: * terom@428: * @param bob Othe object terom@428: * @return Force terom@428: */ terom@428: virtual Vector getPivotForce (void); ekku@322: ekku@322: /** saiam@268: * Checks if object collides with other objects saiam@268: * saiam@268: * @param obj Other PhysicsObject saiam@320: * @return Did we collide? saiam@268: */ saiam@268: bool collides (const PhysicsObject &obj); saiam@268: saiam@268: /** ekku@197: * Update object in physics simulation. saiam@320: * saiam@320: * @param tick_length Length of the physics tick ekku@197: */ terom@221: virtual void tick (TimeMS tick_length); terom@427: terom@427: protected: terom@427: /** terom@428: * Set object shape. terom@428: * terom@428: * XXX: constructor terom@428: * terom@428: * @param shape Vector containing polygon points terom@428: */ terom@428: void setShape(std::vector shape) { terom@428: this->shape = shape; terom@428: } terom@428: terom@428: /** terom@427: * Update object position, also updating our previous position terom@427: * terom@427: * @param pos new position terom@427: */ terom@427: void setPosition (Vector pos); terom@427: terom@427: /** terom@427: * Update current object velocity. terom@427: * terom@427: * @param velocity new velocity terom@427: */ terom@428: void setVelocity (Vector velocity) { terom@428: this->velocity = velocity; terom@428: } terom@428: terom@428: /** terom@428: * Reset state and disable, ready to be resume()'d again in a different place terom@428: */ terom@428: void reset (void); terom@428: terom@428: /** terom@428: * Resume after a reset() at the given position with a zero velocity terom@428: */ terom@428: void resume (Vector position); ekku@197: }; ekku@197: saiam@320: /** Helper struct for the integration */ ekku@197: struct Derivative { terom@428: /** terom@428: * Velocity terom@428: */ terom@428: Vector dx; terom@428: terom@428: /** terom@428: * Acceleration terom@428: */ terom@428: Vector dv; terom@428: terom@428: Derivative () : dx(), dv() { } terom@428: Derivative (Vector dx, Vector dv) : dx(dx), dv(dv) { } ekku@197: }; ekku@197: saiam@268: /** saiam@268: * Returns the "sign" of the cross product between given points. In saiam@268: * practice the sign of the return value tels on which side of the saiam@268: * line drawn between p1 and p2 the point p3 is. saiam@268: * saiam@268: * @param p1 Line start point saiam@268: * @param p2 Line end point saiam@268: * @param p3 Point saiam@268: * @return Variable, the sign of which tells on which side of the line p3 is. saiam@268: */ saiam@268: int8_t crossProduct(const Vector &p1, const Vector &p2, const Vector &p3); saiam@268: ekku@197: #endif