Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Scene/Collision.cpp
1163 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
#if RETRO_REV0U
6
#include "Legacy/CollisionLegacy.cpp"
7
#endif
8
9
#if RETRO_REV0U
10
// Not sure why its 8.0 in v5U, it's 4.0 in v5 and v4, the "fix" is here since 8.0 causes issues with chibi due to his lil hitbox
11
#if RETRO_USE_ORIGINAL_CODE
12
#define COLLISION_OFFSET (TO_FIXED(8))
13
#else
14
#define COLLISION_OFFSET (TO_FIXED(4))
15
#endif
16
#else
17
#define COLLISION_OFFSET (TO_FIXED(4))
18
#endif
19
20
int32 RSDK::collisionTolerance = 0;
21
#if RETRO_REV0U
22
bool32 RSDK::useCollisionOffset = false;
23
#else
24
int32 RSDK::collisionOffset = 0;
25
#endif
26
int32 RSDK::collisionMaskAir = 0;
27
28
Hitbox RSDK::collisionOuter = { 0, 0, 0, 0 };
29
Hitbox RSDK::collisionInner = { 0, 0, 0, 0 };
30
31
Entity *RSDK::collisionEntity = NULL;
32
33
CollisionSensor RSDK::sensors[6];
34
35
#if RETRO_REV0U
36
#if RETRO_USE_ORIGINAL_CODE
37
// not sure why it's 24 here... it was 14 in all prev RSDK versions, maybe a mistake???
38
int32 RSDK::collisionMinimumDistance = TO_FIXED(24);
39
#else
40
int32 RSDK::collisionMinimumDistance = TO_FIXED(14);
41
#endif
42
43
uint8 RSDK::lowCollisionTolerance = 8;
44
uint8 RSDK::highCollisionTolerance = 14;
45
46
uint8 RSDK::floorAngleTolerance = 0x20;
47
uint8 RSDK::wallAngleTolerance = 0x20;
48
uint8 RSDK::roofAngleTolerance = 0x20;
49
#else
50
#define collisionMinimumDistance (14)
51
52
#define lowCollisionTolerance (8)
53
#define highCollisionTolerance (15)
54
55
#define floorAngleTolerance (0x20)
56
#define wallAngleTolerance (0x20)
57
#define roofAngleTolerance (0x20)
58
#endif
59
60
#if !RETRO_USE_ORIGINAL_CODE
61
bool32 RSDK::showHitboxes = false;
62
63
int32 RSDK::debugHitboxCount = 0;
64
DebugHitboxInfo RSDK::debugHitboxList[DEBUG_HITBOX_COUNT];
65
66
int32 RSDK::AddDebugHitbox(uint8 type, uint8 dir, Entity *entity, Hitbox *hitbox)
67
{
68
int32 i = 0;
69
for (; i < debugHitboxCount; ++i) {
70
if (debugHitboxList[i].hitbox.left == hitbox->left && debugHitboxList[i].hitbox.top == hitbox->top
71
&& debugHitboxList[i].hitbox.right == hitbox->right && debugHitboxList[i].hitbox.bottom == hitbox->bottom
72
&& debugHitboxList[i].pos.x == entity->position.x && debugHitboxList[i].pos.y == entity->position.y
73
&& debugHitboxList[i].entity == entity) {
74
return i;
75
}
76
}
77
78
if (i < DEBUG_HITBOX_COUNT) {
79
debugHitboxList[i].type = type;
80
debugHitboxList[i].entity = entity;
81
debugHitboxList[i].collision = 0;
82
debugHitboxList[i].hitbox.left = hitbox->left;
83
debugHitboxList[i].hitbox.top = hitbox->top;
84
debugHitboxList[i].hitbox.right = hitbox->right;
85
debugHitboxList[i].hitbox.bottom = hitbox->bottom;
86
debugHitboxList[i].pos.x = entity->position.x;
87
debugHitboxList[i].pos.y = entity->position.y;
88
89
if ((dir & FLIP_X) == FLIP_X) {
90
int32 store = -debugHitboxList[i].hitbox.left;
91
debugHitboxList[i].hitbox.left = -debugHitboxList[i].hitbox.right;
92
debugHitboxList[i].hitbox.right = store;
93
}
94
if ((dir & FLIP_Y) == FLIP_Y) {
95
int32 store = -debugHitboxList[i].hitbox.top;
96
debugHitboxList[i].hitbox.top = -debugHitboxList[i].hitbox.bottom;
97
debugHitboxList[i].hitbox.bottom = store;
98
}
99
100
int32 id = debugHitboxCount;
101
debugHitboxCount++;
102
return id;
103
}
104
105
return -1;
106
}
107
#endif
108
109
#if RETRO_REV0U || RETRO_USE_MOD_LOADER
110
void RSDK::CopyCollisionMask(uint16 dst, uint16 src, uint8 cPlane, uint8 cMode)
111
{
112
CollisionMask *srcMask = NULL;
113
CollisionMask *dstMask = NULL;
114
115
switch (cMode) {
116
default: break;
117
118
case CMODE_FLOOR:
119
srcMask = &collisionMasks[cPlane][src & 0x3FF];
120
dstMask = &collisionMasks[cPlane][dst & 0x3FF];
121
tileInfo[cPlane][dst & 0x3FF].floorAngle = tileInfo[cPlane][src & 0x3FF].floorAngle;
122
memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);
123
124
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];
125
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];
126
tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].floorAngle;
127
memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);
128
129
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];
130
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];
131
tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].floorAngle;
132
memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);
133
134
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];
135
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];
136
tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].floorAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].floorAngle;
137
memcpy(dstMask->floorMasks, srcMask->floorMasks, sizeof(uint8) * TILE_SIZE);
138
break;
139
140
case CMODE_LWALL:
141
srcMask = &collisionMasks[cPlane][src & 0x3FF];
142
dstMask = &collisionMasks[cPlane][dst & 0x3FF];
143
tileInfo[cPlane][dst & 0x3FF].lWallAngle = tileInfo[cPlane][src & 0x3FF].lWallAngle;
144
memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);
145
146
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];
147
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];
148
tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].lWallAngle;
149
memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);
150
151
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];
152
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];
153
tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].lWallAngle;
154
memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);
155
156
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];
157
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];
158
tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].lWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].lWallAngle;
159
memcpy(dstMask->lWallMasks, srcMask->lWallMasks, sizeof(uint8) * TILE_SIZE);
160
break;
161
162
case CMODE_ROOF:
163
srcMask = &collisionMasks[cPlane][src & 0x3FF];
164
dstMask = &collisionMasks[cPlane][dst & 0x3FF];
165
tileInfo[cPlane][dst & 0x3FF].roofAngle = tileInfo[cPlane][src & 0x3FF].roofAngle;
166
memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);
167
168
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];
169
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];
170
tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].roofAngle;
171
memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);
172
173
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];
174
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];
175
tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].roofAngle;
176
memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);
177
178
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];
179
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];
180
tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].roofAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].roofAngle;
181
memcpy(dstMask->roofMasks, srcMask->roofMasks, sizeof(uint8) * TILE_SIZE);
182
break;
183
184
case CMODE_RWALL:
185
srcMask = &collisionMasks[cPlane][src & 0x3FF];
186
dstMask = &collisionMasks[cPlane][dst & 0x3FF];
187
tileInfo[cPlane][dst & 0x3FF].rWallAngle = tileInfo[cPlane][src & 0x3FF].rWallAngle;
188
memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);
189
190
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_X];
191
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_X];
192
tileInfo[cPlane][(dst & 0x3FF) * FLIP_X].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_X].rWallAngle;
193
memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);
194
195
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_Y];
196
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_Y];
197
tileInfo[cPlane][(dst & 0x3FF) * FLIP_Y].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_Y].rWallAngle;
198
memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);
199
200
srcMask = &collisionMasks[cPlane][(src & 0x3FF) * FLIP_XY];
201
dstMask = &collisionMasks[cPlane][(dst & 0x3FF) * FLIP_XY];
202
tileInfo[cPlane][(dst & 0x3FF) * FLIP_XY].rWallAngle = tileInfo[cPlane][(src & 0x3FF) * FLIP_XY].rWallAngle;
203
memcpy(dstMask->rWallMasks, srcMask->rWallMasks, sizeof(uint8) * TILE_SIZE);
204
break;
205
}
206
}
207
#endif
208
209
bool32 RSDK::CheckObjectCollisionTouch(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox)
210
{
211
int32 store = 0;
212
if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)
213
return false;
214
215
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
216
store = -thisHitbox->left;
217
thisHitbox->left = -thisHitbox->right;
218
thisHitbox->right = store;
219
220
store = -otherHitbox->left;
221
otherHitbox->left = -otherHitbox->right;
222
otherHitbox->right = store;
223
}
224
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
225
store = -thisHitbox->top;
226
thisHitbox->top = -thisHitbox->bottom;
227
thisHitbox->bottom = store;
228
229
store = -otherHitbox->top;
230
otherHitbox->top = -otherHitbox->bottom;
231
otherHitbox->bottom = store;
232
}
233
234
int32 thisIX = FROM_FIXED(thisEntity->position.x);
235
int32 thisIY = FROM_FIXED(thisEntity->position.y);
236
int32 otherIX = FROM_FIXED(otherEntity->position.x);
237
int32 otherIY = FROM_FIXED(otherEntity->position.y);
238
239
bool32 collided = thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left
240
&& thisIY + thisHitbox->top < otherIY + otherHitbox->bottom && thisIY + thisHitbox->bottom > otherIY + otherHitbox->top;
241
242
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
243
store = -thisHitbox->left;
244
thisHitbox->left = -thisHitbox->right;
245
thisHitbox->right = store;
246
247
store = -otherHitbox->left;
248
otherHitbox->left = -otherHitbox->right;
249
otherHitbox->right = store;
250
}
251
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
252
store = -thisHitbox->top;
253
thisHitbox->top = -thisHitbox->bottom;
254
thisHitbox->bottom = store;
255
256
store = -otherHitbox->top;
257
otherHitbox->top = -otherHitbox->bottom;
258
otherHitbox->bottom = store;
259
}
260
261
#if !RETRO_USE_ORIGINAL_CODE
262
if (showHitboxes) {
263
int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_TOUCH, thisEntity->direction, thisEntity, thisHitbox);
264
int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_TOUCH, otherEntity->direction, otherEntity, otherHitbox);
265
266
if (thisHitboxID >= 0 && collided)
267
debugHitboxList[thisHitboxID].collision |= 1 << (collided - 1);
268
if (otherHitboxID >= 0 && collided)
269
debugHitboxList[otherHitboxID].collision |= 1 << (collided - 1);
270
}
271
#endif
272
273
return collided;
274
}
275
276
uint8 RSDK::CheckObjectCollisionBox(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox, bool32 setValues)
277
{
278
if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)
279
return C_NONE;
280
281
int32 collisionSideH = C_NONE;
282
int32 collisionSideV = C_NONE;
283
284
int32 collideX = otherEntity->position.x;
285
int32 collideY = otherEntity->position.y;
286
287
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
288
int32 store = -thisHitbox->left;
289
thisHitbox->left = -thisHitbox->right;
290
thisHitbox->right = store;
291
292
store = -otherHitbox->left;
293
otherHitbox->left = -otherHitbox->right;
294
otherHitbox->right = store;
295
}
296
297
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
298
int32 store = -thisHitbox->top;
299
thisHitbox->top = -thisHitbox->bottom;
300
thisHitbox->bottom = store;
301
302
store = -otherHitbox->top;
303
otherHitbox->top = -otherHitbox->bottom;
304
otherHitbox->bottom = store;
305
}
306
307
int32 thisIX = FROM_FIXED(thisEntity->position.x);
308
int32 thisIY = FROM_FIXED(thisEntity->position.y);
309
int32 otherIX = FROM_FIXED(otherEntity->position.x);
310
int32 otherIY = FROM_FIXED(otherEntity->position.y);
311
312
otherHitbox->top++;
313
otherHitbox->bottom--;
314
315
if (otherIX <= (thisHitbox->right + thisHitbox->left + 2 * thisIX) >> 1) {
316
if (otherIX + otherHitbox->right >= thisIX + thisHitbox->left && thisIY + thisHitbox->top < otherIY + otherHitbox->bottom
317
&& thisIY + thisHitbox->bottom > otherIY + otherHitbox->top) {
318
collisionSideH = C_LEFT;
319
collideX = thisEntity->position.x + TO_FIXED(thisHitbox->left - otherHitbox->right);
320
}
321
}
322
else {
323
if (otherIX + otherHitbox->left < thisIX + thisHitbox->right && thisIY + thisHitbox->top < otherIY + otherHitbox->bottom
324
&& thisIY + thisHitbox->bottom > otherIY + otherHitbox->top) {
325
collisionSideH = C_RIGHT;
326
collideX = thisEntity->position.x + TO_FIXED(thisHitbox->right - otherHitbox->left);
327
}
328
}
329
330
otherHitbox->left++;
331
otherHitbox->top--;
332
otherHitbox->right--;
333
otherHitbox->bottom++;
334
335
if (otherIY < (thisHitbox->top + thisHitbox->bottom + 2 * thisIY) >> 1) {
336
if (otherIY + otherHitbox->bottom >= thisIY + thisHitbox->top && thisIX + thisHitbox->left < otherIX + otherHitbox->right
337
&& thisIX + thisHitbox->right > otherIX + otherHitbox->left) {
338
collisionSideV = C_TOP;
339
collideY = thisEntity->position.y + TO_FIXED(thisHitbox->top - otherHitbox->bottom);
340
}
341
}
342
else {
343
if (otherIY + otherHitbox->top < thisIY + thisHitbox->bottom && thisIX + thisHitbox->left < otherIX + otherHitbox->right) {
344
if (otherIX + otherHitbox->left < thisIX + thisHitbox->right) {
345
collisionSideV = C_BOTTOM;
346
collideY = thisEntity->position.y + TO_FIXED(thisHitbox->bottom - otherHitbox->top);
347
}
348
}
349
}
350
351
otherHitbox->left--;
352
otherHitbox->right++;
353
354
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
355
int32 store = -thisHitbox->left;
356
thisHitbox->left = -thisHitbox->right;
357
thisHitbox->right = store;
358
359
store = -otherHitbox->left;
360
otherHitbox->left = -otherHitbox->right;
361
otherHitbox->right = store;
362
}
363
364
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
365
int32 store = -thisHitbox->top;
366
thisHitbox->top = -thisHitbox->bottom;
367
thisHitbox->bottom = store;
368
369
store = -otherHitbox->top;
370
otherHitbox->top = -otherHitbox->bottom;
371
otherHitbox->bottom = store;
372
}
373
374
uint8 side = C_NONE;
375
376
int32 cx = FROM_FIXED(collideX - otherEntity->position.x);
377
int32 cy = FROM_FIXED(collideY - otherEntity->position.y);
378
if ((cx * cx >= cy * cy && (collisionSideV || !collisionSideH)) || (!collisionSideH && collisionSideV)) {
379
side = collisionSideV;
380
}
381
else {
382
side = collisionSideH;
383
}
384
385
if (setValues) {
386
int32 velX = 0;
387
switch (side) {
388
default:
389
case C_NONE: break;
390
391
case C_TOP:
392
otherEntity->position.y = collideY;
393
394
if (otherEntity->velocity.y > 0)
395
otherEntity->velocity.y = 0;
396
397
#if RETRO_REV0U
398
if (otherEntity->tileCollisions != TILECOLLISION_UP) {
399
#endif
400
if (!otherEntity->onGround && otherEntity->velocity.y >= 0) {
401
otherEntity->groundVel = otherEntity->velocity.x;
402
otherEntity->angle = 0x00;
403
otherEntity->onGround = true;
404
}
405
#if RETRO_REV0U
406
}
407
#endif
408
break;
409
410
case C_LEFT:
411
otherEntity->position.x = collideX;
412
413
velX = otherEntity->velocity.x;
414
if (otherEntity->onGround) {
415
if (otherEntity->collisionMode == CMODE_ROOF)
416
velX = -otherEntity->groundVel;
417
else
418
velX = otherEntity->groundVel;
419
}
420
421
if (velX > 0) {
422
otherEntity->velocity.x = 0;
423
otherEntity->groundVel = 0;
424
}
425
break;
426
427
case C_RIGHT:
428
otherEntity->position.x = collideX;
429
430
velX = otherEntity->velocity.x;
431
if (otherEntity->onGround) {
432
if (otherEntity->collisionMode == CMODE_ROOF)
433
velX = -otherEntity->groundVel;
434
else
435
velX = otherEntity->groundVel;
436
}
437
438
if (velX < 0) {
439
otherEntity->velocity.x = 0;
440
otherEntity->groundVel = 0;
441
}
442
break;
443
444
case C_BOTTOM:
445
otherEntity->position.y = collideY;
446
447
if (otherEntity->velocity.y < 0)
448
otherEntity->velocity.y = 0;
449
450
#if RETRO_REV0U
451
if (otherEntity->tileCollisions == TILECOLLISION_UP) {
452
if (!otherEntity->onGround && otherEntity->velocity.y <= 0) {
453
otherEntity->angle = 0x80;
454
otherEntity->groundVel = -otherEntity->velocity.x;
455
otherEntity->onGround = true;
456
}
457
}
458
#endif
459
break;
460
}
461
}
462
else {
463
#if !RETRO_REV0U
464
switch (side) {
465
default:
466
case C_NONE: break;
467
case C_TOP: otherEntity->position.y = collideY; break;
468
case C_LEFT: otherEntity->position.x = collideX; break;
469
case C_RIGHT: otherEntity->position.x = collideX; break;
470
case C_BOTTOM: otherEntity->position.y = collideY; break;
471
}
472
#endif
473
}
474
475
#if !RETRO_USE_ORIGINAL_CODE
476
if (showHitboxes) {
477
int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_BOX, thisEntity->direction, thisEntity, thisHitbox);
478
int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_BOX, otherEntity->direction, otherEntity, otherHitbox);
479
480
if (thisHitboxID >= 0 && side)
481
debugHitboxList[thisHitboxID].collision |= 1 << (side - 1);
482
if (otherHitboxID >= 0 && side)
483
debugHitboxList[otherHitboxID].collision |= 1 << (4 - side);
484
}
485
#endif
486
return side;
487
}
488
489
bool32 RSDK::CheckObjectCollisionPlatform(Entity *thisEntity, Hitbox *thisHitbox, Entity *otherEntity, Hitbox *otherHitbox, bool32 setValues)
490
{
491
int32 store = 0;
492
bool32 collided = false;
493
494
if (!thisEntity || !otherEntity || !thisHitbox || !otherHitbox)
495
return false;
496
497
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
498
store = -thisHitbox->left;
499
thisHitbox->left = -thisHitbox->right;
500
thisHitbox->right = store;
501
502
store = -otherHitbox->left;
503
otherHitbox->left = -otherHitbox->right;
504
otherHitbox->right = store;
505
}
506
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
507
store = -thisHitbox->top;
508
thisHitbox->top = -thisHitbox->bottom;
509
thisHitbox->bottom = store;
510
511
store = -otherHitbox->top;
512
otherHitbox->top = -otherHitbox->bottom;
513
otherHitbox->bottom = store;
514
}
515
516
int32 thisIX = FROM_FIXED(thisEntity->position.x);
517
int32 thisIY = FROM_FIXED(thisEntity->position.y);
518
int32 otherIX = FROM_FIXED(otherEntity->position.x);
519
int32 otherIY = FROM_FIXED(otherEntity->position.y);
520
521
int32 otherMoveY = FROM_FIXED(otherEntity->position.y - otherEntity->velocity.y);
522
523
#if RETRO_REV0U
524
if (otherEntity->tileCollisions == TILECOLLISION_UP) {
525
if (otherIY - otherHitbox->bottom >= thisIY + thisHitbox->top && otherMoveY - otherHitbox->bottom <= thisIY + thisHitbox->bottom
526
&& thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left
527
&& otherEntity->velocity.y <= 0) {
528
529
otherEntity->position.y = thisEntity->position.y + TO_FIXED(thisHitbox->bottom + otherHitbox->bottom);
530
531
if (setValues) {
532
otherEntity->velocity.y = 0;
533
534
if (!otherEntity->onGround) {
535
otherEntity->groundVel = -otherEntity->velocity.x;
536
otherEntity->angle = 0x80;
537
otherEntity->onGround = true;
538
}
539
}
540
541
collided = true;
542
}
543
}
544
else {
545
#endif
546
if (otherIY + otherHitbox->bottom >= thisIY + thisHitbox->top && otherMoveY + otherHitbox->bottom <= thisIY + thisHitbox->bottom
547
&& thisIX + thisHitbox->left < otherIX + otherHitbox->right && thisIX + thisHitbox->right > otherIX + otherHitbox->left
548
&& otherEntity->velocity.y >= 0) {
549
550
otherEntity->position.y = thisEntity->position.y + TO_FIXED(thisHitbox->top - otherHitbox->bottom);
551
552
if (setValues) {
553
otherEntity->velocity.y = 0;
554
555
if (!otherEntity->onGround) {
556
otherEntity->groundVel = otherEntity->velocity.x;
557
otherEntity->angle = 0x00;
558
otherEntity->onGround = true;
559
}
560
}
561
562
collided = true;
563
}
564
#if RETRO_REV0U
565
}
566
#endif
567
568
if ((thisEntity->direction & FLIP_X) == FLIP_X) {
569
store = -thisHitbox->left;
570
thisHitbox->left = -thisHitbox->right;
571
thisHitbox->right = store;
572
573
store = -otherHitbox->left;
574
otherHitbox->left = -otherHitbox->right;
575
otherHitbox->right = store;
576
}
577
578
if ((thisEntity->direction & FLIP_Y) == FLIP_Y) {
579
store = -thisHitbox->top;
580
thisHitbox->top = -thisHitbox->bottom;
581
thisHitbox->bottom = store;
582
583
store = -otherHitbox->top;
584
otherHitbox->top = -otherHitbox->bottom;
585
otherHitbox->bottom = store;
586
}
587
588
#if !RETRO_USE_ORIGINAL_CODE
589
if (showHitboxes) {
590
int32 thisHitboxID = RSDK::AddDebugHitbox(H_TYPE_PLAT, thisEntity->direction, thisEntity, thisHitbox);
591
int32 otherHitboxID = RSDK::AddDebugHitbox(H_TYPE_PLAT, otherEntity->direction, otherEntity, otherHitbox);
592
#if RETRO_REV0U
593
if (otherEntity->tileCollisions == TILECOLLISION_UP) {
594
595
if (thisHitboxID >= 0 && collided)
596
debugHitboxList[thisHitboxID].collision |= 1 << 3;
597
if (otherHitboxID >= 0 && collided)
598
debugHitboxList[otherHitboxID].collision |= 1 << 0;
599
}
600
else {
601
#endif
602
if (thisHitboxID >= 0 && collided)
603
debugHitboxList[thisHitboxID].collision |= 1 << 0;
604
if (otherHitboxID >= 0 && collided)
605
debugHitboxList[otherHitboxID].collision |= 1 << 3;
606
#if RETRO_REV0U
607
}
608
#endif
609
}
610
#endif
611
612
return collided;
613
}
614
615
bool32 RSDK::ObjectTileCollision(Entity *entity, uint16 cLayers, uint8 cMode, uint8 cPlane, int32 xOffset, int32 yOffset, bool32 setPos)
616
{
617
int32 layerID = 1;
618
bool32 collided = false;
619
int32 posX = FROM_FIXED(xOffset + entity->position.x);
620
int32 posY = FROM_FIXED(yOffset + entity->position.y);
621
622
int32 solid = 0;
623
switch (cMode) {
624
default: return false;
625
626
case CMODE_FLOOR:
627
solid = cPlane ? (1 << 14) : (1 << 12);
628
629
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
630
if (cLayers & layerID) {
631
TileLayer *layer = &tileLayers[l];
632
int32 colX = posX - layer->position.x;
633
int32 colY = posY - layer->position.y;
634
int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;
635
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
636
for (int32 i = 0; i < 3; ++i) {
637
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
638
uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];
639
if (tile < 0xFFFF && tile & solid) {
640
int32 ty = cy + collisionMasks[cPlane][tile & 0xFFF].floorMasks[colX & 0xF];
641
if (colY >= ty && abs(colY - ty) <= 14) {
642
collided = true;
643
colY = ty;
644
i = 3;
645
}
646
}
647
}
648
cy += TILE_SIZE;
649
}
650
}
651
posX = layer->position.x + colX;
652
posY = layer->position.y + colY;
653
}
654
}
655
656
if (setPos && collided)
657
entity->position.y = TO_FIXED(posY) - yOffset;
658
return collided;
659
660
case CMODE_LWALL:
661
solid = cPlane ? (1 << 15) : (1 << 13);
662
663
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
664
if (cLayers & layerID) {
665
TileLayer *layer = &tileLayers[l];
666
int32 colX = posX - layer->position.x;
667
int32 colY = posY - layer->position.y;
668
int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;
669
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
670
for (int32 i = 0; i < 3; ++i) {
671
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
672
uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];
673
if (tile < 0xFFFF && tile & solid) {
674
int32 tx = cx + collisionMasks[cPlane][tile & 0xFFF].lWallMasks[colY & 0xF];
675
if (colX >= tx && abs(colX - tx) <= 14) {
676
collided = true;
677
colX = tx;
678
i = 3;
679
}
680
}
681
}
682
cx += TILE_SIZE;
683
}
684
}
685
posX = layer->position.x + colX;
686
posY = layer->position.y + colY;
687
}
688
}
689
690
if (setPos && collided)
691
entity->position.x = TO_FIXED(posX) - xOffset;
692
return collided;
693
694
case CMODE_ROOF:
695
solid = cPlane ? (1 << 15) : (1 << 13);
696
697
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
698
if (cLayers & layerID) {
699
TileLayer *layer = &tileLayers[l];
700
int32 colX = posX - layer->position.x;
701
int32 colY = posY - layer->position.y;
702
int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;
703
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
704
for (int32 i = 0; i < 3; ++i) {
705
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
706
uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];
707
if (tile < 0xFFFF && tile & solid) {
708
int32 ty = cy + collisionMasks[cPlane][tile & 0xFFF].roofMasks[colX & 0xF];
709
if (colY <= ty && abs(colY - ty) <= 14) {
710
collided = true;
711
colY = ty;
712
i = 3;
713
}
714
}
715
}
716
cy -= TILE_SIZE;
717
}
718
}
719
posX = layer->position.x + colX;
720
posY = layer->position.y + colY;
721
}
722
}
723
724
if (setPos && collided)
725
entity->position.y = TO_FIXED(posY) - yOffset;
726
return collided;
727
728
case CMODE_RWALL:
729
solid = cPlane ? (1 << 15) : (1 << 13);
730
731
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
732
if (cLayers & layerID) {
733
TileLayer *layer = &tileLayers[l];
734
int32 colX = posX - layer->position.x;
735
int32 colY = posY - layer->position.y;
736
int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;
737
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
738
for (int32 i = 0; i < 3; ++i) {
739
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
740
uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];
741
if (tile < 0xFFFF && tile & solid) {
742
int32 tx = cx + collisionMasks[cPlane][tile & 0xFFF].rWallMasks[colY & 0xF];
743
if (colX <= tx && abs(colX - tx) <= 14) {
744
collided = true;
745
colX = tx;
746
i = 3;
747
}
748
}
749
}
750
cx -= TILE_SIZE;
751
}
752
}
753
posX = layer->position.x + colX;
754
posY = layer->position.y + colY;
755
}
756
}
757
758
if (setPos && collided)
759
entity->position.x = TO_FIXED(posX) - xOffset;
760
return collided;
761
}
762
}
763
bool32 RSDK::ObjectTileGrip(Entity *entity, uint16 cLayers, uint8 cMode, uint8 cPlane, int32 xOffset, int32 yOffset, int32 tolerance)
764
{
765
int32 layerID = 1;
766
bool32 collided = false;
767
int32 posX = FROM_FIXED(xOffset + entity->position.x);
768
int32 posY = FROM_FIXED(yOffset + entity->position.y);
769
770
int32 solid = 0;
771
switch (cMode) {
772
default: return false;
773
774
case CMODE_FLOOR:
775
solid = cPlane ? (1 << 14) : (1 << 12);
776
777
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
778
if (cLayers & layerID) {
779
TileLayer *layer = &tileLayers[l];
780
int32 colX = posX - layer->position.x;
781
int32 colY = posY - layer->position.y;
782
int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;
783
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
784
for (int32 i = 0; i < 3; ++i) {
785
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
786
uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];
787
if (tile < 0xFFFF && tile & solid) {
788
int32 mask = collisionMasks[cPlane][tile & 0xFFF].floorMasks[colX & 0xF];
789
int32 ty = cy + mask;
790
if (mask < 0xFF) {
791
if (abs(colY - ty) <= tolerance) {
792
collided = true;
793
colY = ty;
794
}
795
i = 3;
796
}
797
}
798
}
799
cy += TILE_SIZE;
800
}
801
}
802
posX = layer->position.x + colX;
803
posY = layer->position.y + colY;
804
}
805
}
806
807
if (collided)
808
entity->position.y = TO_FIXED(posY) - yOffset;
809
return collided;
810
811
case CMODE_LWALL:
812
solid = cPlane ? (1 << 15) : (1 << 13);
813
814
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
815
if (cLayers & layerID) {
816
TileLayer *layer = &tileLayers[l];
817
int32 colX = posX - layer->position.x;
818
int32 colY = posY - layer->position.y;
819
int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;
820
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
821
for (int32 i = 0; i < 3; ++i) {
822
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
823
uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];
824
if (tile < 0xFFFF && tile & solid) {
825
int32 mask = collisionMasks[cPlane][tile & 0xFFF].lWallMasks[colY & 0xF];
826
int32 tx = cx + mask;
827
if (mask < 0xFF) {
828
if (abs(colX - tx) <= tolerance) {
829
collided = true;
830
colX = tx;
831
}
832
i = 3;
833
}
834
}
835
}
836
cx += TILE_SIZE;
837
}
838
}
839
posX = layer->position.x + colX;
840
posY = layer->position.y + colY;
841
}
842
}
843
844
if (collided)
845
entity->position.x = TO_FIXED(posX) - xOffset;
846
return collided;
847
848
case CMODE_ROOF:
849
solid = cPlane ? (1 << 15) : (1 << 13);
850
851
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
852
if (cLayers & layerID) {
853
TileLayer *layer = &tileLayers[l];
854
int32 colX = posX - layer->position.x;
855
int32 colY = posY - layer->position.y;
856
int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;
857
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
858
for (int32 i = 0; i < 3; ++i) {
859
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
860
uint16 tile = layer->layout[(colX >> 4) + ((cy / TILE_SIZE) << layer->widthShift)];
861
if (tile < 0xFFFF && tile & solid) {
862
int32 mask = collisionMasks[cPlane][tile & 0xFFF].roofMasks[colX & 0xF];
863
int32 ty = cy + mask;
864
if (mask < 0xFF) {
865
if (abs(colY - ty) <= tolerance) {
866
collided = true;
867
colY = ty;
868
}
869
i = 3;
870
}
871
}
872
}
873
cy -= TILE_SIZE;
874
}
875
}
876
posX = layer->position.x + colX;
877
posY = layer->position.y + colY;
878
}
879
}
880
881
if (collided)
882
entity->position.y = TO_FIXED(posY) - yOffset;
883
return collided;
884
885
case CMODE_RWALL:
886
solid = cPlane ? (1 << 15) : (1 << 13);
887
888
for (int32 l = 0; l < LAYER_COUNT; ++l, layerID <<= 1) {
889
if (cLayers & layerID) {
890
TileLayer *layer = &tileLayers[l];
891
int32 colX = posX - layer->position.x;
892
int32 colY = posY - layer->position.y;
893
int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;
894
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
895
for (int32 i = 0; i < 3; ++i) {
896
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
897
uint16 tile = layer->layout[(cx >> 4) + ((colY / TILE_SIZE) << layer->widthShift)];
898
if (tile < 0xFFFF && tile & solid) {
899
int32 mask = collisionMasks[cPlane][tile & 0xFFF].rWallMasks[colY & 0xF];
900
int32 tx = cx + mask;
901
if (mask < 0xFF) {
902
if (abs(colX - tx) <= tolerance) {
903
collided = true;
904
colX = tx;
905
}
906
i = 3;
907
}
908
}
909
}
910
cx -= TILE_SIZE;
911
}
912
}
913
posX = layer->position.x + colX;
914
posY = layer->position.y + colY;
915
}
916
}
917
918
if (collided)
919
entity->position.x = TO_FIXED(posX) - xOffset;
920
return collided;
921
}
922
}
923
924
void RSDK::ProcessObjectMovement(Entity *entity, Hitbox *outerBox, Hitbox *innerBox)
925
{
926
if (entity && outerBox && innerBox) {
927
if (entity->tileCollisions) {
928
entity->angle &= 0xFF;
929
930
collisionTolerance = highCollisionTolerance;
931
if (abs(entity->groundVel) < TO_FIXED(6) && entity->angle == 0)
932
collisionTolerance = lowCollisionTolerance;
933
934
collisionOuter.left = outerBox->left;
935
collisionOuter.top = outerBox->top;
936
collisionOuter.right = outerBox->right;
937
collisionOuter.bottom = outerBox->bottom;
938
939
collisionInner.left = innerBox->left;
940
collisionInner.top = innerBox->top;
941
collisionInner.right = innerBox->right;
942
collisionInner.bottom = innerBox->bottom;
943
944
collisionEntity = entity;
945
946
#if RETRO_REV0U
947
collisionMaskAir = collisionOuter.bottom >= 14 ? 19 : 17;
948
949
if (entity->onGround) {
950
// true = normal, false = flipped
951
if (entity->tileCollisions == TILECOLLISION_DOWN)
952
useCollisionOffset = entity->angle == 0x00;
953
else
954
useCollisionOffset = entity->angle == 0x80;
955
956
#if !RETRO_USE_ORIGINAL_CODE
957
// fixes some clipping issues as chibi sonic (& using small hitboxes)
958
// shouldn't effect anything else :)
959
if (collisionOuter.bottom < 14)
960
useCollisionOffset = false;
961
#endif
962
963
ProcessPathGrip();
964
}
965
else {
966
useCollisionOffset = false;
967
// true = normal, false = flipped
968
if (entity->tileCollisions == TILECOLLISION_DOWN)
969
ProcessAirCollision_Down();
970
else
971
ProcessAirCollision_Up();
972
}
973
#else
974
if (collisionOuter.bottom >= 14) {
975
collisionOffset = COLLISION_OFFSET;
976
collisionMaskAir = 19;
977
}
978
else {
979
collisionOffset = 0;
980
collisionTolerance = 15;
981
collisionMaskAir = 17;
982
}
983
984
if (entity->onGround)
985
ProcessPathGrip();
986
else
987
ProcessAirCollision_Down();
988
#endif
989
990
if (entity->onGround) {
991
entity->velocity.x = entity->groundVel * cos256LookupTable[entity->angle & 0xFF] >> 8;
992
entity->velocity.y = entity->groundVel * sin256LookupTable[entity->angle & 0xFF] >> 8;
993
}
994
else {
995
entity->groundVel = entity->velocity.x;
996
}
997
}
998
else {
999
entity->position.x += entity->velocity.x;
1000
entity->position.y += entity->velocity.y;
1001
}
1002
}
1003
}
1004
1005
void RSDK::ProcessAirCollision_Down()
1006
{
1007
uint8 movingDown = 0;
1008
uint8 movingUp = 0;
1009
uint8 movingLeft = 0;
1010
uint8 movingRight = 0;
1011
1012
int32 offset = 0;
1013
#if RETRO_REV0U
1014
offset = useCollisionOffset ? COLLISION_OFFSET : 0;
1015
#else
1016
offset = collisionOffset;
1017
#endif
1018
1019
if (collisionEntity->velocity.x >= 0) {
1020
movingRight = 1;
1021
sensors[0].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right);
1022
sensors[0].position.y = collisionEntity->position.y + offset;
1023
}
1024
1025
if (collisionEntity->velocity.x <= 0) {
1026
movingLeft = 1;
1027
sensors[1].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);
1028
sensors[1].position.y = collisionEntity->position.y + offset;
1029
}
1030
1031
// Bug Details:
1032
// using collision outer here results in a few slopes having some wonky collision if you jump at the on the wrong angles
1033
// v4 and prior uses inner box here instead, which works fine as far as I can tell...
1034
// Fix (I think, it may break something else?):
1035
// uncomment the 2 lines below and remove the two below that to get v4-like behaviour
1036
// sensors[2].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.left);
1037
// sensors[3].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.right);
1038
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1039
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1040
sensors[4].position.x = sensors[2].position.x;
1041
sensors[5].position.x = sensors[3].position.x;
1042
1043
sensors[0].collided = false;
1044
sensors[1].collided = false;
1045
sensors[2].collided = false;
1046
sensors[3].collided = false;
1047
sensors[4].collided = false;
1048
sensors[5].collided = false;
1049
if (collisionEntity->velocity.y >= 0) {
1050
movingDown = 1;
1051
sensors[2].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);
1052
sensors[3].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);
1053
}
1054
1055
if (abs(collisionEntity->velocity.x) > TO_FIXED(1) || collisionEntity->velocity.y < 0) {
1056
movingUp = 1;
1057
sensors[4].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);
1058
sensors[5].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);
1059
}
1060
1061
int32 cnt = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? ((abs(collisionEntity->velocity.y) >> collisionMaskAir) + 1)
1062
: (abs(collisionEntity->velocity.x) >> collisionMaskAir) + 1);
1063
int32 velX = collisionEntity->velocity.x / cnt;
1064
int32 velY = collisionEntity->velocity.y / cnt;
1065
int32 velX2 = collisionEntity->velocity.x - velX * (cnt - 1);
1066
int32 velY2 = collisionEntity->velocity.y - velY * (cnt - 1);
1067
while (cnt > 0) {
1068
if (cnt < 2) {
1069
velX = velX2;
1070
velY = velY2;
1071
}
1072
cnt--;
1073
1074
if (movingRight == 1) {
1075
sensors[0].position.x += velX;
1076
sensors[0].position.y += velY;
1077
LWallCollision(&sensors[0]);
1078
1079
if (sensors[0].collided) {
1080
movingRight = 2;
1081
}
1082
#if !RETRO_REV0U
1083
else if (collisionEntity->velocity.x < TO_FIXED(2) && collisionOffset > 0) {
1084
sensors[0].position.y -= collisionOffset << 1;
1085
LWallCollision(&sensors[0]);
1086
1087
if (sensors[0].collided)
1088
movingRight = 2;
1089
sensors[0].position.y += collisionOffset << 1;
1090
}
1091
#endif
1092
}
1093
1094
if (movingLeft == 1) {
1095
sensors[1].position.x += velX;
1096
sensors[1].position.y += velY;
1097
RWallCollision(&sensors[1]);
1098
1099
if (sensors[1].collided) {
1100
movingLeft = 2;
1101
}
1102
#if !RETRO_REV0U
1103
else if (collisionEntity->velocity.x > -TO_FIXED(2) && collisionOffset > 0) {
1104
sensors[1].position.y -= collisionOffset << 1;
1105
RWallCollision(&sensors[1]);
1106
1107
if (sensors[1].collided)
1108
movingLeft = 2;
1109
sensors[1].position.y += collisionOffset << 1;
1110
}
1111
#endif
1112
}
1113
1114
if (movingRight == 2) {
1115
collisionEntity->velocity.x = 0;
1116
collisionEntity->groundVel = 0;
1117
collisionEntity->position.x = sensors[0].position.x - TO_FIXED(collisionOuter.right);
1118
1119
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1120
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1121
sensors[4].position.x = sensors[2].position.x;
1122
sensors[5].position.x = sensors[3].position.x;
1123
1124
velX = 0;
1125
velX2 = 0;
1126
movingRight = 3;
1127
}
1128
1129
if (movingLeft == 2) {
1130
collisionEntity->velocity.x = 0;
1131
collisionEntity->groundVel = 0;
1132
collisionEntity->position.x = sensors[1].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1133
1134
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1135
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1136
sensors[4].position.x = sensors[2].position.x;
1137
sensors[5].position.x = sensors[3].position.x;
1138
1139
velX = 0;
1140
velX2 = 0;
1141
movingLeft = 3;
1142
}
1143
1144
if (movingDown == 1) {
1145
for (int32 i = 2; i < 4; i++) {
1146
if (!sensors[i].collided) {
1147
sensors[i].position.x += velX;
1148
sensors[i].position.y += velY;
1149
FloorCollision(&sensors[i]);
1150
}
1151
}
1152
1153
if (sensors[2].collided || sensors[3].collided) {
1154
movingDown = 2;
1155
cnt = 0;
1156
}
1157
}
1158
1159
if (movingUp == 1) {
1160
for (int32 i = 4; i < 6; i++) {
1161
if (!sensors[i].collided) {
1162
sensors[i].position.x += velX;
1163
sensors[i].position.y += velY;
1164
RoofCollision(&sensors[i]);
1165
}
1166
}
1167
1168
if (sensors[4].collided || sensors[5].collided) {
1169
movingUp = 2;
1170
cnt = 0;
1171
}
1172
}
1173
}
1174
1175
if (movingRight < 2 && movingLeft < 2)
1176
collisionEntity->position.x += collisionEntity->velocity.x;
1177
1178
if (movingUp < 2 && movingDown < 2) {
1179
collisionEntity->position.y += collisionEntity->velocity.y;
1180
return;
1181
}
1182
1183
if (movingDown == 2) {
1184
collisionEntity->onGround = true;
1185
1186
if (sensors[2].collided && sensors[3].collided) {
1187
if (sensors[2].position.y >= sensors[3].position.y) {
1188
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);
1189
collisionEntity->angle = sensors[3].angle;
1190
}
1191
else {
1192
collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);
1193
collisionEntity->angle = sensors[2].angle;
1194
}
1195
}
1196
else if (sensors[2].collided) {
1197
collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);
1198
collisionEntity->angle = sensors[2].angle;
1199
}
1200
else if (sensors[3].collided) {
1201
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);
1202
collisionEntity->angle = sensors[3].angle;
1203
}
1204
1205
if (collisionEntity->angle > 0xA0 && collisionEntity->angle < 0xDE && collisionEntity->collisionMode != CMODE_LWALL) {
1206
collisionEntity->collisionMode = CMODE_LWALL;
1207
collisionEntity->position.x -= TO_FIXED(4);
1208
}
1209
1210
if (collisionEntity->angle > 0x22 && collisionEntity->angle < 0x60 && collisionEntity->collisionMode != CMODE_RWALL) {
1211
collisionEntity->collisionMode = CMODE_RWALL;
1212
collisionEntity->position.x += TO_FIXED(4);
1213
}
1214
1215
int32 speed = 0;
1216
if (collisionEntity->angle < 0x80) {
1217
if (collisionEntity->angle < 0x10) {
1218
speed = collisionEntity->velocity.x;
1219
}
1220
else if (collisionEntity->angle >= 0x20) {
1221
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? collisionEntity->velocity.y
1222
: collisionEntity->velocity.x);
1223
}
1224
else {
1225
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? (collisionEntity->velocity.y >> 1)
1226
: collisionEntity->velocity.x);
1227
}
1228
}
1229
else if (collisionEntity->angle > 0xF0) {
1230
speed = collisionEntity->velocity.x;
1231
}
1232
else if (collisionEntity->angle <= 0xE0) {
1233
speed =
1234
(abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? -collisionEntity->velocity.y : collisionEntity->velocity.x);
1235
}
1236
else {
1237
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? -(collisionEntity->velocity.y >> 1)
1238
: collisionEntity->velocity.x);
1239
}
1240
1241
if (speed < -TO_FIXED(24))
1242
speed = -TO_FIXED(24);
1243
1244
if (speed > TO_FIXED(24))
1245
speed = TO_FIXED(24);
1246
1247
collisionEntity->groundVel = speed;
1248
collisionEntity->velocity.x = speed;
1249
collisionEntity->velocity.y = 0;
1250
}
1251
1252
if (movingUp == 2) {
1253
int32 sensorAngle = 0;
1254
1255
if (sensors[4].collided && sensors[5].collided) {
1256
if (sensors[4].position.y <= sensors[5].position.y) {
1257
collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1258
sensorAngle = sensors[5].angle;
1259
}
1260
else {
1261
collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1262
sensorAngle = sensors[4].angle;
1263
}
1264
}
1265
else if (sensors[4].collided) {
1266
collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1267
sensorAngle = sensors[4].angle;
1268
}
1269
else if (sensors[5].collided) {
1270
collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1271
sensorAngle = sensors[5].angle;
1272
}
1273
sensorAngle &= 0xFF;
1274
1275
if (sensorAngle < 0x62) {
1276
if (collisionEntity->velocity.y < -abs(collisionEntity->velocity.x)) {
1277
collisionEntity->onGround = true;
1278
collisionEntity->angle = sensorAngle;
1279
collisionEntity->collisionMode = CMODE_RWALL;
1280
collisionEntity->position.x += TO_FIXED(4);
1281
collisionEntity->position.y -= TO_FIXED(2);
1282
1283
collisionEntity->groundVel = collisionEntity->angle <= 0x60 ? collisionEntity->velocity.y : (collisionEntity->velocity.y >> 1);
1284
}
1285
}
1286
1287
if (sensorAngle > 0x9E && sensorAngle < 0xC1) {
1288
if (collisionEntity->velocity.y < -abs(collisionEntity->velocity.x)) {
1289
collisionEntity->onGround = true;
1290
collisionEntity->angle = sensorAngle;
1291
collisionEntity->collisionMode = CMODE_LWALL;
1292
collisionEntity->position.x -= TO_FIXED(4);
1293
collisionEntity->position.y -= TO_FIXED(2);
1294
1295
collisionEntity->groundVel = collisionEntity->angle >= 0xA0 ? -collisionEntity->velocity.y : -(collisionEntity->velocity.y >> 1);
1296
}
1297
}
1298
1299
if (collisionEntity->velocity.y < 0)
1300
collisionEntity->velocity.y = 0;
1301
}
1302
}
1303
#if RETRO_REV0U
1304
void RSDK::ProcessAirCollision_Up()
1305
{
1306
uint8 movingDown = 0;
1307
uint8 movingUp = 0;
1308
uint8 movingLeft = 0;
1309
uint8 movingRight = 0;
1310
1311
int32 offset = useCollisionOffset ? -COLLISION_OFFSET : 0;
1312
1313
if (collisionEntity->velocity.x >= 0) {
1314
movingRight = 1;
1315
sensors[0].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right);
1316
sensors[0].position.y = collisionEntity->position.y + offset;
1317
}
1318
1319
if (collisionEntity->velocity.x <= 0) {
1320
movingLeft = 1;
1321
sensors[1].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);
1322
sensors[1].position.y = collisionEntity->position.y + offset;
1323
}
1324
1325
// Bug Details:
1326
// using collision outer here results in a few slopes having some wonky collision if you jump at the on the wrong angles
1327
// v4 and prior uses inner box here instead, which works fine as far as I can tell...
1328
// Fix (I think, it may break something else?):
1329
// uncomment the 2 lines below and remove the two below that to get v4-like behaviour
1330
// sensors[2].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.left);
1331
// sensors[3].pos.x = collisionEntity->position.x + TO_FIXED(collisionInner.right);
1332
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1333
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1334
sensors[4].position.x = sensors[2].position.x;
1335
sensors[5].position.x = sensors[3].position.x;
1336
1337
sensors[0].collided = false;
1338
sensors[1].collided = false;
1339
sensors[2].collided = false;
1340
sensors[3].collided = false;
1341
sensors[4].collided = false;
1342
sensors[5].collided = false;
1343
if (collisionEntity->velocity.y <= 0) {
1344
movingDown = 1;
1345
sensors[4].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);
1346
sensors[5].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.top) - TO_FIXED(1);
1347
}
1348
1349
if (abs(collisionEntity->velocity.x) > TO_FIXED(1) || collisionEntity->velocity.y > 0) {
1350
movingUp = 1;
1351
sensors[2].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);
1352
sensors[3].position.y = collisionEntity->position.y + TO_FIXED(collisionOuter.bottom);
1353
}
1354
1355
int32 cnt = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? ((abs(collisionEntity->velocity.y) >> collisionMaskAir) + 1)
1356
: (abs(collisionEntity->velocity.x) >> collisionMaskAir) + 1);
1357
int32 velX = collisionEntity->velocity.x / cnt;
1358
int32 velY = collisionEntity->velocity.y / cnt;
1359
int32 velX2 = collisionEntity->velocity.x - velX * (cnt - 1);
1360
int32 velY2 = collisionEntity->velocity.y - velY * (cnt - 1);
1361
while (cnt > 0) {
1362
if (cnt < 2) {
1363
velX = velX2;
1364
velY = velY2;
1365
}
1366
cnt--;
1367
1368
if (movingRight == 1) {
1369
sensors[0].position.x += velX;
1370
sensors[0].position.y += velY;
1371
LWallCollision(&sensors[0]);
1372
1373
if (sensors[0].collided) {
1374
movingRight = 2;
1375
}
1376
#if !RETRO_REV0U
1377
else if (collisionEntity->velocity.x < TO_FIXED(2) && collisionOffset > 0) {
1378
sensors[0].position.y -= collisionOffset << 1;
1379
LWallCollision(&sensors[0]);
1380
1381
if (sensors[0].collided)
1382
movingRight = 2;
1383
sensors[0].position.y += collisionOffset << 1;
1384
}
1385
#endif
1386
}
1387
1388
if (movingLeft == 1) {
1389
sensors[1].position.x += velX;
1390
sensors[1].position.y += velY;
1391
RWallCollision(&sensors[1]);
1392
1393
if (sensors[1].collided) {
1394
movingLeft = 2;
1395
}
1396
#if !RETRO_REV0U
1397
else if (collisionEntity->velocity.x > -TO_FIXED(2) && collisionOffset > 0) {
1398
sensors[1].position.y -= collisionOffset << 1;
1399
RWallCollision(&sensors[1]);
1400
1401
if (sensors[1].collided)
1402
movingLeft = 2;
1403
sensors[1].position.y += collisionOffset << 1;
1404
}
1405
#endif
1406
}
1407
1408
if (movingRight == 2) {
1409
collisionEntity->velocity.x = 0;
1410
collisionEntity->groundVel = 0;
1411
collisionEntity->position.x = sensors[0].position.x - TO_FIXED(collisionOuter.right);
1412
1413
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1414
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1415
sensors[4].position.x = sensors[2].position.x;
1416
sensors[5].position.x = sensors[3].position.x;
1417
1418
velX = 0;
1419
velX2 = 0;
1420
movingRight = 3;
1421
}
1422
1423
if (movingLeft == 2) {
1424
collisionEntity->velocity.x = 0;
1425
collisionEntity->groundVel = 0;
1426
collisionEntity->position.x = sensors[1].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1427
1428
sensors[2].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1429
sensors[3].position.x = collisionEntity->position.x + TO_FIXED(collisionOuter.right) - TO_FIXED(2);
1430
sensors[4].position.x = sensors[2].position.x;
1431
sensors[5].position.x = sensors[3].position.x;
1432
1433
velX = 0;
1434
velX2 = 0;
1435
movingLeft = 3;
1436
}
1437
1438
if (movingUp == 1) {
1439
for (int32 i = 2; i < 4; i++) {
1440
if (!sensors[i].collided) {
1441
sensors[i].position.x += velX;
1442
sensors[i].position.y += velY;
1443
FloorCollision(&sensors[i]);
1444
}
1445
}
1446
1447
if (sensors[2].collided || sensors[3].collided) {
1448
movingUp = 2;
1449
cnt = 0;
1450
}
1451
}
1452
1453
if (movingDown == 1) {
1454
for (int32 i = 4; i < 6; i++) {
1455
if (!sensors[i].collided) {
1456
sensors[i].position.x += velX;
1457
sensors[i].position.y += velY;
1458
RoofCollision(&sensors[i]);
1459
}
1460
}
1461
1462
if (sensors[4].collided || sensors[5].collided) {
1463
movingDown = 2;
1464
cnt = 0;
1465
}
1466
}
1467
}
1468
1469
if (movingRight < 2 && movingLeft < 2)
1470
collisionEntity->position.x += collisionEntity->velocity.x;
1471
1472
if (movingUp < 2 && movingDown < 2) {
1473
collisionEntity->position.y += collisionEntity->velocity.y;
1474
return;
1475
}
1476
1477
if (movingDown == 2) {
1478
collisionEntity->onGround = true;
1479
1480
if (sensors[4].collided && sensors[5].collided) {
1481
if (sensors[4].position.y <= sensors[5].position.y) {
1482
collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1483
collisionEntity->angle = sensors[5].angle;
1484
}
1485
else {
1486
collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1487
collisionEntity->angle = sensors[4].angle;
1488
}
1489
}
1490
else if (sensors[4].collided) {
1491
collisionEntity->position.y = sensors[4].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1492
collisionEntity->angle = sensors[4].angle;
1493
}
1494
else if (sensors[5].collided) {
1495
collisionEntity->position.y = sensors[5].position.y - TO_FIXED(collisionOuter.top) + TO_FIXED(1);
1496
collisionEntity->angle = sensors[5].angle;
1497
}
1498
1499
if (collisionEntity->angle > 0xA2 && collisionEntity->angle < 0xE0 && collisionEntity->collisionMode != CMODE_LWALL) {
1500
collisionEntity->collisionMode = CMODE_LWALL;
1501
collisionEntity->position.x -= TO_FIXED(4);
1502
}
1503
1504
if (collisionEntity->angle > 0x20 && collisionEntity->angle < 0x5E && collisionEntity->collisionMode != CMODE_RWALL) {
1505
collisionEntity->collisionMode = CMODE_RWALL;
1506
collisionEntity->position.x += TO_FIXED(4);
1507
}
1508
1509
int32 speed = 0;
1510
if (collisionEntity->angle >= 0x80) {
1511
if (collisionEntity->angle < 0x90) {
1512
speed = -collisionEntity->velocity.x;
1513
}
1514
else if (collisionEntity->angle >= 0xA0) {
1515
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? collisionEntity->velocity.y
1516
: collisionEntity->velocity.x);
1517
}
1518
else {
1519
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? (collisionEntity->velocity.y >> 1)
1520
: collisionEntity->velocity.x);
1521
}
1522
}
1523
else if (collisionEntity->angle <= 0x70) {
1524
speed = collisionEntity->velocity.x;
1525
}
1526
else if (collisionEntity->angle <= 0x60) {
1527
speed =
1528
(abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y) ? -collisionEntity->velocity.y : collisionEntity->velocity.x);
1529
}
1530
else {
1531
speed = (abs(collisionEntity->velocity.x) <= abs(collisionEntity->velocity.y >> 1) ? -(collisionEntity->velocity.y >> 1)
1532
: collisionEntity->velocity.x);
1533
}
1534
1535
if (speed < -TO_FIXED(24))
1536
speed = -TO_FIXED(24);
1537
1538
if (speed > TO_FIXED(24))
1539
speed = TO_FIXED(24);
1540
1541
collisionEntity->groundVel = speed;
1542
collisionEntity->velocity.x = speed;
1543
collisionEntity->velocity.y = 0;
1544
}
1545
1546
if (movingUp == 2) {
1547
int32 sensorAngle = 0;
1548
1549
if (sensors[2].collided && sensors[3].collided) {
1550
if (sensors[2].position.y >= sensors[3].position.y) {
1551
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);
1552
sensorAngle = sensors[3].angle;
1553
}
1554
else {
1555
collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);
1556
sensorAngle = sensors[2].angle;
1557
}
1558
}
1559
else if (sensors[2].collided) {
1560
collisionEntity->position.y = sensors[2].position.y - TO_FIXED(collisionOuter.bottom);
1561
sensorAngle = sensors[2].angle;
1562
}
1563
else if (sensors[3].collided) {
1564
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.bottom);
1565
sensorAngle = sensors[3].angle;
1566
}
1567
sensorAngle &= 0xFF;
1568
1569
if (sensorAngle >= 0x21 && sensorAngle <= 0x40) {
1570
if (collisionEntity->velocity.y > -abs(collisionEntity->velocity.x)) {
1571
collisionEntity->onGround = true;
1572
collisionEntity->angle = sensorAngle;
1573
collisionEntity->collisionMode = CMODE_RWALL;
1574
collisionEntity->position.x += TO_FIXED(4);
1575
collisionEntity->position.y -= TO_FIXED(2);
1576
1577
collisionEntity->groundVel = collisionEntity->angle <= 0x20 ? collisionEntity->velocity.y : (collisionEntity->velocity.y >> 1);
1578
}
1579
}
1580
1581
if (sensorAngle >= 0xC0 && sensorAngle <= 0xE2) {
1582
if (collisionEntity->velocity.y > -abs(collisionEntity->velocity.x)) {
1583
collisionEntity->onGround = true;
1584
collisionEntity->angle = sensorAngle;
1585
collisionEntity->collisionMode = CMODE_LWALL;
1586
collisionEntity->position.x -= TO_FIXED(4);
1587
collisionEntity->position.y -= TO_FIXED(2);
1588
1589
collisionEntity->groundVel = collisionEntity->angle <= 0xE0 ? -collisionEntity->velocity.y : -(collisionEntity->velocity.y >> 1);
1590
}
1591
}
1592
1593
if (collisionEntity->velocity.y > 0)
1594
collisionEntity->velocity.y = 0;
1595
}
1596
}
1597
#endif
1598
void RSDK::ProcessPathGrip()
1599
{
1600
int32 xVel = 0;
1601
int32 yVel = 0;
1602
1603
sensors[4].position.x = collisionEntity->position.x;
1604
sensors[4].position.y = collisionEntity->position.y;
1605
for (int32 i = 0; i < 6; ++i) {
1606
sensors[i].angle = collisionEntity->angle;
1607
sensors[i].collided = false;
1608
}
1609
SetPathGripSensors(sensors);
1610
1611
int32 absSpeed = abs(collisionEntity->groundVel);
1612
int32 checkDist = absSpeed >> 18;
1613
absSpeed &= 0x3FFFF;
1614
while (checkDist > -1) {
1615
if (checkDist >= 1) {
1616
xVel = cos256LookupTable[collisionEntity->angle] << 10;
1617
yVel = sin256LookupTable[collisionEntity->angle] << 10;
1618
checkDist--;
1619
}
1620
else {
1621
xVel = absSpeed * cos256LookupTable[collisionEntity->angle] >> 8;
1622
yVel = absSpeed * sin256LookupTable[collisionEntity->angle] >> 8;
1623
checkDist = -1;
1624
}
1625
1626
if (collisionEntity->groundVel < 0) {
1627
xVel = -xVel;
1628
yVel = -yVel;
1629
}
1630
1631
sensors[0].collided = false;
1632
sensors[1].collided = false;
1633
sensors[2].collided = false;
1634
sensors[4].position.x += xVel;
1635
sensors[4].position.y += yVel;
1636
int32 tileDistance = -1;
1637
1638
switch (collisionEntity->collisionMode) {
1639
case CMODE_FLOOR: {
1640
sensors[3].position.x += xVel;
1641
sensors[3].position.y += yVel;
1642
1643
if (collisionEntity->groundVel > 0) {
1644
LWallCollision(&sensors[3]);
1645
#if RETRO_REV0U
1646
if (sensors[3].collided)
1647
sensors[2].position.x = sensors[3].position.x - TO_FIXED(2);
1648
#endif
1649
}
1650
1651
if (collisionEntity->groundVel < 0) {
1652
RWallCollision(&sensors[3]);
1653
#if RETRO_REV0U
1654
if (sensors[3].collided)
1655
sensors[0].position.x = sensors[3].position.x + TO_FIXED(2);
1656
#endif
1657
}
1658
1659
if (sensors[3].collided) {
1660
xVel = 0;
1661
checkDist = -1;
1662
}
1663
1664
for (int32 i = 0; i < 3; i++) {
1665
sensors[i].position.x += xVel;
1666
sensors[i].position.y += yVel;
1667
FindFloorPosition(&sensors[i]);
1668
}
1669
1670
tileDistance = -1;
1671
for (int32 i = 0; i < 3; i++) {
1672
if (tileDistance > -1) {
1673
if (sensors[i].collided) {
1674
if (sensors[i].position.y < sensors[tileDistance].position.y)
1675
tileDistance = i;
1676
1677
if (sensors[i].position.y == sensors[tileDistance].position.y && (sensors[i].angle < 0x08 || sensors[i].angle > 0xF8))
1678
tileDistance = i;
1679
}
1680
}
1681
else if (sensors[i].collided)
1682
tileDistance = i;
1683
}
1684
1685
if (tileDistance <= -1) {
1686
checkDist = -1;
1687
}
1688
else {
1689
sensors[0].position.y = sensors[tileDistance].position.y;
1690
sensors[0].angle = sensors[tileDistance].angle;
1691
1692
sensors[1].position.y = sensors[0].position.y;
1693
sensors[1].angle = sensors[0].angle;
1694
1695
sensors[2].position.y = sensors[0].position.y;
1696
sensors[2].angle = sensors[0].angle;
1697
1698
sensors[4].position.x = sensors[1].position.x;
1699
sensors[4].position.y = sensors[0].position.y - TO_FIXED(collisionOuter.bottom);
1700
}
1701
1702
if (sensors[0].angle < 0xDE && sensors[0].angle > 0x80)
1703
collisionEntity->collisionMode = CMODE_LWALL;
1704
if (sensors[0].angle > 0x22 && sensors[0].angle < 0x80)
1705
collisionEntity->collisionMode = CMODE_RWALL;
1706
break;
1707
}
1708
1709
case CMODE_LWALL: {
1710
sensors[3].position.x += xVel;
1711
sensors[3].position.y += yVel;
1712
1713
if (collisionEntity->groundVel > 0)
1714
RoofCollision(&sensors[3]);
1715
1716
if (collisionEntity->groundVel < 0)
1717
FloorCollision(&sensors[3]);
1718
1719
if (sensors[3].collided) {
1720
yVel = 0;
1721
checkDist = -1;
1722
}
1723
1724
for (int32 i = 0; i < 3; i++) {
1725
sensors[i].position.x += xVel;
1726
sensors[i].position.y += yVel;
1727
FindLWallPosition(&sensors[i]);
1728
}
1729
1730
tileDistance = -1;
1731
for (int32 i = 0; i < 3; i++) {
1732
if (tileDistance > -1) {
1733
if (sensors[i].position.x < sensors[tileDistance].position.x && sensors[i].collided) {
1734
tileDistance = i;
1735
}
1736
}
1737
else if (sensors[i].collided) {
1738
tileDistance = i;
1739
}
1740
}
1741
1742
if (tileDistance <= -1) {
1743
checkDist = -1;
1744
}
1745
else {
1746
sensors[0].position.x = sensors[tileDistance].position.x;
1747
sensors[0].angle = sensors[tileDistance].angle;
1748
1749
sensors[1].position.x = sensors[0].position.x;
1750
sensors[1].angle = sensors[0].angle;
1751
1752
sensors[2].position.x = sensors[0].position.x;
1753
sensors[2].angle = sensors[0].angle;
1754
1755
sensors[4].position.x = sensors[1].position.x - TO_FIXED(collisionOuter.bottom);
1756
sensors[4].position.y = sensors[1].position.y;
1757
}
1758
1759
if (sensors[0].angle > 0xE2)
1760
collisionEntity->collisionMode = CMODE_FLOOR;
1761
1762
if (sensors[0].angle < 0x9E)
1763
collisionEntity->collisionMode = CMODE_ROOF;
1764
break;
1765
}
1766
1767
case CMODE_ROOF: {
1768
sensors[3].position.x += xVel;
1769
sensors[3].position.y += yVel;
1770
1771
if (collisionEntity->groundVel > 0) {
1772
RWallCollision(&sensors[3]);
1773
#if RETRO_REV0U
1774
if (sensors[3].collided)
1775
sensors[2].position.x = sensors[3].position.x + TO_FIXED(2);
1776
#endif
1777
}
1778
1779
if (collisionEntity->groundVel < 0) {
1780
LWallCollision(&sensors[3]);
1781
#if RETRO_REV0U
1782
if (sensors[3].collided)
1783
sensors[0].position.x = sensors[3].position.x - TO_FIXED(2);
1784
#endif
1785
}
1786
1787
if (sensors[3].collided) {
1788
xVel = 0;
1789
checkDist = -1;
1790
}
1791
1792
for (int32 i = 0; i < 3; i++) {
1793
sensors[i].position.x += xVel;
1794
sensors[i].position.y += yVel;
1795
FindRoofPosition(&sensors[i]);
1796
}
1797
1798
tileDistance = -1;
1799
for (int32 i = 0; i < 3; i++) {
1800
if (tileDistance > -1) {
1801
if (sensors[i].position.y > sensors[tileDistance].position.y && sensors[i].collided) {
1802
tileDistance = i;
1803
}
1804
}
1805
else if (sensors[i].collided) {
1806
tileDistance = i;
1807
}
1808
}
1809
1810
if (tileDistance <= -1) {
1811
checkDist = -1;
1812
}
1813
else {
1814
sensors[0].position.y = sensors[tileDistance].position.y;
1815
sensors[0].angle = sensors[tileDistance].angle;
1816
1817
sensors[1].position.y = sensors[0].position.y;
1818
sensors[1].angle = sensors[0].angle;
1819
1820
sensors[2].position.y = sensors[0].position.y;
1821
sensors[2].angle = sensors[0].angle;
1822
1823
sensors[4].position.x = sensors[1].position.x;
1824
sensors[4].position.y = sensors[0].position.y + TO_FIXED(collisionOuter.bottom) + TO_FIXED(1);
1825
}
1826
1827
if (sensors[0].angle > 0xA2)
1828
collisionEntity->collisionMode = CMODE_LWALL;
1829
if (sensors[0].angle < 0x5E)
1830
collisionEntity->collisionMode = CMODE_RWALL;
1831
break;
1832
}
1833
1834
case CMODE_RWALL: {
1835
sensors[3].position.x += xVel;
1836
sensors[3].position.y += yVel;
1837
1838
if (collisionEntity->groundVel > 0)
1839
FloorCollision(&sensors[3]);
1840
1841
if (collisionEntity->groundVel < 0)
1842
RoofCollision(&sensors[3]);
1843
1844
if (sensors[3].collided) {
1845
yVel = 0;
1846
checkDist = -1;
1847
}
1848
1849
for (int32 i = 0; i < 3; i++) {
1850
sensors[i].position.x += xVel;
1851
sensors[i].position.y += yVel;
1852
FindRWallPosition(&sensors[i]);
1853
}
1854
1855
tileDistance = -1;
1856
for (int32 i = 0; i < 3; i++) {
1857
if (tileDistance > -1) {
1858
if (sensors[i].position.x > sensors[tileDistance].position.x && sensors[i].collided) {
1859
tileDistance = i;
1860
}
1861
}
1862
else if (sensors[i].collided) {
1863
tileDistance = i;
1864
}
1865
}
1866
1867
if (tileDistance <= -1) {
1868
checkDist = -1;
1869
}
1870
else {
1871
sensors[0].position.x = sensors[tileDistance].position.x;
1872
sensors[0].angle = sensors[tileDistance].angle;
1873
1874
sensors[1].position.x = sensors[0].position.x;
1875
sensors[1].angle = sensors[0].angle;
1876
1877
sensors[2].position.x = sensors[0].position.x;
1878
sensors[2].angle = sensors[0].angle;
1879
1880
sensors[4].position.x = sensors[1].position.x + TO_FIXED(collisionOuter.bottom) + TO_FIXED(1);
1881
sensors[4].position.y = sensors[1].position.y;
1882
}
1883
1884
if (sensors[0].angle < 0x1E)
1885
collisionEntity->collisionMode = CMODE_FLOOR;
1886
if (sensors[0].angle > 0x62)
1887
collisionEntity->collisionMode = CMODE_ROOF;
1888
break;
1889
}
1890
}
1891
1892
if (tileDistance != -1)
1893
collisionEntity->angle = sensors[0].angle;
1894
1895
if (!sensors[3].collided)
1896
SetPathGripSensors(sensors);
1897
else
1898
checkDist = -2;
1899
}
1900
1901
#if RETRO_REV0U
1902
int32 newCollisionMode = collisionEntity->tileCollisions == TILECOLLISION_DOWN ? CMODE_FLOOR : CMODE_ROOF;
1903
int32 newAngle = newCollisionMode << 6;
1904
#else
1905
int32 newCollisionMode = CMODE_FLOOR;
1906
int32 newAngle = newCollisionMode << 6;
1907
#endif
1908
1909
switch (collisionEntity->collisionMode) {
1910
case CMODE_FLOOR: {
1911
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
1912
collisionEntity->angle = sensors[0].angle;
1913
1914
if (!sensors[3].collided) {
1915
collisionEntity->position.x = sensors[4].position.x;
1916
}
1917
else {
1918
if (collisionEntity->groundVel > 0)
1919
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);
1920
1921
if (collisionEntity->groundVel < 0)
1922
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1923
1924
collisionEntity->groundVel = 0;
1925
collisionEntity->velocity.x = 0;
1926
}
1927
1928
collisionEntity->position.y = sensors[4].position.y;
1929
}
1930
else {
1931
collisionEntity->onGround = false;
1932
collisionEntity->collisionMode = newCollisionMode;
1933
collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
1934
collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
1935
if (collisionEntity->velocity.y < -TO_FIXED(16))
1936
collisionEntity->velocity.y = -TO_FIXED(16);
1937
1938
if (collisionEntity->velocity.y > TO_FIXED(16))
1939
collisionEntity->velocity.y = TO_FIXED(16);
1940
1941
collisionEntity->groundVel = collisionEntity->velocity.x;
1942
collisionEntity->angle = newAngle;
1943
if (!sensors[3].collided) {
1944
collisionEntity->position.x += collisionEntity->velocity.x;
1945
}
1946
else {
1947
if (collisionEntity->groundVel > 0)
1948
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);
1949
if (collisionEntity->groundVel < 0)
1950
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
1951
1952
collisionEntity->groundVel = 0;
1953
collisionEntity->velocity.x = 0;
1954
}
1955
1956
collisionEntity->position.y += collisionEntity->velocity.y;
1957
}
1958
break;
1959
}
1960
1961
case CMODE_LWALL: {
1962
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
1963
collisionEntity->angle = sensors[0].angle;
1964
}
1965
else {
1966
collisionEntity->onGround = false;
1967
collisionEntity->collisionMode = newCollisionMode;
1968
collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
1969
collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
1970
1971
if (collisionEntity->velocity.y < -TO_FIXED(16))
1972
collisionEntity->velocity.y = -TO_FIXED(16);
1973
1974
if (collisionEntity->velocity.y > TO_FIXED(16))
1975
collisionEntity->velocity.y = TO_FIXED(16);
1976
1977
collisionEntity->groundVel = collisionEntity->velocity.x;
1978
collisionEntity->angle = newAngle;
1979
}
1980
1981
if (!sensors[3].collided) {
1982
collisionEntity->position.x = sensors[4].position.x;
1983
collisionEntity->position.y = sensors[4].position.y;
1984
}
1985
else {
1986
if (collisionEntity->groundVel > 0)
1987
collisionEntity->position.y = sensors[3].position.y + TO_FIXED(collisionOuter.right) + TO_FIXED(1);
1988
1989
if (collisionEntity->groundVel < 0)
1990
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.left);
1991
1992
collisionEntity->groundVel = 0;
1993
collisionEntity->position.x = sensors[4].position.x;
1994
}
1995
break;
1996
}
1997
1998
case CMODE_ROOF: {
1999
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
2000
collisionEntity->angle = sensors[0].angle;
2001
2002
if (!sensors[3].collided) {
2003
collisionEntity->position.x = sensors[4].position.x;
2004
}
2005
else {
2006
if (collisionEntity->groundVel > 0)
2007
collisionEntity->position.x = sensors[3].position.x + TO_FIXED(collisionOuter.right);
2008
2009
if (collisionEntity->groundVel < 0)
2010
collisionEntity->position.x = sensors[3].position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);
2011
2012
collisionEntity->groundVel = 0;
2013
}
2014
}
2015
else {
2016
collisionEntity->onGround = false;
2017
collisionEntity->collisionMode = newCollisionMode;
2018
collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
2019
collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
2020
2021
if (collisionEntity->velocity.y < -TO_FIXED(16))
2022
collisionEntity->velocity.y = -TO_FIXED(16);
2023
2024
if (collisionEntity->velocity.y > TO_FIXED(16))
2025
collisionEntity->velocity.y = TO_FIXED(16);
2026
2027
collisionEntity->angle = newAngle;
2028
collisionEntity->groundVel = collisionEntity->velocity.x;
2029
2030
if (!sensors[3].collided) {
2031
collisionEntity->position.x += collisionEntity->velocity.x;
2032
}
2033
else {
2034
if (collisionEntity->groundVel > 0)
2035
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.right);
2036
2037
if (collisionEntity->groundVel < 0)
2038
collisionEntity->position.x = sensors[3].position.x - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
2039
2040
collisionEntity->groundVel = 0;
2041
}
2042
}
2043
collisionEntity->position.y = sensors[4].position.y;
2044
break;
2045
}
2046
2047
case CMODE_RWALL: {
2048
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
2049
collisionEntity->angle = sensors[0].angle;
2050
}
2051
else {
2052
collisionEntity->onGround = false;
2053
collisionEntity->collisionMode = newCollisionMode;
2054
collisionEntity->velocity.x = cos256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
2055
collisionEntity->velocity.y = sin256LookupTable[collisionEntity->angle] * collisionEntity->groundVel >> 8;
2056
2057
if (collisionEntity->velocity.y < -TO_FIXED(16))
2058
collisionEntity->velocity.y = -TO_FIXED(16);
2059
2060
if (collisionEntity->velocity.y > TO_FIXED(16))
2061
collisionEntity->velocity.y = TO_FIXED(16);
2062
2063
collisionEntity->groundVel = collisionEntity->velocity.x;
2064
collisionEntity->angle = newAngle;
2065
}
2066
2067
if (!sensors[3].collided) {
2068
collisionEntity->position.x = sensors[4].position.x;
2069
collisionEntity->position.y = sensors[4].position.y;
2070
}
2071
else {
2072
if (collisionEntity->groundVel > 0)
2073
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.right);
2074
2075
if (collisionEntity->groundVel < 0)
2076
collisionEntity->position.y = sensors[3].position.y - TO_FIXED(collisionOuter.left) + TO_FIXED(1);
2077
2078
collisionEntity->groundVel = 0;
2079
collisionEntity->position.x = sensors[4].position.x;
2080
}
2081
break;
2082
}
2083
2084
default: break;
2085
}
2086
}
2087
2088
void RSDK::SetPathGripSensors(CollisionSensor *sensors)
2089
{
2090
int32 offset = 0;
2091
#if RETRO_REV0U
2092
offset = useCollisionOffset ? COLLISION_OFFSET : 0;
2093
#else
2094
offset = collisionOffset;
2095
#endif
2096
2097
switch (collisionEntity->collisionMode) {
2098
case CMODE_FLOOR:
2099
sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);
2100
sensors[1].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);
2101
sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.bottom);
2102
sensors[3].position.y = sensors[4].position.y + offset;
2103
2104
sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionInner.left) - TO_FIXED(1);
2105
sensors[1].position.x = sensors[4].position.x;
2106
sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionInner.right);
2107
if (collisionEntity->groundVel <= 0)
2108
sensors[3].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.left) - TO_FIXED(1);
2109
else
2110
sensors[3].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.right);
2111
break;
2112
2113
case CMODE_LWALL:
2114
sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);
2115
sensors[1].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);
2116
sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionOuter.bottom);
2117
sensors[3].position.x = sensors[4].position.x;
2118
2119
sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionInner.left) - TO_FIXED(1);
2120
sensors[1].position.y = sensors[4].position.y;
2121
sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionInner.right);
2122
if (collisionEntity->groundVel <= 0)
2123
sensors[3].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.left);
2124
else
2125
sensors[3].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.right) - TO_FIXED(1);
2126
break;
2127
2128
case CMODE_ROOF:
2129
sensors[0].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2130
sensors[1].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2131
sensors[2].position.y = sensors[4].position.y - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2132
sensors[3].position.y = sensors[4].position.y - offset;
2133
2134
sensors[0].position.x = sensors[4].position.x + TO_FIXED(collisionInner.left) - TO_FIXED(1);
2135
sensors[1].position.x = sensors[4].position.x;
2136
sensors[2].position.x = sensors[4].position.x + TO_FIXED(collisionInner.right);
2137
if (collisionEntity->groundVel <= 0)
2138
sensors[3].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.left);
2139
else
2140
sensors[3].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.right) - TO_FIXED(1);
2141
break;
2142
2143
case CMODE_RWALL:
2144
sensors[0].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2145
sensors[1].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2146
sensors[2].position.x = sensors[4].position.x - TO_FIXED(collisionOuter.bottom) - TO_FIXED(1);
2147
sensors[3].position.x = sensors[4].position.x;
2148
2149
sensors[0].position.y = sensors[4].position.y + TO_FIXED(collisionInner.left) - TO_FIXED(1);
2150
sensors[1].position.y = sensors[4].position.y;
2151
sensors[2].position.y = sensors[4].position.y + TO_FIXED(collisionInner.right);
2152
if (collisionEntity->groundVel <= 0)
2153
sensors[3].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.left) - TO_FIXED(1);
2154
else
2155
sensors[3].position.y = sensors[4].position.y + TO_FIXED(collisionOuter.right);
2156
break;
2157
2158
default: break;
2159
}
2160
}
2161
2162
void RSDK::FindFloorPosition(CollisionSensor *sensor)
2163
{
2164
int32 posX = FROM_FIXED(sensor->position.x);
2165
int32 posY = FROM_FIXED(sensor->position.y);
2166
2167
int32 solid = 0;
2168
#if RETRO_REV0U
2169
if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)
2170
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2171
else
2172
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2173
#else
2174
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2175
#endif
2176
2177
int32 startY = posY;
2178
2179
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2180
if (collisionEntity->collisionLayers & layerID) {
2181
TileLayer *layer = &tileLayers[l];
2182
int32 colX = posX - layer->position.x;
2183
int32 colY = posY - layer->position.y;
2184
int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;
2185
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
2186
for (int32 i = 0; i < 3; ++i) {
2187
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
2188
uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];
2189
2190
if (tile < 0xFFFF && tile & solid) {
2191
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].floorMasks[colX & 0xF];
2192
int32 ty = cy + mask;
2193
int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;
2194
2195
if (mask < 0xFF) {
2196
if (!sensor->collided || startY >= ty) {
2197
if (abs(colY - ty) <= collisionTolerance) {
2198
#if RETRO_REV0U
2199
#if !RETRO_USE_ORIGINAL_CODE
2200
if (abs(sensor->angle - tileAngle) <= TILE_SIZE * 2 // * 3 causes some issues in certain tiles
2201
#else
2202
if (abs(sensor->angle - tileAngle) <= TILE_SIZE * 3
2203
#endif
2204
|| abs(sensor->angle - tileAngle + 0x100) <= floorAngleTolerance
2205
|| abs(sensor->angle - tileAngle - 0x100) <= floorAngleTolerance) {
2206
#else
2207
if (abs(sensor->angle - tileAngle) <= 0x20 || abs(sensor->angle - tileAngle + 0x100) <= 0x20
2208
|| abs(sensor->angle - tileAngle - 0x100) <= 0x20) {
2209
#endif
2210
sensor->collided = true;
2211
sensor->angle = tileAngle;
2212
sensor->position.y = TO_FIXED(ty + layer->position.y);
2213
startY = ty;
2214
i = 3;
2215
}
2216
}
2217
}
2218
}
2219
}
2220
}
2221
2222
cy += TILE_SIZE;
2223
}
2224
}
2225
2226
posX = layer->position.x + colX;
2227
posY = layer->position.y + colY;
2228
}
2229
}
2230
}
2231
void RSDK::FindLWallPosition(CollisionSensor *sensor)
2232
{
2233
int32 posX = FROM_FIXED(sensor->position.x);
2234
int32 posY = FROM_FIXED(sensor->position.y);
2235
2236
int32 solid = collisionEntity->collisionPlane ? ((1 << 14) | (1 << 15)) : ((1 << 12) | (1 << 13));
2237
2238
int32 startX = posX;
2239
2240
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2241
if (collisionEntity->collisionLayers & layerID) {
2242
TileLayer *layer = &tileLayers[l];
2243
int32 colX = posX - layer->position.x;
2244
int32 colY = posY - layer->position.y;
2245
int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;
2246
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
2247
for (int32 i = 0; i < 3; ++i) {
2248
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
2249
uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];
2250
2251
if (tile < 0xFFFF && tile & solid) {
2252
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].lWallMasks[colY & 0xF];
2253
int32 tx = cx + mask;
2254
int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].lWallAngle;
2255
2256
if (mask < 0xFF) {
2257
if (!sensor->collided || startX >= tx) {
2258
if (abs(colX - tx) <= collisionTolerance && abs(sensor->angle - tileAngle) <= wallAngleTolerance) {
2259
sensor->collided = true;
2260
sensor->angle = tileAngle;
2261
sensor->position.x = TO_FIXED(tx + layer->position.x);
2262
startX = tx;
2263
i = 3;
2264
}
2265
}
2266
}
2267
}
2268
}
2269
2270
cx += TILE_SIZE;
2271
}
2272
}
2273
2274
posX = layer->position.x + colX;
2275
posY = layer->position.y + colY;
2276
}
2277
}
2278
}
2279
void RSDK::FindRoofPosition(CollisionSensor *sensor)
2280
{
2281
int32 posX = FROM_FIXED(sensor->position.x);
2282
int32 posY = FROM_FIXED(sensor->position.y);
2283
2284
int32 solid = 0;
2285
#if RETRO_REV0U
2286
if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)
2287
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2288
else
2289
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2290
#else
2291
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2292
#endif
2293
2294
int32 startY = posY;
2295
2296
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2297
if (collisionEntity->collisionLayers & layerID) {
2298
TileLayer *layer = &tileLayers[l];
2299
int32 colX = posX - layer->position.x;
2300
int32 colY = posY - layer->position.y;
2301
int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;
2302
2303
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
2304
for (int32 i = 0; i < 3; ++i) {
2305
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
2306
uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];
2307
2308
if (tile < 0xFFFF && tile & solid) {
2309
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].roofMasks[colX & 0xF];
2310
int32 ty = cy + mask;
2311
int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;
2312
2313
if (mask < 0xFF) {
2314
if (!sensor->collided || startY <= ty) {
2315
if (abs(colY - ty) <= collisionTolerance && abs(sensor->angle - tileAngle) <= roofAngleTolerance) {
2316
sensor->collided = true;
2317
sensor->angle = tileAngle;
2318
sensor->position.y = TO_FIXED(ty + layer->position.y);
2319
startY = ty;
2320
i = 3;
2321
}
2322
}
2323
}
2324
}
2325
}
2326
2327
cy -= TILE_SIZE;
2328
}
2329
}
2330
2331
posX = layer->position.x + colX;
2332
posY = layer->position.y + colY;
2333
}
2334
}
2335
}
2336
void RSDK::FindRWallPosition(CollisionSensor *sensor)
2337
{
2338
int32 posX = FROM_FIXED(sensor->position.x);
2339
int32 posY = FROM_FIXED(sensor->position.y);
2340
2341
int32 solid = collisionEntity->collisionPlane ? ((1 << 14) | (1 << 15)) : ((1 << 12) | (1 << 13));
2342
2343
int32 startX = posX;
2344
2345
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2346
if (collisionEntity->collisionLayers & layerID) {
2347
TileLayer *layer = &tileLayers[l];
2348
int32 colX = posX - layer->position.x;
2349
int32 colY = posY - layer->position.y;
2350
int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;
2351
2352
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
2353
for (int32 i = 0; i < 3; ++i) {
2354
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
2355
uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];
2356
2357
if (tile < 0xFFFF && tile & solid) {
2358
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].rWallMasks[colY & 0xF];
2359
int32 tx = cx + mask;
2360
int32 tileAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].rWallAngle;
2361
2362
if (mask < 0xFF) {
2363
if (!sensor->collided || startX <= tx) {
2364
if (abs(colX - tx) <= collisionTolerance && abs(sensor->angle - tileAngle) <= wallAngleTolerance) {
2365
sensor->collided = true;
2366
sensor->angle = tileAngle;
2367
sensor->position.x = TO_FIXED(tx + layer->position.x);
2368
startX = tx;
2369
i = 3;
2370
}
2371
}
2372
}
2373
}
2374
}
2375
2376
cx -= TILE_SIZE;
2377
}
2378
}
2379
2380
posX = layer->position.x + colX;
2381
posY = layer->position.y + colY;
2382
}
2383
}
2384
}
2385
2386
void RSDK::FloorCollision(CollisionSensor *sensor)
2387
{
2388
int32 posX = FROM_FIXED(sensor->position.x);
2389
int32 posY = FROM_FIXED(sensor->position.y);
2390
2391
int32 solid = 0;
2392
#if RETRO_REV0U
2393
if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)
2394
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2395
else
2396
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2397
#else
2398
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2399
#endif
2400
2401
#if RETRO_REV0U
2402
int32 collideAngle = 0;
2403
int32 collidePos = 0x7FFFFFFF;
2404
#endif
2405
2406
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2407
if (collisionEntity->collisionLayers & layerID) {
2408
TileLayer *layer = &tileLayers[l];
2409
int32 colX = posX - layer->position.x;
2410
int32 colY = posY - layer->position.y;
2411
int32 cy = (colY & -TILE_SIZE) - TILE_SIZE;
2412
2413
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
2414
#if RETRO_REV0U
2415
int32 stepCount = 2;
2416
#else
2417
int32 stepCount = 3;
2418
#endif
2419
for (int32 i = 0; i < stepCount; ++i) {
2420
int32 step = TILE_SIZE;
2421
2422
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
2423
uint16 tile = layer->layout[(colX / TILE_SIZE) + ((cy / TILE_SIZE) << layer->widthShift)];
2424
if (tile < 0xFFFF && tile & solid) {
2425
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].floorMasks[colX & 0xF];
2426
#if RETRO_REV0U
2427
int32 ty = layer->position.y + cy + mask;
2428
#else
2429
int32 ty = cy + mask;
2430
#endif
2431
if (mask < 0xFF) {
2432
#if RETRO_REV0U
2433
step = -TILE_SIZE;
2434
if (colY < collidePos) {
2435
collideAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;
2436
collidePos = ty;
2437
i = stepCount;
2438
#else
2439
if (colY >= ty) {
2440
if (abs(colY - ty) <= collisionMinimumDistance) {
2441
sensor->collided = true;
2442
sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].floorAngle;
2443
sensor->position.y = TO_FIXED(ty + layer->position.y);
2444
i = stepCount;
2445
}
2446
#endif
2447
}
2448
}
2449
}
2450
}
2451
2452
cy += step;
2453
}
2454
}
2455
2456
posX = layer->position.x + colX;
2457
posY = layer->position.y + colY;
2458
}
2459
}
2460
2461
#if RETRO_REV0U
2462
if (collidePos != 0x7FFFFFFF) {
2463
int32 collideDist = sensor->position.y - TO_FIXED(collidePos);
2464
if (sensor->position.y >= TO_FIXED(collidePos) && collideDist <= collisionMinimumDistance) {
2465
sensor->angle = collideAngle;
2466
sensor->position.y = TO_FIXED(collidePos);
2467
sensor->collided = true;
2468
}
2469
}
2470
#endif
2471
}
2472
void RSDK::LWallCollision(CollisionSensor *sensor)
2473
{
2474
int32 posX = FROM_FIXED(sensor->position.x);
2475
int32 posY = FROM_FIXED(sensor->position.y);
2476
2477
int32 solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2478
2479
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2480
if (collisionEntity->collisionLayers & layerID) {
2481
TileLayer *layer = &tileLayers[l];
2482
int32 colX = posX - layer->position.x;
2483
int32 colY = posY - layer->position.y;
2484
int32 cx = (colX & -TILE_SIZE) - TILE_SIZE;
2485
2486
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
2487
for (int32 i = 0; i < 3; ++i) {
2488
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
2489
uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];
2490
2491
if (tile < 0xFFFF && tile & solid) {
2492
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].lWallMasks[colY & 0xF];
2493
int32 tx = cx + mask;
2494
if (mask < 0xFF && colX >= tx && abs(colX - tx) <= 14) {
2495
sensor->collided = true;
2496
sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].lWallAngle;
2497
sensor->position.x = TO_FIXED(tx + layer->position.x);
2498
i = 3;
2499
}
2500
}
2501
}
2502
2503
cx += TILE_SIZE;
2504
}
2505
}
2506
2507
posX = layer->position.x + colX;
2508
posY = layer->position.y + colY;
2509
}
2510
}
2511
}
2512
void RSDK::RoofCollision(CollisionSensor *sensor)
2513
{
2514
int32 posX = FROM_FIXED(sensor->position.x);
2515
int32 posY = FROM_FIXED(sensor->position.y);
2516
2517
int32 solid = 0;
2518
#if RETRO_REV0U
2519
if (collisionEntity->tileCollisions == TILECOLLISION_DOWN)
2520
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2521
else
2522
solid = collisionEntity->collisionPlane ? (1 << 14) : (1 << 12);
2523
#else
2524
solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2525
#endif
2526
2527
#if RETRO_REV0U
2528
int32 collideAngle = 0;
2529
int32 collidePos = -1;
2530
#endif
2531
2532
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2533
if (collisionEntity->collisionLayers & layerID) {
2534
TileLayer *layer = &tileLayers[l];
2535
int32 colX = posX - layer->position.x;
2536
int32 colY = posY - layer->position.y;
2537
int32 cy = (colY & -TILE_SIZE) + TILE_SIZE;
2538
2539
if (colX >= 0 && colX < TILE_SIZE * layer->xsize) {
2540
#if RETRO_REV0U
2541
int32 stepCount = 2;
2542
#else
2543
int32 stepCount = 3;
2544
#endif
2545
for (int32 i = 0; i < stepCount; ++i) {
2546
int32 step = -TILE_SIZE;
2547
2548
if (cy >= 0 && cy < TILE_SIZE * layer->ysize) {
2549
int32 tileX = (colX / TILE_SIZE);
2550
int32 tileY = (cy / TILE_SIZE);
2551
uint16 tile = layer->layout[tileX + (tileY << layer->widthShift)];
2552
2553
if (tile < 0xFFFF && tile & solid) {
2554
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].roofMasks[colX & 0xF];
2555
#if RETRO_REV0U
2556
int32 ty = layer->position.y + cy + mask;
2557
#else
2558
int32 ty = cy + mask;
2559
#endif
2560
if (mask < 0xFF) {
2561
#if RETRO_REV0U
2562
step = TILE_SIZE;
2563
if (colY > collidePos) {
2564
collideAngle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;
2565
collidePos = ty;
2566
i = stepCount;
2567
#else
2568
if (colY < ty) {
2569
if (abs(colY - ty) <= collisionMinimumDistance) {
2570
sensor->collided = true;
2571
sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].roofAngle;
2572
sensor->position.y = TO_FIXED(ty + layer->position.y);
2573
i = stepCount;
2574
}
2575
#endif
2576
}
2577
}
2578
}
2579
}
2580
2581
cy += step;
2582
}
2583
}
2584
2585
posX = layer->position.x + colX;
2586
posY = layer->position.y + colY;
2587
}
2588
}
2589
2590
#if RETRO_REV0U
2591
if (collidePos >= 0 && sensor->position.y <= TO_FIXED(collidePos) && sensor->position.y - TO_FIXED(collidePos) >= -collisionMinimumDistance) {
2592
sensor->angle = collideAngle;
2593
sensor->position.y = TO_FIXED(collidePos);
2594
sensor->collided = true;
2595
}
2596
#endif
2597
}
2598
void RSDK::RWallCollision(CollisionSensor *sensor)
2599
{
2600
int32 posX = FROM_FIXED(sensor->position.x);
2601
int32 posY = FROM_FIXED(sensor->position.y);
2602
2603
int32 solid = collisionEntity->collisionPlane ? (1 << 15) : (1 << 13);
2604
2605
for (int32 l = 0, layerID = 1; l < LAYER_COUNT; ++l, layerID <<= 1) {
2606
if (collisionEntity->collisionLayers & layerID) {
2607
TileLayer *layer = &tileLayers[l];
2608
int32 colX = posX - layer->position.x;
2609
int32 colY = posY - layer->position.y;
2610
int32 cx = (colX & -TILE_SIZE) + TILE_SIZE;
2611
2612
if (colY >= 0 && colY < TILE_SIZE * layer->ysize) {
2613
for (int32 i = 0; i < 3; ++i) {
2614
if (cx >= 0 && cx < TILE_SIZE * layer->xsize) {
2615
uint16 tile = layer->layout[(cx / TILE_SIZE) + ((colY / TILE_SIZE) << layer->widthShift)];
2616
2617
if (tile < 0xFFFF && tile & solid) {
2618
int32 mask = collisionMasks[collisionEntity->collisionPlane][tile & 0xFFF].rWallMasks[colY & 0xF];
2619
int32 tx = cx + mask;
2620
if (mask < 0xFF && colX <= tx && abs(colX - tx) <= 14) {
2621
sensor->collided = true;
2622
sensor->angle = tileInfo[collisionEntity->collisionPlane][tile & 0xFFF].rWallAngle;
2623
sensor->position.x = TO_FIXED(tx + layer->position.x);
2624
i = 3;
2625
}
2626
}
2627
}
2628
2629
cx -= TILE_SIZE;
2630
}
2631
}
2632
2633
posX = layer->position.x + colX;
2634
posY = layer->position.y + colY;
2635
}
2636
}
2637
}
2638
2639