00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <math.h>
00021 #include "colors.hxx"
00022 #include "particle_factory.hxx"
00023 #include "controller.hxx"
00024 #include "rect_collider.hxx"
00025 #include "construo_error.hxx"
00026
00027 Collider*
00028 RectCollider::duplicate() const
00029 {
00030 return new RectCollider(x1, y1, x2, y2);
00031 }
00032
00033 RectCollider::RectCollider (lisp_object_t* cursor)
00034 {
00035 Vector2d pos1, pos2;
00036
00037 LispReader reader(cursor);
00038 if (reader.read_vector("pos1", &pos1) == false
00039 || reader.read_vector("pos2", &pos2) == false)
00040 {
00041 throw ConstruoError("RectCollider entry incomplete");
00042 }
00043
00044 x1 = pos1.x;
00045 y1 = pos1.y;
00046 x2 = pos2.x;
00047 y2 = pos2.y;
00048 }
00049
00050 RectCollider::RectCollider (float x1_, float y1_, float x2_, float y2_)
00051 : x1 (x1_), y1 (y1_), x2 (x2_), y2 (y2_)
00052 {
00053 }
00054
00055 bool
00056 RectCollider::is_at (const Vector2d& pos)
00057 {
00058 return (x1 <= pos.x && x2 > pos.x
00059 && y1 <= pos.y && y2 > pos.y);
00060 }
00061
00062 Vector2d
00063 RectCollider::get_pos()
00064 {
00065 return Vector2d ((x1 + x2)/2.0f,
00066 (y1 + y2)/2.0f);
00067 }
00068
00069 void
00070 RectCollider::set_pos(const Vector2d& pos)
00071 {
00072 Vector2d center = get_pos();
00073 x1 = x1 - center.x + pos.x;
00074 x2 = x2 - center.x + pos.x;
00075 y1 = y1 - center.y + pos.y;
00076 y2 = y2 - center.y + pos.y;
00077 }
00078
00079 void
00080 RectCollider::bounce ()
00081 {
00082 ParticleFactory* particle_mgr = Controller::instance()->get_world()->get_particle_mgr();
00083
00084 float damp = 0.8;
00085 for (ParticleFactory::ParticleIter i = particle_mgr->begin(); i != particle_mgr->end (); ++i)
00086 {
00087 Vector2d& pos = (*i)->pos;
00088 Vector2d& velocity = (*i)->velocity;
00089
00090 if (pos.x > x1 && pos.x < x2
00091 && pos.y > y1 && pos.y < y2)
00092 {
00093 float left_dist = pos.x - x1;
00094 float right_dist = x2 - pos.x;
00095
00096 float top_dist = pos.y - y1;
00097 float bottom_dist = y2 - pos.y;
00098
00099 if (left_dist < right_dist
00100 && left_dist < top_dist
00101 && left_dist < bottom_dist)
00102 {
00103 velocity.x = -fabs(velocity.x);
00104 pos.x = x1;
00105 }
00106 else if (right_dist < left_dist
00107 && right_dist < top_dist
00108 && right_dist < bottom_dist)
00109 {
00110 velocity.x = fabs(velocity.x);
00111 pos.x = x2;
00112 }
00113 else if (top_dist < left_dist
00114 && top_dist < right_dist
00115 && top_dist < bottom_dist)
00116 {
00117 velocity.y = -fabs(velocity.y);
00118 pos.y = y1;
00119 }
00120 else
00121 {
00122 velocity.y = fabs(velocity.y);
00123 pos.y = y2;
00124 }
00125 velocity *= damp;
00126 }
00127 }
00128 }
00129
00130 void
00131 RectCollider::draw (GraphicContext* gc)
00132 {
00133
00134 gc->draw_fill_rect (x1, y1, x2, y2, Colors::rect_collider_bg);
00135 gc->draw_rect (x1, y1, x2, y2, Colors::rect_collider_fg);
00136 }
00137
00138 void
00139 RectCollider::draw_highlight (GraphicContext* gc)
00140 {
00141
00142 gc->draw_rect (x1, y1, x2, y2, Colors::selection_rect);
00143 }
00144
00145 lisp_object_t*
00146 RectCollider::serialize()
00147 {
00148 LispWriter obj ("rect");
00149 obj.write_vector ("pos1", Vector2d(x1, y1));
00150 obj.write_vector ("pos2", Vector2d(x2, y2));
00151 return obj.create_lisp ();
00152 }
00153
00154