1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
// physics.cpp: no physics books were hurt nor consulted in the construction of
// this code. All physics computations and constants were invented on the fly
// and simply tweaked until they "felt right", and have no basis in reality.
// Collision detection is simplistic but very robust (uses discrete steps at
// fixed fps).
#include "cube.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "MapModelInfo.h"
// collide with player or monster
static bool
plcollide(
DynamicEntity *d, DynamicEntity *o, float *headspace, float *hi, float *lo)
{
if (o.state != CS_ALIVE)
return true;
const float r = o.radius + d.radius;
if (fabs(o.origin.x - d.origin.x) < r &&
fabs(o.origin.y - d.origin.y) < r) {
if (d.origin.z - d.eyeHeight < o.origin.z - o.eyeHeight) {
if (o.origin.z - o.eyeHeight < *hi)
*hi = o.origin.z - o.eyeHeight - 1;
} else if (o.origin.z + o.aboveEye > *lo)
*lo = o.origin.z + o.aboveEye + 1;
if (fabs(o.origin.z - d.origin.z) < o.aboveEye + d.eyeHeight)
return false;
if (d.monsterState)
return false; // hack
//
*headspace = d.origin.z - o.origin.z - o.aboveEye - d.eyeHeight;
if (*headspace < 0)
*headspace = 10;
}
return true;
}
|
>
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
// physics.cpp: no physics books were hurt nor consulted in the construction of
// this code. All physics computations and constants were invented on the fly
// and simply tweaked until they "felt right", and have no basis in reality.
// Collision detection is simplistic but very robust (uses discrete steps at
// fixed fps).
#include "cube.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "MapModelInfo.h"
#import "Monster.h"
// collide with player or monster
static bool
plcollide(
DynamicEntity *d, DynamicEntity *o, float *headspace, float *hi, float *lo)
{
if (o.state != CS_ALIVE)
return true;
const float r = o.radius + d.radius;
if (fabs(o.origin.x - d.origin.x) < r &&
fabs(o.origin.y - d.origin.y) < r) {
if (d.origin.z - d.eyeHeight < o.origin.z - o.eyeHeight) {
if (o.origin.z - o.eyeHeight < *hi)
*hi = o.origin.z - o.eyeHeight - 1;
} else if (o.origin.z + o.aboveEye > *lo)
*lo = o.origin.z + o.aboveEye + 1;
if (fabs(o.origin.z - d.origin.z) < o.aboveEye + d.eyeHeight)
return false;
if ([d isKindOfClass:Monster.class])
return false; // hack
*headspace = d.origin.z - o.origin.z - o.aboveEye - d.eyeHeight;
if (*headspace < 0)
*headspace = 10;
}
return true;
}
|
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
const float fy2 = d.origin.y + d.radius;
const int x1 = fast_f2nat(fx1);
const int y1 = fast_f2nat(fy1);
const int x2 = fast_f2nat(fx2);
const int y2 = fast_f2nat(fy2);
float hi = 127, lo = -128;
// big monsters are afraid of heights, unless angry :)
float minfloor = (d.monsterState && !spawn && d.health > 100)
? d.origin.z - d.eyeHeight - 4.5f
: -1000.0f;
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
// collide with map
if (OUTBORD(x, y))
return false;
struct sqr *s = S(x, y);
|
|
>
|
|
|
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
const float fy2 = d.origin.y + d.radius;
const int x1 = fast_f2nat(fx1);
const int y1 = fast_f2nat(fy1);
const int x2 = fast_f2nat(fx2);
const int y2 = fast_f2nat(fy2);
float hi = 127, lo = -128;
// big monsters are afraid of heights, unless angry :)
float minfloor =
([d isKindOfClass:Monster.class] && !spawn && d.health > 100
? d.origin.z - d.eyeHeight - 4.5f
: -1000.0f);
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
// collide with map
if (OUTBORD(x, y))
return false;
struct sqr *s = S(x, y);
|
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
if (d != player1)
if (!plcollide(d, player1, &headspace, &hi, &lo))
return false;
// this loop can be a performance bottleneck with many monster on a slow
// cpu, should replace with a blockmap but seems mostly fast enough
for (DynamicEntity *monster in getmonsters())
if (!vreject(d.origin, monster.origin, 7.0f) && d != monster &&
!plcollide(d, monster, &headspace, &hi, &lo))
return false;
headspace -= 0.01f;
mmcollide(d, &hi, &lo); // collide with map models
|
|
|
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
if (d != player1)
if (!plcollide(d, player1, &headspace, &hi, &lo))
return false;
// this loop can be a performance bottleneck with many monster on a slow
// cpu, should replace with a blockmap but seems mostly fast enough
for (Monster *monster in Monster.monsters)
if (!vreject(d.origin, monster.origin, 7.0f) && d != monster &&
!plcollide(d, monster, &headspace, &hi, &lo))
return false;
headspace -= 0.01f;
mmcollide(d, &hi, &lo); // collide with map models
|
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
// correct water feel
if (water)
pl.velocity = OFMakeVector3D(
pl.velocity.x / 8,
pl.velocity.y / 8, pl.velocity.z);
if (local)
playsoundc(S_JUMP);
else if (pl.monsterState) {
OFVector3D loc = pl.origin;
playsound(S_JUMP, &loc);
}
} else if (pl.timeInAir > 800) {
// if we land after long time must have been a
// high jump, make thud sound
if (local)
playsoundc(S_LAND);
else if (pl.monsterState) {
OFVector3D loc = pl.origin;
playsound(S_LAND, &loc);
}
}
pl.timeInAir = 0;
} else
|
|
|
|
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
// correct water feel
if (water)
pl.velocity = OFMakeVector3D(
pl.velocity.x / 8,
pl.velocity.y / 8, pl.velocity.z);
if (local)
playsoundc(S_JUMP);
else if ([pl isKindOfClass:Monster.class]) {
OFVector3D loc = pl.origin;
playsound(S_JUMP, &loc);
}
} else if (pl.timeInAir > 800) {
// if we land after long time must have been a
// high jump, make thud sound
if (local)
playsoundc(S_LAND);
else if ([pl isKindOfClass:Monster.class]) {
OFVector3D loc = pl.origin;
playsound(S_LAND, &loc);
}
}
pl.timeInAir = 0;
} else
|