diff --git a/clown3d-DS.nds b/clown3d-DS.nds index 8aa7f22..baf4546 100644 Binary files a/clown3d-DS.nds and b/clown3d-DS.nds differ diff --git a/collisions.c b/collisions.c index 6c28b14..bd1ea35 100644 --- a/collisions.c +++ b/collisions.c @@ -19,7 +19,6 @@ #include "headers.h" int which; -static int cf = 0; /* Compares using absolute values, equivalent to measuring the magnitude of a 1-dimensional @@ -116,7 +115,7 @@ float smallestOfThree(float a, float b, float c) \ /* in the case of a corner, wall-direction is ambiguous and must be \ inferred from player direction */ \ - if(which && !cc) \ + if(which) \ if(fabs(x_offs / node->box.move.x - z_offs / node->box.move.z) < 2.0) {\ if(fabs(move.x) > fabs(move.z)) { \ ratio = x_offs / node->box.move.x; which = 1; \ @@ -138,10 +137,6 @@ float smallestOfThree(float a, float b, float c) react.y = node->box.move.y * ratio; \ react.z = node->box.move.z * ratio; \ \ - if(node->type == PLAYER && \ - ratio == 0.0 && node->box.move.y == 0.0){ \ - glitch = 1; goto foundglitch; } \ - \ goto jump; \ } \ @@ -170,9 +165,7 @@ void resolveCollisions(game_obj* objs, void (*handler)(void*, void*)) vector move, react; float x_offs, y_offs, z_offs; float ratio; - int cc; - int glitch = 0; - int n; + int ee; /* * Objects marked as "stairs" have normal @@ -194,8 +187,8 @@ void resolveCollisions(game_obj* objs, void (*handler)(void*, void*)) for(node = objs; node != NULL; node = node->next) { if(node->type == SOLID) continue; /* heuristic: SOLIDs don't move ! */ - cc = 0; - glitch = 0; + + ee = 0; for(node2 = objs; node2 != NULL; node2 = node2->next) { if(node != node2 && node->type != NONE && node2->type != NONE) { @@ -292,16 +285,20 @@ void resolveCollisions(game_obj* objs, void (*handler)(void*, void*)) collision_found2: /* Simple edge-evasion, based on PypeBros' suggestion. - When a collision occurs,the projection of the player's - move vector on the "wall direction" (obtained here from - earlier collision calculations) is added for edge evasion. */ - if(node->type == PLAYER && which == 3 && !glitch && !cc) { - node->box.min.x += move.x * 0.4; - node->box.max.x += move.x * 0.4; + When a collision occurs, a request is made to add the + the projection of the player's move vector on the "wall direction" + (obtained here from earlier collision calculations). The + edge-evasion module will cancel all edge-evasion if a conflict + (edge-evasion in both wall-directions requested) is detected. + */ + + if(which == 3) { + edge_evade(node, node2, 0); + ee = 1; } - if(node->type == PLAYER && which == 1 && !glitch && !cc) { - node->box.min.z += move.z * 0.4; - node->box.max.z += move.z * 0.4; + if(which == 1) { + edge_evade(node, node2, 1); + ee = 1; } node->box.min.x += react.x; @@ -320,12 +317,10 @@ void resolveCollisions(game_obj* objs, void (*handler)(void*, void*)) } if(react.x || react.y || react.z) { - ++cc; (*handler)(node, node2); (*handler)(node2, node); } - foundglitch: /* * Restore the move vector as * it was prior to the Y axis / X, Z axes @@ -337,20 +332,10 @@ void resolveCollisions(game_obj* objs, void (*handler)(void*, void*)) } } - /* last resort for player collisions too complex for engine */ - if(node->type == PLAYER) { - player->data[PLAYER_GLITCHED] = 0; - if(glitch) { - player->data[PLAYER_GLITCHED] = 1; - player->data[PLAYER_X] -= player->data[PLAYER_GMX]; - player->data[PLAYER_Z] -= player->data[PLAYER_GMZ]; - cf = 0; - } else if(++cf >= 5 && (move.x || move.z)){ - player->data[PLAYER_GMX] = move.x; - player->data[PLAYER_GMZ] = move.z; - cf = 0; - } - } + /* If no edge-evasion requests occured in this collision + code frame, clear the edge-evasion data. (The edge-evasion + module is a state machine) */ + if(!ee) edge_evade(node, NULL, 0); } } diff --git a/edge-evasion.c b/edge-evasion.c new file mode 100644 index 0000000..cd7a23e --- /dev/null +++ b/edge-evasion.c @@ -0,0 +1,18 @@ + +#include "headers.h" + +void edge_evade(game_obj* who, game_obj* what, int dir) +{ + if(what) + who->ee_bits |= (2 << dir); + + if(!who->ee_targ) { + who->ee_targ = what; + who->ee_dir = dir; + } + + if(!what) { + who->ee_targ = NULL; + who->ee_bits = 0; + } +} diff --git a/headers.h b/headers.h index 2eb578d..86cf832 100644 --- a/headers.h +++ b/headers.h @@ -74,7 +74,9 @@ typedef struct game_obj vector coords; float rot; collisionBox box; - collisionBox last_good; + void* ee_targ; + int ee_dir; + int ee_bits; float* data; void* prev; void* next; @@ -99,10 +101,7 @@ enum PLAYER_MOVEY, PLAYER_MOVEZ, PLAYER_KEYS, - PLAYER_BULLET_TIMER, - PLAYER_GMX, - PLAYER_GMZ, - PLAYER_GLITCHED + PLAYER_BULLET_TIMER }; /* KEY */ @@ -263,6 +262,8 @@ extern void gc_push(game_obj* ptr); extern void gc_collect(void); extern void gc_stop(void); +extern void edge_evade(game_obj* who, game_obj* what, int dir); + #endif diff --git a/main.c b/main.c index acfcad4..198fc2b 100644 --- a/main.c +++ b/main.c @@ -266,6 +266,9 @@ void runGameFrame(void) resolveCollisions(objs, collisionFunction); + /* Edge-evasion */ + for(node = objs; node; node = node->next) + eeFunction(node); /* * Drawing code follows diff --git a/oop.c b/oop.c index a7c312d..6b012c4 100644 --- a/oop.c +++ b/oop.c @@ -95,3 +95,16 @@ void collisionFunction(void* va, void* vb) } } +void eeFunction(void* va) +{ + game_obj* a = va; + + if(a == NULL) return; + + switch(a->type){ + case PLAYER: + playerEdgeEvade(a); + break; + } +} + diff --git a/player.c b/player.c index 5de6636..0b45a9e 100644 --- a/player.c +++ b/player.c @@ -28,6 +28,8 @@ void playerInit(game_obj* a) a->data[PLAYER_DIRZ] = 0.0; a->data[PLAYER_KEYS] = 0; a->data[PLAYER_BULLET_TIMER] = 0.0f; + a->ee_targ = NULL; + a->ee_bits = 0; } void playerTick(game_obj* player) @@ -147,11 +149,9 @@ void playerTick(game_obj* player) player->data[PLAYER_ON_PLATFORM] = 0.0; - if(!player->data[PLAYER_GLITCHED]) { - player->data[PLAYER_X] += player->data[PLAYER_MOVEX]; - player->data[PLAYER_Y] += player->data[PLAYER_MOVEY]; - player->data[PLAYER_Z] += player->data[PLAYER_MOVEZ]; - } + player->data[PLAYER_X] += player->data[PLAYER_MOVEX]; + player->data[PLAYER_Y] += player->data[PLAYER_MOVEY]; + player->data[PLAYER_Z] += player->data[PLAYER_MOVEZ]; /* Player collision box and movement vector */ player->box.min.x = (float)(player->data[PLAYER_X] - 10); @@ -222,3 +222,13 @@ void playerDraw(game_obj* player) drawModelWithGL(turtleModel); } } + +void playerEdgeEvade(game_obj* player) +{ + if(player->ee_targ && player->ee_bits != 6) { + switch(player->ee_dir) { + case 0: player->data[PLAYER_X] += player->data[PLAYER_MOVEX]; break; + case 1: player->data[PLAYER_Z] += player->data[PLAYER_MOVEZ]; break; + } + } +}