1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 #include "world.hh"
5 #include "body.hh"
6 #include "view.hh"
7 #include <stdlib.h>
8
World()9 World::World()
10 : _static_friction(0.2), _dynamic_friction(0.2),
11 _angular_friction(0.3), _angular_friction_2(1)
12 {
13 }
14
15 void
set_static_friction(double d)16 World::set_static_friction(double d)
17 {
18 _static_friction = d;
19 }
20
21 void
set_dynamic_friction(double d)22 World::set_dynamic_friction(double d)
23 {
24 _dynamic_friction = d;
25 }
26
27 void
set_angular_friction(double d)28 World::set_angular_friction(double d)
29 {
30 if (d < 0)
31 d = 0;
32 _angular_friction = d;
33 }
34
35 void
add(Body * b)36 World::add(Body *b)
37 {
38 _bodies.push_back(b);
39 b->embody(this);
40 if (b->movable())
41 _moving_bodies.push_back(b);
42 if (b->z_plane() > 0)
43 _collidable_bodies.push_back(b);
44 }
45
46 void
remove(Body * b)47 World::remove(Body *b)
48 {
49 for (int i = 0; i < _moving_bodies.size(); i++)
50 if (_moving_bodies[i] == b) {
51 _moving_bodies[i] = _moving_bodies.back();
52 _moving_bodies.pop_back();
53 break;
54 }
55 for (int i = 0; i < _collidable_bodies.size(); i++)
56 if (_collidable_bodies[i] == b) {
57 _collidable_bodies[i] = _collidable_bodies.back();
58 _collidable_bodies.pop_back();
59 break;
60 }
61 for (int i = 0; i < _bodies.size(); i++)
62 if (_bodies[i] == b) {
63 _bodies[i] = _bodies.back();
64 _bodies.pop_back();
65 break;
66 }
67 }
68
69 extern "C" {
70 static int
body_qsorter(const void * thunk1,const void * thunk2)71 body_qsorter(const void *thunk1, const void *thunk2)
72 {
73 const Body **b1 = (const Body **)thunk1;
74 const Body **b2 = (const Body **)thunk2;
75 return (*b1)->move_phase() - (*b2)->move_phase();
76 }
77 }
78
79 void
reset()80 World::reset()
81 {
82 for (int i = 0; i < _bodies.size(); i++)
83 _bodies[i]->reset();
84 if (_bodies.size())
85 qsort(&_bodies[0], _bodies.size(), sizeof(Body *), body_qsorter);
86 }
87
88 void
trail_snapshot()89 World::trail_snapshot()
90 {
91 for (int i = 0; i < _bodies.size(); i++)
92 _bodies[i]->trail_snapshot();
93 }
94
95 void
random_place(bool do_movable,bool do_stationary,View * view)96 World::random_place(bool do_movable, bool do_stationary, View *view)
97 {
98 Point ll = view->lower_left();
99 Point ur = view->upper_right();
100 Point delta = ur - ll;
101
102 for (int i = 0; i < _bodies.size(); i++)
103 if (_bodies[i]->movable() ? do_movable : do_stationary) {
104 Point p = ll;
105 p.x += ((double)rand() / RAND_MAX) * delta.x;
106 p.y += ((double)rand() / RAND_MAX) * delta.y;
107 double rotation = ((double)rand() / RAND_MAX) * 2*M_PI;
108 _bodies[i]->place(p, rotation);
109 }
110
111 reset();
112 }
113
114 void
draw(View * v) const115 World::draw(View *v) const
116 {
117 v->clear();
118 for (int i = 0; i < _bodies.size(); i++)
119 _bodies[i]->draw(v);
120 v->expose();
121 }
122
123 #define MOVE_TIME_QUANTUM 0.1
124 void
move() const125 World::move() const
126 {
127 for (int i = 0; i < _bodies.size(); i++)
128 _bodies[i]->move(MOVE_TIME_QUANTUM);
129 }
130
131 void
check_collisions() const132 World::check_collisions() const
133 {
134 int cs = _collidable_bodies.size();
135 if (cs) {
136 Body * const *cb = _collidable_bodies.begin();
137 for (int i = 0; i < cs - 1; i++)
138 for (int j = i + 1; j < cs; j++)
139 if (cb[i]->might_collide(cb[j]))
140 cb[i]->collide(cb[j]);
141 }
142 }
143