1 /*
2 Copyright (C) 2009 Facundo Domínguez
3
4 This file is part of Spacejunk.
5
6 Spacejunk is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Foobar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Foobar. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "simulation.h"
21 #include "collisionengine.h"
22 #include "functionexts.h"
23
24 using namespace std;
25
Simulation(const PlayerState & ps,const list<int> & onStep)26 Simulation::Simulation(const PlayerState & ps,const list<int> &onStep)
27 : physic(ps),tevents(this),onStep(onStep),colPrecision(35),deltaCol(0) {
28 ce=new CollisionEngine<PhysicBody,Simulation>(-20000,-20000,20000,20000,this);
29 for (vector<PhysicBody*>::iterator i=physic.bodies.begin();
30 i!=physic.bodies.end();i++)
31 if (*i) ce->add(*i);
32 };
33
34
35 class Collision : public Event {
36 public:
37 Simulation * sim;
38 int c1,c2;
39 Vector2d normal;
40
Collision()41 Collision() : sim(NULL),c1(-1),c2(-1),normal(0) {};
Collision(Simulation * sim,int c1,int c2,const Vector2d & normal)42 Collision(Simulation * sim,int c1,int c2,const Vector2d & normal):
43 sim(sim),c1(c1),c2(c2),normal(normal) {};
setQueue(Simulation * sim,const TimerId & tid)44 void setQueue(Simulation * sim,const TimerId & tid) {}
45 int fire(Simulation * sim);
cancel(Simulation * sim)46 void cancel(Simulation * sim) {}
47 };
48
49
fire(Simulation * sim)50 int Collision::fire(Simulation * sim) {
51 PhysicBody * b1=sim->physic.bodies[c1];
52 PhysicBody * b2=sim->physic.bodies[c2];
53 if (!b1 || !b2) return 0;
54
55 b1->testForCollision();
56 b2->testForCollision();
57
58 for (EventListenerList<SimCollisionListener*>::iterator i=sim->collisionListeners.begin();i!=sim->collisionListeners.end();i++)
59 (*i)->evtCollision(sim,b1,b2,normal);
60 return 0;
61 }
62
63
handle_col(Simulation * sim,PhysicBody * c1,PhysicBody * c2,real t,const Vector2d & normal)64 int handle_col(Simulation * sim,PhysicBody * c1,PhysicBody * c2,real t,const Vector2d & normal) {
65 int key=(int)(t*sim->physic.getInterpolatedTime());
66 sim->coldata.push_front(make_pair(key,Collision(sim,c1->id,c2->id,normal)));
67 return 0;
68 };
69
handle_collisions()70 int Simulation::handle_collisions() {
71 ce->step(wrap_collision_handler<PhysicBody,Simulation,handle_col>);
72 if (!coldata.empty()) {
73 int t=physic.unstep();
74 tevents.clock-=t;
75 for (list<std::pair<int,Collision> >::iterator i=coldata.begin();coldata.end()!=i;i++) {
76 tevents.set(i->first,i->second);
77 }
78 coldata.clear();
79 return t;
80 }
81 return 0;
82 };
83
step(int delta)84 void Simulation::step(int delta) {
85 step(delta,null);
86 };
87
clear()88 void Simulation::clear() {
89 for (vector<PhysicBody*>::iterator i=physic.bodies.begin();i!=physic.bodies.end();i++) {
90 if (!*i) continue;
91 deleteBody((*i)->id);
92 }
93 physic.clear();
94 };
95
purge()96 void Simulation::purge() {
97 for (vector<PhysicBody*>::iterator i=physic.bodies.begin();i!=physic.bodies.end();i++) {
98 if (!*i) continue;
99 PhysicBody * pb=*i;
100 deleteBody_without_event((*i)->id);
101 delete pb;
102 }
103 physic.clear();
104 tevents.clear();
105 };
106
addBody(PhysicBody * c)107 void Simulation::addBody(PhysicBody * c) {
108 physic.addBody(c);
109 ce->add(c);
110 }
111
addBody(int id,PhysicBody * c)112 void Simulation::addBody(int id,PhysicBody * c) {
113 physic.addBody(id,c);
114 ce->add(c);
115 }
116
deleteBody(int id)117 void Simulation::deleteBody(int id) {
118 if (id<0 || !physic.bodies[id]) return;
119
120 for (EventListenerList<SimDeletionListener*>::iterator i=deletionListeners.begin();i!=deletionListeners.end();i++)
121 (*i)->evtDeleteBody(this,id);
122
123 deleteBody_without_event(id);
124 }
125
deleteBody_without_event(int id)126 void Simulation::deleteBody_without_event(int id) {
127 ce->deleteBody(physic.bodies[id]);
128 physic.deleteBody(id);
129 }
130
~Simulation()131 Simulation::~Simulation() {
132 delete ce;
133 };
134
operator =(const Simulation & orig)135 void Simulation::operator = (const Simulation & orig) {
136 purge();
137
138 physic=orig.physic;
139 for (vector<PhysicBody*>::const_iterator i=physic.bodies.begin();i!=physic.bodies.end();i++) {
140 if (!*i) continue;
141 ce->add(*i);
142 }
143
144 colPrecision=orig.colPrecision;
145 deltaCol=orig.deltaCol;
146 orig.tevents.copy(tevents);
147 };
148