Created
April 2, 2014 14:34
-
-
Save Orpheon/9935407 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| char* get_commands(Navmesh *mesh, Character *character, Rect *current_rect, Rect *next_rect) | |
| { | |
| char *output = calloc(sizeof(char), OUTPUT_LENGTH); | |
| // If we're not inside our current/last rectangle, then we are in the air flying towards our destination, so we should just continue to do that | |
| if (character->x < current_rect->bottomleft.x || character->x > current_rect->bottomright.x || character->y < current_rect->topleft.y || character->y > current_rect->bottomleft.y) | |
| { | |
| // Get the equation of the parabola of our current falling (in the form y = ax^2 + bx + c) | |
| double a, b, c; | |
| a = GRAVITY/2; | |
| b = sqrt(character->hs*character->hs + character->vs*character->vs) - 2*a*character->x; | |
| c = character->y - a*character->x*character->x - b*character->x; | |
| // Test whether we'll land within the right boundaries with the current path | |
| double landing_x; | |
| // The determinant should always be positive since we will always be above the target (and gravity always points down) | |
| landing_x = (-b + sqrt(b*b - 4*a*(c-next_rect->bottomleft.y)))/(2*a); | |
| if (landing_x < next_rect->bottomleft.x) | |
| { | |
| // We're overshooting on the left side | |
| output[DIRECTION] = DIR_LEFT; | |
| } | |
| else if (landing_x > next_rect->bottomright.x) | |
| { | |
| // We're overshooting on the right side | |
| output[DIRECTION] = DIR_RIGHT; | |
| } | |
| else | |
| { | |
| // We're good, but we might get to where-ever faster if we continued moving in the direction we were going until now | |
| if (character->hs < 0) | |
| { | |
| output[DIRECTION] = DIR_LEFT; | |
| } | |
| else if (character->hs > 0) | |
| { | |
| output[DIRECTION] = DIR_RIGHT; | |
| } | |
| else | |
| { | |
| output[DIRECTION] = STANDSTILL; | |
| } | |
| } | |
| // It does not make any sense for us to jump right now, assuming no doublejump | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // Target rect is underneath us | |
| if (sign(current_rect->bottomright.x - next_rect->bottomright.x) != sign(current_rect->bottomleft.x - next_rect->bottomleft.x)) | |
| { | |
| // We need to find what side to walk/jump off of | |
| if (abs(current_rect->bottomleft.x - next_rect->bottomleft.x) < abs(current_rect->bottomright.x - next_rect->bottomright.x)) | |
| { | |
| output[DIRECTION] = DIR_LEFT; | |
| } | |
| else | |
| { | |
| output[DIRECTION] = DIR_RIGHT; | |
| } | |
| // There is no occasion where we'd want to jump, so don't do it | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // Target rect is on our right | |
| else if (current_rect->bottomright.x < next_rect->bottomleft.x) | |
| { | |
| // If target rect is low enough to just be able to walk over (flat or stair, both up or down) and near enough | |
| if (abs(current_rect->bottomright.y - next_rect->bottomleft.y) <= 6 && current_rect->bottomright.x+6 == next_rect->bottomleft.x) | |
| { | |
| // Just go on walking | |
| output[DIRECTION] = DIR_RIGHT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // We might need to jump | |
| else | |
| { | |
| // Get the equation of the parabola of walking off the edge (in the form y = ax^2 + bx + c) | |
| double a, b, c; | |
| a = GRAVITY/2; | |
| b = sqrt(character->hs*character->hs + character->vs*character->vs) - 2*a*current_rect->bottomright.x; | |
| c = current_rect->bottomright.y - a*current_rect->bottomright.x*current_rect->bottomright.x - b*current_rect->bottomright.x; | |
| double landing_x, determinant; | |
| // First check whether "walking off" even makes sense (it doesn't if we need to go higher) | |
| determinant = b*b - 4*a*(c-next_rect->bottomleft.y); | |
| if (determinant >= 0) | |
| { | |
| // A sqrt is always positive, and we want the larger one of the two solutions (the one on the right) | |
| landing_x = (-b + sqrt(determinant))/(2*a); | |
| if (landing_x >= next_rect->bottomleft.x && landing_x <= next_rect->bottomright.x) | |
| { | |
| // Just walking off at current speeds will grant us safe landing. | |
| // Do so. | |
| output[DIRECTION] = DIR_RIGHT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // Would we be going too far? | |
| if (landing_x > next_rect->bottomright.x) | |
| { | |
| // Should we already be braking now? | |
| c = character->y - a*character->x*character->x - b*character->x; | |
| determinant = b*b - 4*a*(c-next_rect->bottomleft.y); | |
| if (determinant >= 0) | |
| { | |
| // Check whether walking off from our -current- position would already be enough to overshoot | |
| landing_x = (-b + sqrt(determinant))/(2*a); | |
| if (landing_x > next_rect->bottomright.x) | |
| { | |
| // It's high time we brake | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| } | |
| } | |
| } | |
| // Would jumping help? | |
| // Calculate the jumping parabola from our current position | |
| double v_y = character->vs - 8; | |
| b = sqrt(character->hs*character->hs + v_y*v_y) - 2*a*character->x; | |
| c = character->y - a*character->x*character->x - b*character->x; | |
| // It is not possible for this sqrt to be invalid. If this were the case, the navmesh has to be broken | |
| landing_x = (-b + sqrt(b*b - 4*a*(c-next_rect->bottomleft.y)))/(2*a); | |
| if (landing_x >= next_rect->bottomleft.x && landing_x <= next_rect->bottomright.x) | |
| { | |
| // Jumping would work right now | |
| output[DIRECTION] = DIR_RIGHT; | |
| output[JUMP] = 1; | |
| return output; | |
| } | |
| // Nothing to do right now, lets just keep running in the right direction until something new happens | |
| output[DIRECTION] = DIR_RIGHT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| } | |
| // Target rect is on our left | |
| else if (current_rect->bottomleft.x > next_rect->bottomright.x) | |
| { | |
| // If target rect is low enough to just be able to walk over (flat or stair, both up or down) and near enough | |
| if (abs(current_rect->bottomright.y - next_rect->bottomleft.y) <= 6 && current_rect->bottomleft.x-6 == next_rect->bottomright.x) | |
| { | |
| // Just go on walking | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // We might need to jump | |
| else | |
| { | |
| // Get the equation of the parabola of walking off the edge (in the form y = ax^2 + bx + c) | |
| double a, b, c; | |
| a = GRAVITY/2; | |
| b = sqrt(character->hs*character->hs + character->vs*character->vs) - 2*a*current_rect->bottomleft.x; | |
| c = current_rect->bottomleft.y - a*current_rect->bottomleft.x*current_rect->bottomleft.x - b*current_rect->bottomleft.x; | |
| double landing_x, determinant; | |
| // First check whether "walking off" even makes sense (it doesn't if we need to go higher) | |
| determinant = b*b - 4*a*(c-next_rect->bottomright.y); | |
| if (determinant >= 0) | |
| { | |
| // A sqrt is always positive, and we want the larger one of the two solutions (the one on the right) | |
| landing_x = (-b + sqrt(determinant))/(2*a); | |
| if (landing_x >= next_rect->bottomleft.x && landing_x <= next_rect->bottomright.x) | |
| { | |
| // Just walking off at current speeds will grant us safe landing. | |
| // Do so. | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| // Would we be going too far? | |
| if (landing_x < next_rect->bottomleft.x) | |
| { | |
| // Should we already be braking now? | |
| c = character->y - a*character->x*character->x - b*character->x; | |
| determinant = b*b - 4*a*(c-next_rect->bottomleft.y); | |
| if (determinant >= 0) | |
| { | |
| // Check whether walking off from our -current- position would already be enough to overshoot | |
| landing_x = (-b + sqrt(determinant))/(2*a); | |
| if (landing_x < next_rect->bottomleft.x) | |
| { | |
| // It's high time we brake | |
| output[DIRECTION] = DIR_RIGHT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| } | |
| } | |
| } | |
| // Would jumping help? | |
| // Calculate the jumping parabola from our current position | |
| double v_y = character->vs - 8; | |
| b = sqrt(character->hs*character->hs + v_y*v_y) - 2*a*character->x; | |
| c = character->y - a*character->x*character->x - b*character->x; | |
| // It is not possible for this sqrt to be invalid. If this were the case, the navmesh has to be broken | |
| landing_x = (-b + sqrt(b*b - 4*a*(c-next_rect->bottomleft.y)))/(2*a); | |
| if (landing_x >= next_rect->bottomleft.x && landing_x <= next_rect->bottomright.x) | |
| { | |
| // Jumping would work right now | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 1; | |
| return output; | |
| } | |
| // Nothing to do right now, lets just keep running in the right direction until something new happens | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 0; | |
| return output; | |
| } | |
| } | |
| // Should never happen | |
| else | |
| { | |
| printf("\n\nERROR: Control end in move.c - This requires investigation."); | |
| fflush(stdout); | |
| output[DIRECTION] = DIR_LEFT; | |
| output[JUMP] = 1; | |
| return output; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment