author | ekku |
Thu, 20 Nov 2008 21:22:03 +0000 | |
changeset 82 | 8f60abd6a083 |
parent 81 | 4a91cf6f5cc7 |
child 83 | cbba9729e92b |
permissions | -rw-r--r-- |
58 | 1 |
|
2 |
#include "Physics.hh" |
|
3 |
#include "Engine.hh" |
|
4 |
||
45
32c876923cac
I added a couple of lines. This still clearly is not going to work in this state.
saiam
parents:
44
diff
changeset
|
5 |
#include <algorithm> |
50
9e1a6506f5a1
some rough-handed code modifications towards a newer, better, working Physics
terom
parents:
49
diff
changeset
|
6 |
#include <functional> |
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
7 |
#include <cmath> |
45
32c876923cac
I added a couple of lines. This still clearly is not going to work in this state.
saiam
parents:
44
diff
changeset
|
8 |
|
60 | 9 |
PhysicsWorld::PhysicsWorld (Vector gravity, Vector dimensions) |
79 | 10 |
: tick_timer(PHYSICS_TICK_MS), gravity(gravity), dimensions(dimensions), terrain(dimensions.x, std::vector<TerrainType>(dimensions.y, EMPTY)) { |
50
9e1a6506f5a1
some rough-handed code modifications towards a newer, better, working Physics
terom
parents:
49
diff
changeset
|
11 |
|
54 | 12 |
slots.connect(tick_timer.sig_timer(), this, &PhysicsWorld::tick); |
50
9e1a6506f5a1
some rough-handed code modifications towards a newer, better, working Physics
terom
parents:
49
diff
changeset
|
13 |
tick_timer.enable(); |
9e1a6506f5a1
some rough-handed code modifications towards a newer, better, working Physics
terom
parents:
49
diff
changeset
|
14 |
} |
44 | 15 |
|
16 |
void PhysicsWorld::addObject (PhysicsObject *object) { |
|
47 | 17 |
objects.push_back(object); |
44 | 18 |
} |
19 |
||
20 |
void PhysicsWorld::tick () { |
|
60 | 21 |
// Engine::log(DEBUG, "physics.apply_force") << "*tick*"; |
58 | 22 |
|
76 | 23 |
for (std::vector<PhysicsObject*>::iterator i = objects.begin(); i != objects.end(); i++) { |
24 |
(*i)->tick(); |
|
25 |
} |
|
48
fa1da22db8a0
It looks like physics could now work, but I doubt it...
saiam
parents:
47
diff
changeset
|
26 |
} |
fa1da22db8a0
It looks like physics could now work, but I doubt it...
saiam
parents:
47
diff
changeset
|
27 |
|
60 | 28 |
PhysicsObject::PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity) |
29 |
: world(world), mass(mass), position(position), velocity(velocity) { |
|
30 |
||
31 |
world.addObject(this); |
|
32 |
} |
|
44 | 33 |
|
34 |
void PhysicsObject::updatePosition () { |
|
35 |
||
47 | 36 |
// Calculate gravity's influence on the velocity vector |
60 | 37 |
this->velocity += world.gravity * (PHYSICS_TICK_MS / 1000.0); |
47 | 38 |
|
60 | 39 |
Vector newPosition = position + velocity * (PHYSICS_TICK_MS / 1000.0); |
44 | 40 |
|
47 | 41 |
//TODO Handle the object as a square or a polygon |
58 | 42 |
|
80 | 43 |
bool collided = false; |
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
44 |
|
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
45 |
//goes 1 unit forward every step and check if has hit anything |
80 | 46 |
Vector unitVector = (newPosition-position) / (newPosition-position).length(); |
82 | 47 |
|
48 |
Vector tmpVector = position; |
|
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
49 |
Vector reached = position; |
82 | 50 |
int steps = (int) (newPosition-position).length(); |
51 |
for(int i = 0; i < steps; i++) { |
|
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
52 |
tmpVector += unitVector; |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
53 |
if(world.getType(tmpVector) != EMPTY) { |
80 | 54 |
//Engine::log(DEBUG, "physics.update_position") << "hit something"; |
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
55 |
// Then we have hit something |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
56 |
reached = position + unitVector*(i-1); |
80 | 57 |
collided = true; |
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
58 |
break; |
80 | 59 |
} else { |
60 |
//Engine::log(DEBUG, "physics.update_position") << "didnt hit"; |
|
61 |
} |
|
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
62 |
} |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
63 |
|
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
64 |
// In case of some float error |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
65 |
if(!collided) { |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
66 |
if(world.getType(newPosition)) { |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
67 |
// There was error, and there is ground |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
68 |
newPosition = tmpVector; |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
69 |
} else { |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
70 |
// This means everything was ok, so no need to do anything |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
71 |
} |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
72 |
} else { |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
73 |
newPosition = reached; |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
74 |
this->velocity = Vector(0, 0); |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
75 |
//TODO: it shouldn't just stop on collision |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
76 |
} |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
77 |
this->position = newPosition; |
44 | 78 |
} |
79 |
||
73 | 80 |
bool PhysicsWorld::collided (Vector oldPos, Vector newPos) { |
76 | 81 |
int deltaX = oldPos.x - newPos.x; |
82 |
int deltaY = oldPos.y - newPos.y; |
|
83 |
double distance = sqrt(deltaX * deltaX + deltaY * deltaY); |
|
79 | 84 |
double xInc = deltaX / distance; |
85 |
double yInc = deltaY / distance; |
|
73 | 86 |
double currentX = oldPos.x; |
87 |
double currentY = oldPos.y; |
|
88 |
||
76 | 89 |
// This implementation is bit slow since it checks some squares twice. |
73 | 90 |
for(unsigned int i = 1; i < distance; i++) { |
76 | 91 |
currentX += xInc; |
92 |
currentY += yInc; |
|
93 |
if(terrain[(int)currentX][(int)currentY] != EMPTY) |
|
79 | 94 |
return true; |
76 | 95 |
} |
79 | 96 |
return false; |
73 | 97 |
} |
98 |
||
79 | 99 |
void PhysicsObject::integrate(Vector force, TimeMS dt) { |
70 | 100 |
// TODO |
101 |
} |
|
102 |
||
79 | 103 |
void PhysicsObject::applyForce (Vector force, TimeMS dt) { |
58 | 104 |
Vector oldVelocity = velocity; |
105 |
||
60 | 106 |
this->velocity += force * dt / 1000 / mass; // The last factor denotes the time. |
47 | 107 |
// It should be scaled somehow. |
58 | 108 |
|
60 | 109 |
// Engine::log(DEBUG, "physics.apply_force") << "force=" << force << ", velocity " << oldVelocity << " -> " << velocity; |
44 | 110 |
} |
111 |
||
60 | 112 |
void PhysicsObject::updatePhysics (Vector position, Vector velocity) { |
47 | 113 |
this->position = position; |
114 |
this->velocity = velocity; |
|
44 | 115 |
} |
116 |
||
117 |
Vector PhysicsObject::getPosition () { |
|
47 | 118 |
return this->position; |
44 | 119 |
} |
120 |
||
121 |
void PhysicsObject::tick () { |
|
47 | 122 |
this->updatePosition(); |
44 | 123 |
} |
124 |
||
75 | 125 |
/** |
126 |
* simple random map generation |
|
127 |
* first fills whole level with dirt |
|
128 |
* then randomizes circles of empty or rock |
|
129 |
* @param seed - seed number for random number generator |
|
130 |
*/ |
|
79 | 131 |
void PhysicsWorld::generateTerrain(int seed) { |
75 | 132 |
// generating should use own random number generator, but didn't find easily how that is done |
133 |
srand(seed); |
|
134 |
||
135 |
// some constants to control random generation |
|
136 |
const int min_range = 10; |
|
137 |
const int max_range = 40; |
|
79 | 138 |
const int num = 0; |
75 | 139 |
const int rock_rarity = 4; // 1 / rock_rarity will be rock circle |
140 |
||
141 |
// loops for amount of circles |
|
142 |
for(int i = 0; i < num; i++) { |
|
143 |
// information of new circle |
|
79 | 144 |
int midx = rand()%(int)dimensions.x; |
145 |
int midy = rand()%(int)dimensions.y; |
|
146 |
||
147 |
// put first circle in the middle of the cave |
|
148 |
// so that we have some area we can certainly spawn into |
|
149 |
if(i == 0) { |
|
150 |
midx = dimensions.x / 2; |
|
151 |
midy = dimensions.y / 2; |
|
152 |
} |
|
153 |
||
75 | 154 |
int range = rand()%(max_range-min_range)+min_range; |
155 |
TerrainType type = EMPTY; |
|
156 |
if(rand()%rock_rarity == 0) { |
|
157 |
type = ROCK; |
|
158 |
} |
|
159 |
// loops for every pixel of circle |
|
79 | 160 |
for(int x = std::max(0, midx-range); x < std::min((int)dimensions.x, midx+range); x++) { |
161 |
for(int y = std::max(0, midy-range); y < std::min((int)dimensions.y, midy+range); y++) { |
|
75 | 162 |
if(x*x+y*y < range*range) { |
163 |
// and sets it to type |
|
164 |
terrain[x][y] = type; |
|
165 |
} |
|
166 |
} |
|
167 |
} |
|
168 |
} |
|
169 |
} |
|
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
170 |
|
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
171 |
/** |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
172 |
* Returns terrainType in given tile. ROCK if tile is out of area |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
173 |
* @param pos - coordinate of tile |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
174 |
*/ |
79 | 175 |
TerrainType PhysicsWorld::getType(Vector pos) const { |
77
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
176 |
int x = (int)(pos.x); |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
177 |
int y = (int)(pos.y); |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
178 |
if(x < 0 || y < 0 || x >= dimensions.x || y >= dimensions.y) { |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
179 |
return ROCK; |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
180 |
} |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
181 |
return terrain[x][y]; |
98dc9008d15f
changed collision detection, remove old if content with new
nireco
parents:
76
diff
changeset
|
182 |
} |