/* * Copyright (C) 2002,2003,2004 Daniel Heck * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * $Id: world.hh,v 1.42 2004/03/15 20:15:32 dheck Exp $ */ #ifndef WORLD_HH_INCLUDED #define WORLD_HH_INCLUDED #include "objects.hh" #include "util.hh" namespace world { using namespace enigma; /* -------------------- Types -------------------- */ using px::V2; using std::string; /*! * Impulse is used to transfer force from one Object to another * Object. Currently only Stones can be the destination of * Impulses. */ struct Impulse { // Variables Object *sender; GridPos dest; Direction dir; // Constructors Impulse(Object *sender_, const GridPos& dest_, Direction dir_) : sender(sender_), dest(dest_), dir(dir_) {} }; struct Message { // Variables std::string message; enigma::Value value; GridPos gridpos; // Constructors Message (); Message (const std::string &message, const enigma::Value &value, GridPos gridpos = GridPos()); }; /*! The different kinds of materials objects in Enigma can be made of. */ enum MaterialType { MATERIAL_GLASS, MATERIAL_METAL, MATERIAL_STONE, }; /*! * This structure stores all the information that is necessary to * handle collisions between stones and actors. */ struct StoneContact { // Variables. Actor *actor; GridPos stonepos; StoneResponse response; V2 contact_point; // Where do the shapes meet? (world coordinates) V2 normal; // The surface normal at the contact point bool is_collision; // Actor moves towards the stone, not away bool ignore; // Ignore this contact bool new_collision; // True if actor did not touch the stone before bool is_contact; // if false, contact_point is closest feature std::string sound; // Constructor. StoneContact (Actor *a, GridPos stonepos, const V2 & contact_point, const V2 & surface_normal); StoneContact(); }; // Which of the four faces of the stone does the actor touch? Direction contact_face (const StoneContact &sc); DirectionBits contact_faces (const StoneContact &sc); /* -------------------- Force Fields -------------------- */ class ForceField { public: virtual ~ForceField() {} virtual void add_force(Actor *a, V2 &force) = 0; virtual void tick(double /*dtime*/) {} }; class ConstantForce : public ForceField { public: ConstantForce(V2 f=V2()) : force(f) {} void add_force(Actor */*a*/, V2 &f) { f += force; } void set_force (const V2 &force_) { force = force_; } private: V2 force; }; //---------------------------------------------------------------------- // GLOBAL VARIABLES //---------------------------------------------------------------------- /* The global timer for all objects that need to be notified at regular intervals. */ extern util::Timer GameTimer; /* Output a message whenever a message is being sent. */ extern bool TrackMessages; /* A hack to implement BlackBallsStone and WhiteBallsStone. */ extern Actor *CurrentCollisionActor; //---------------------------------------------------------------------- // FUNCTIONS //---------------------------------------------------------------------- /* -------------------- World Management -------------------- */ void Init(); void PrepareLevel (int w, int h); /* Create a new, empty world with width `w' and height `h`. */ void Resize (int w, int h); /* Initialize the world after loading it. Call this after loading the world to force laser beams to be recalculated etc. */ bool InitWorld(); void Tick(double dtime); void TickFinished (); // Destroy all objects and the complete object repository void Shutdown(); bool IsLevelBorder(GridPos p); bool IsInsideLevel(GridPos p); Object *GetObject (const GridLoc &l); /* -------------------- Named Objects -------------------- */ void NameObject (Object *obj, const string &name); void UnnameObject (Object *obj); void TransferObjectName(Object *source, Object *target); Object *GetNamedObject (const string &name); /* -------------------- Force Fields -------------------- */ void AddForceField (ForceField *ff); void RemoveForceField (ForceField *ff); void SetMouseForce (V2 f); void SetConstantForce (V2 force); /* -------------------- Rubbers Bands -------------------- */ struct RubberBandData { double strength; double length; double minlength; RubberBandData (); RubberBandData (const RubberBandData &); }; struct Rubber_Band_Info { Actor *act; RubberBandData data; }; typedef std::vector RBI_vector; /*! Add a rubber band that connects an actor with either a stone or another actor. `strength' is the force constant, and `length' is the natural length of the elastic: if it is shorter than `length' it will exert no force on the actor(s). */ void AddRubberBand (Actor *a, Stone *st, const RubberBandData &d); void AddRubberBand (Actor *a, Actor *a2, const RubberBandData &d); /*! Remove the rubber band between `a' and `st'. If `st' is 0, all rubber bands connecting `a' to a stone will be cut. */ void KillRubberBand (Actor *a, Stone *st); /*! Remove the rubber band between `a' and `a2'. If `a2' is 0, all rubber bands connecting `a' to other actors will be cut. */ void KillRubberBand (Actor *a, Actor *a2); /*! Remove all rubber bands attached to stone ST. */ void KillRubberBands (Stone *st); /*! Fills given vector with basic info about rubbers attached to given stone */ void GiveRubberBands (Stone *st, RBI_vector &rubbers); /*! Returns true if there already is a rubber band connecting `a' and `st'. */ bool HasRubberBand (Actor *a, Stone *st); /* -------------------- Puzzle Stone Scrambling -------------------- */ void SetScrambleIntensity(int intensity); void AddScramble(GridPos p, Direction d); /* -------------------- Signals & Messages -------------------- */ void AddSignal (const GridLoc &src, const GridLoc &dst, const string &msg); bool HaveSignals (Object *src); /*! Return true if suitable signal was found. */ bool EmitSignalByIndex (Object *src, int signalidx, int value=0); /* Signal indices start at 0 */ bool GetSignalTargetPos (Object *src, GridPos &pos, int signalidx = 0); void BroadcastMessage (const std::string& msg, const enigma::Value& value, GridLayerBits grids); void SendMessage (Object *o, const string &msg); void SendMessage (Object *o, const string &msg, const enigma::Value& value); void SendMessage (Object *o, const Message &m); /*! This function is used by all triggers, switches etc. that perform some particular action when activated (like opening doors or switching lasers on and off). It interprets the "action" and "target" attributes of `o'. */ void PerformAction (Object *o, bool onoff); /* -------------------- Actors -------------------- */ void AddActor (Actor *a); void AddActor (double x, double y, Actor* a); Actor *YieldActor(Actor *a); void KillActor (Actor *a); void WarpActor (Actor *a, double newx, double newy, bool keep_velocity); /*! Move `a' to its respawnpos immediately; do not run an animation like `RespawnActor(a)' would. */ void FastRespawnActor (Actor *a, bool keep_velocity); /*! Like FastRespawnActor but marble 'appears' by running an animation. */ void RespawnActor (Actor *a); /*! Find the marble of the other color (ac-whiteball <-> ac-blackball). */ Actor *FindOtherMarble (Actor *thisMarble); /*! Searches for other marble and exchanges their positions. Returns false if no other marble could be found. */ bool ExchangeMarbles (Actor *marble1); void GrabActor (Actor *a); void ReleaseActor (Actor *a); unsigned CountActorsOfKind (ActorID id); /*! Find all actors at most RANGE units away from CENTER. Returns false if none were found. */ bool GetActorsInRange (px::V2 center, double range, std::vector &actors); /*! Find all actors that are inside 'pos'. Returns false if none were found. */ bool GetActorsInsideField (const GridPos& pos, std::vector& actors); /*! Shatter all actors inside 'pos'. */ void ShatterActorsInsideField (const GridPos &pos); /* -------------------- Field -------------------- */ struct Field { // Variables Floor *floor; Item *item; Stone *stone; // Constructor and Destructor Field(); ~Field(); }; const Field *GetField (GridPos p); /* -------------------- Stones -------------------- */ void SetStone(GridPos p, Stone* st); void ReplaceStone(GridPos p, Stone *st); Stone *GetStone(GridPos p); Stone *YieldStone(GridPos p); void KillStone(GridPos p); void MoveStone(GridPos oldPos, GridPos newPos); /* -------------------- Items -------------------- */ void SetItem (GridPos p, Item* it); void SetItem (GridPos p, ItemID id); Item *GetItem (GridPos p); Item *YieldItem (GridPos p); void KillItem (GridPos p); /* -------------------- Floors -------------------- */ void SetFloor (GridPos p, Floor* st); Floor *GetFloor (GridPos p); void KillFloor (GridPos p); /* -------------------- Impulses -------------------- */ void addDelayedImpulse(const Impulse& impulse, double delay, const Stone *estimated_receiver); /* -------------------- Explosions -------------------- */ enum ExplosionType { EXPLOSION_DYNAMITE, EXPLOSION_BLACKBOMB, EXPLOSION_WHITEBOMB, EXPLOSION_BOMBSTONE, EXPLOSION_SPITTER, }; void SendExplosionEffect (GridPos p, ExplosionType type); /* -------------------- Creation/Definition of objects -------------------- */ Object *MakeObject (const char *kind); Floor *MakeFloor (const char *kind); Stone *MakeStone (const char *kind); Stone *MakeStone (StoneID id); Actor *MakeActor (const char *kind); Actor *MakeActor (ActorID id); void DisposeObject(Object *o); void DefineSimpleStone (const string &kind, const string &sound, int hollow, int glass); void DefineSimpleStoneMovable (const string &kind, const string &sound, int glass); void DefineSimpleFloor(const string &kind, double friction, double mousefactor); /* Register a new object. */ void Register (Object *obj); void Register (const string &kind, Object *obj); void Register (const string &kind, Floor *obj); void Register (const string &kind, Stone *obj); void RegisterStone (Stone *st); void RegisterActor (Actor *ac); void Register (const string &kind, Item *obj); void RegisterItem (Item *it); Item *MakeItem (const char *kind); Item *MakeItem (ItemID id); /* Shutdown object repository */ void Repos_Shutdown(); Object *GetObjectTemplate(const string &kind); /* Print information about all registered objects to stdout. */ void DumpObjectInfo(); } #endif