1 // Construo - A wire-frame construction gamee
2 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 #include <math.h>
18 #include "colors.hpp"
19 #include "particle_factory.hpp"
20 #include "controller.hpp"
21 #include "rect_collider.hpp"
22 #include "construo_error.hpp"
23
24 Collider*
duplicate() const25 RectCollider::duplicate() const
26 {
27 return new RectCollider(x1, y1, x2, y2);
28 }
29
RectCollider(lisp_object_t * cursor)30 RectCollider::RectCollider (lisp_object_t* cursor)
31 {
32 Vector2d pos1, pos2;
33
34 LispReader reader(cursor);
35 if (reader.read_vector("pos1", &pos1) == false
36 || reader.read_vector("pos2", &pos2) == false)
37 {
38 throw ConstruoError("RectCollider entry incomplete");
39 }
40
41 x1 = pos1.x;
42 y1 = pos1.y;
43 x2 = pos2.x;
44 y2 = pos2.y;
45 }
46
RectCollider(float x1_,float y1_,float x2_,float y2_)47 RectCollider::RectCollider (float x1_, float y1_, float x2_, float y2_)
48 : x1 (Math::min(x1_, x2_)),
49 y1 (Math::min(y1_, y2_)),
50 x2 (Math::max(x1_, x2_)),
51 y2 (Math::max(y1_, y2_))
52 {
53 }
54
55 bool
is_at(const Vector2d & pos)56 RectCollider::is_at (const Vector2d& pos)
57 {
58 return (x1 <= pos.x && x2 > pos.x
59 && y1 <= pos.y && y2 > pos.y);
60 }
61
62 Vector2d
get_pos()63 RectCollider::get_pos()
64 {
65 return Vector2d ((x1 + x2)/2.0f,
66 (y1 + y2)/2.0f);
67 }
68
69 void
set_pos(const Vector2d & pos)70 RectCollider::set_pos(const Vector2d& pos)
71 {
72 Vector2d center = get_pos();
73 x1 = x1 - center.x + pos.x;
74 x2 = x2 - center.x + pos.x;
75 y1 = y1 - center.y + pos.y;
76 y2 = y2 - center.y + pos.y;
77 }
78
79 void
bounce()80 RectCollider::bounce ()
81 {
82 ParticleFactory* particle_mgr = Controller::instance()->get_world()->get_particle_mgr();
83
84 float damp = 0.8;
85 for (ParticleFactory::ParticleIter i = particle_mgr->begin(); i != particle_mgr->end (); ++i)
86 {
87 Vector2d& pos = (*i)->pos;
88 Vector2d& velocity = (*i)->velocity;
89
90 if (pos.x > x1 && pos.x < x2
91 && pos.y > y1 && pos.y < y2)
92 {
93 float left_dist = pos.x - x1;
94 float right_dist = x2 - pos.x;
95
96 float top_dist = pos.y - y1;
97 float bottom_dist = y2 - pos.y;
98
99 if (left_dist < right_dist
100 && left_dist < top_dist
101 && left_dist < bottom_dist)
102 {
103 velocity.x = -fabs(velocity.x);
104 pos.x = x1;
105 }
106 else if (right_dist < left_dist
107 && right_dist < top_dist
108 && right_dist < bottom_dist)
109 {
110 velocity.x = fabs(velocity.x);
111 pos.x = x2;
112 }
113 else if (top_dist < left_dist
114 && top_dist < right_dist
115 && top_dist < bottom_dist)
116 {
117 velocity.y = -fabs(velocity.y);
118 pos.y = y1;
119 }
120 else
121 {
122 velocity.y = fabs(velocity.y);
123 pos.y = y2;
124 }
125 velocity *= damp;
126 }
127 }
128 }
129
130 void
draw(GraphicContext * gc)131 RectCollider::draw (GraphicContext* gc)
132 {
133 //std::cout << "Drawing collider" << std::endl;
134 gc->draw_fill_rect (x1, y1, x2, y2, Colors::rect_collider_bg);
135 gc->draw_rect (x1, y1, x2, y2, Colors::rect_collider_fg);
136 }
137
138 void
draw_highlight(GraphicContext * gc)139 RectCollider::draw_highlight (GraphicContext* gc)
140 {
141 //gc->draw_fill_rect (x1, y1, x2, y2, Colors::rect_collider_bg);
142 gc->draw_rect (x1, y1, x2, y2, Colors::selection_rect);
143 }
144
145 BoundingBox
get_bounding_box() const146 RectCollider::get_bounding_box() const
147 {
148 return BoundingBox(x1, y1, x2, y2);
149 }
150
151 lisp_object_t*
serialize()152 RectCollider::serialize()
153 {
154 LispWriter obj ("rect");
155 obj.write_vector ("pos1", Vector2d(x1, y1));
156 obj.write_vector ("pos2", Vector2d(x2, y2));
157 return obj.create_lisp ();
158 }
159
160 /* EOF */
161