00001 #ifndef H_SDLPP_PHYSICS
00002 #define H_SDLPP_PHYSICS
00003
00004 #include <sdlpp_common.h>
00005
00006 namespace SDLPP {
00007
00008 class BitRow
00009 {
00010 enum { BITS=8*sizeof(unsigned) };
00011 typedef std::vector<unsigned> base_vec;
00012 base_vec m_Data;
00013 int m_Size;
00014
00015 unsigned get_word(int i) const { if (i<0 || i>=int(m_Data.size())) return 0; return m_Data[i]; }
00016 unsigned get_word_at(int offset) const
00017 {
00018 int w=offset/BITS;
00019 int o=offset-(w*BITS);
00020 unsigned word=(get_word(w)>>o);
00021 if (o>0)
00022 {
00023 unsigned next=get_word(w+1);
00024 next<<=(BITS-o);
00025 word|=next;
00026 }
00027 return word;
00028 }
00029
00030 int get_first_one(unsigned u) const
00031 {
00032 for(int i=0;i<BITS && u;++i,u>>=1)
00033 if ((u&1)!=0) return i;
00034 return 0;
00035 }
00036 public:
00037 BitRow(int size)
00038 : m_Data((size+BITS-1)/BITS,0),
00039 m_Size(size)
00040 {}
00041 void set(int i, bool state=true)
00042 {
00043 if (i<0 || i>=m_Size) return;
00044 int wi=i/BITS;
00045 int oi=i-(wi*BITS);
00046 unsigned& word=m_Data[wi];
00047 unsigned value=(1<<oi);
00048 if (state) word|=value;
00049 else word&=~value;
00050 }
00051
00052 unsigned get_bits(int offset, int len) const
00053 {
00054 unsigned word=get_word_at(offset);
00055 unsigned mask=-1;
00056 mask <<= len;
00057 mask = ~mask;
00058 return word&mask;
00059 }
00060
00061 int test(const BitRow& br, int offset, int br_offset) const
00062 {
00063 if (offset<0) return br.test(*this,-offset,0);
00064 int len=Min(m_Size-offset,br.m_Size-br_offset);
00065 for(int i=0;i<len;i+=BITS)
00066 {
00067 unsigned w=get_word_at(i+offset);
00068 unsigned brw=br.get_word_at(i+br_offset);
00069 w&=brw;
00070 if (w) return i+get_first_one(w);
00071 }
00072 return -1;
00073 }
00074 };
00075
00076 class CollisionModel2D
00077 {
00078 typedef std::vector<BitRow> Grid;
00079 Grid m_Grid;
00080 iRect2 m_Rect;
00081
00082 const BitRow& get_row(int y) const
00083 {
00084 static const BitRow empty_row(64);
00085 if (y<0 || y>=int(m_Grid.size())) return empty_row;
00086 return m_Grid[y];
00087 }
00088
00089 public:
00090 CollisionModel2D() {}
00091 CollisionModel2D(Bitmap image);
00092 bool empty() const { return m_Grid.empty(); }
00093 bool test(const CollisionModel2D& o, iVec2& offset);
00094 unsigned get_bits(const iVec2& offset, int len) const;
00095 void build(Bitmap image);
00096 };
00097
00098
00099 class RigidBody2D : public GameObject
00100 {
00101 dVec2 m_Position;
00102 dVec2 m_Velocity;
00103 dVec2 m_Acceleration;
00104 double m_Mass;
00105 xstring m_Name;
00106
00107 dVec2 get_collision_normal(CollisionModel2D& cm, const iVec2& offset);
00108 public:
00109 RigidBody2D(double mass=0) : m_Mass(mass) {}
00110
00111 virtual void interact(RigidBody2D* o, int dt);
00112 virtual iRect2 get_rect() const = 0;
00113 virtual bool is_collidable() const { return true; }
00114 virtual CollisionModel2D& get_col_model() = 0;
00115 virtual xstring get_flag(const xstring& flag) = 0;
00116 virtual const xstring& get(const xstring& property) const = 0;
00117 virtual void handle_collision(RigidBody2D* o) {}
00118 virtual bool advance(int dt)
00119 {
00120 double DT=dt*0.001;
00121 m_Velocity+=(m_Acceleration*DT);
00122 m_Position+=m_Velocity*DT;
00123 return true;
00124 }
00125
00126 double get_mass() const { return m_Mass; }
00127 void set_mass(double m) { m_Mass=m; }
00128 iVec2 get_position() const { return iVec2(int(m_Position.x),int(m_Position.y)); }
00129 const dVec2& get_velocity() const { return m_Velocity; }
00130 const dVec2& get_acceleration() const { return m_Acceleration; }
00131 void offset_position(const dVec2& dp)
00132 {
00133 m_Position+=dp;
00134 }
00135 void set_position(const iVec2& p)
00136 {
00137 m_Position=dVec2(p.x,p.y);
00138 }
00139 void set_velocity(const dVec2& v)
00140 {
00141 m_Velocity=v;
00142 }
00143 void set_velocity(const dVec2& direction, double speed)
00144 {
00145 set_velocity(direction.normalized()*speed);
00146 }
00147 void set_acceleration(const dVec2& a)
00148 {
00149 m_Acceleration=a;
00150 }
00151 void set_acceleration(const dVec2& direction, double magnitude)
00152 {
00153 set_acceleration(direction.normalized()*magnitude);
00154 }
00155
00156 void set_name(const xstring& name) { m_Name=name; }
00157 const xstring& get_name() const { return m_Name; }
00158 };
00159
00160 class FrameTimer
00161 {
00162 int m_LastTicks;
00163 public:
00164 FrameTimer() : m_LastTicks(SDL_GetTicks()) {}
00165 int calc_dt()
00166 {
00167 int cur=SDL_GetTicks();
00168 int dt=cur-m_LastTicks;
00169 m_LastTicks=cur;
00170 return dt;
00171 }
00172 };
00173
00174
00175 }
00176
00177 #endif // H_SDLPP_PHYSICS
00178