#include #include #include #include "game.h" #include "const.h" #include "movement.h" #include "spawn.h" #include "system/mouse_io.h" #include "system/pc_stuff.h" #include "system/vga.h" #define SIGN(x) ((x > 0) - (x < 0)) void captureAndLimitMousePosition( struct RabbitPosition *pos, struct MouseStatus *mouseStatus ) { pos->oldMouseDotPosition[0] = pos->mouseDotPosition[0]; pos->oldMouseDotPosition[1] = pos->mouseDotPosition[1]; pos->mouseDotPosition[0] = mouseStatus->xPosition; pos->mouseDotPosition[1] = mouseStatus->yPosition; if (pos->mouseDotPosition[0] < MOUSE_LIMIT_LEFT) pos->mouseDotPosition[0] = MOUSE_LIMIT_LEFT; if (pos->mouseDotPosition[0] >= MOUSE_LIMIT_RIGHT) pos->mouseDotPosition[0] = MOUSE_LIMIT_RIGHT; if (pos->mouseDotPosition[1] < MOUSE_LIMIT_TOP) pos->mouseDotPosition[1] = MOUSE_LIMIT_TOP; if (pos->mouseDotPosition[1] >= MOUSE_LIMIT_BOTTOM) pos->mouseDotPosition[1] = MOUSE_LIMIT_BOTTOM; } // now this is ray casting struct TargetMousePosition { int x, y; }; void constrainMousePosition( struct RabbitPosition *pos, struct TargetMousePosition *target ) { int i, didChange, which; int currentX, currentY; float xCrossover, yCrossover; float maxDeltaX, maxDeltaY, fixHypotenuse, fixDistance; float currentDeltaX, currentDeltaY; float adjustedDeltaX, adjustedDeltaY; int considerX, considerY; maxDeltaX = sin(pos->mouseAngle * DEG2RAD) * MOUSE_DISTANCE; maxDeltaY = -cos(pos->mouseAngle * DEG2RAD) * MOUSE_DISTANCE; currentX = target->x + maxDeltaX; currentY = target->y + maxDeltaY; if (maxDeltaX > 0) { currentDeltaX = ARENA_RIGHT_EDGE - target->x; } else { currentDeltaX = target->x - ARENA_LEFT_EDGE; } if (maxDeltaY > 0) { currentDeltaY = ARENA_BOTTOM_EDGE - target->y; } else { currentDeltaY = target->y - ARENA_TOP_EDGE; } which = -1; considerY = currentY > ARENA_BOTTOM_EDGE || currentY < ARENA_TOP_EDGE; considerX = currentX > ARENA_RIGHT_EDGE || currentX < ARENA_LEFT_EDGE; if (considerX || considerY) { if (considerX && considerY) { which = currentDeltaY < currentDeltaX; } else { which = considerY; } } switch (which) { case 0: // x if (maxDeltaX > 0) { adjustedDeltaX = ARENA_RIGHT_EDGE - target->x; } else { adjustedDeltaX = -(target->x - ARENA_LEFT_EDGE); } adjustedDeltaY = (adjustedDeltaX / sin(pos->mouseAngle * DEG2RAD)) * -cos(pos->mouseAngle * DEG2RAD); if (fabs(adjustedDeltaY) > currentDeltaY) { adjustedDeltaY = SIGN(adjustedDeltaY) * currentDeltaY; } break; case 1: // y if (maxDeltaY > 0) { adjustedDeltaY = ARENA_BOTTOM_EDGE - target->y; } else { adjustedDeltaY = -(target->y - ARENA_TOP_EDGE); } adjustedDeltaX = (adjustedDeltaY / -cos(pos->mouseAngle * DEG2RAD)) * sin(pos->mouseAngle * DEG2RAD); if (fabs(adjustedDeltaX) > currentDeltaX) { adjustedDeltaX = SIGN(adjustedDeltaX) * currentDeltaX; } break; } if (which != -1) { currentX = target->x + adjustedDeltaX; currentY = target->y + adjustedDeltaY; } target->x = currentX; target->y = currentY; } void calculateTargetAngle( struct RabbitPosition *pos ) { float distanceX, distanceY; float angle, fixHypotenuse, fixDistance; struct TargetMousePosition targetMousePosition; // Position the cursor distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0]; distanceY = pos->mouseDotPosition[1] - pos->rabbitPosition[1]; // edge case -- top left corner if ( pos->rabbitPosition[0] == ARENA_LEFT_EDGE && pos->rabbitPosition[1] == ARENA_TOP_EDGE && distanceX == 0 && distanceY == 0 ) { angle = 315; } else { angle = atan2(distanceY, distanceX) * RAD2DEG + 90; if (angle < 0) angle += 360; } pos->mouseAngle = angle; pos->oldMousePosition[0] = pos->mousePosition[0]; pos->oldMousePosition[1] = pos->mousePosition[1]; targetMousePosition.x = pos->rabbitPosition[0]; targetMousePosition.y = pos->rabbitPosition[1]; constrainMousePosition(pos, &targetMousePosition); pos->mousePosition[0] = targetMousePosition.x; pos->mousePosition[1] = targetMousePosition.y; } void handleEnemyMovement( struct EnemyPosition enemyPosition[], struct RabbitPosition *pos ) { char hasExitedGate; int i, xDistance, yDistance; for (i = 0; i < ENEMY_MAX_COUNT; ++i) { if (!enemyPosition[i].isActive) continue; enemyPosition[i].enemyMoveDelayStep += 1; if (enemyPosition[i].enemyMoveDelayStep < ENEMY_MOVE_DELAY) continue; enemyPosition[i].enemyMoveDelayStep = 0; enemyPosition[i].oldEnemyPosition[0] = enemyPosition[i].enemyPosition[0]; enemyPosition[i].oldEnemyPosition[1] = enemyPosition[i].enemyPosition[1]; if (enemyPosition[i].hasLeftGate) { // which straight directon is the player closest to xDistance = pos->rabbitPosition[0] - enemyPosition[i].enemyPosition[0]; yDistance = pos->rabbitPosition[1] - enemyPosition[i].enemyPosition[1]; if (abs(xDistance) > abs(yDistance)) { enemyPosition[i].enemyPosition[0] += SIGN(xDistance) * ENEMY_MOVE_SPEED; } else { enemyPosition[i].enemyPosition[1] += SIGN(yDistance) * ENEMY_MOVE_SPEED; } } else { switch (enemyPosition[i].gateExitedFrom) { // top case 0: xDistance = 0; yDistance = ENEMY_MOVE_SPEED; break; // right case 1: xDistance = -ENEMY_MOVE_SPEED; yDistance = 0; break; // bottom case 2: xDistance = 0; yDistance = -ENEMY_MOVE_SPEED; break; // left case 3: xDistance = ENEMY_MOVE_SPEED; yDistance = 0; break; } enemyPosition[i].enemyPosition[0] += xDistance; enemyPosition[i].enemyPosition[1] += yDistance; switch (enemyPosition[i].gateExitedFrom) { case 0: hasExitedGate = ( enemyPosition[i].enemyPosition[1] > spawnPointRanges[0].top + spawnPointRanges[0].height ); break; case 1: hasExitedGate = ( enemyPosition[i].enemyPosition[0] < spawnPointRanges[1].left ); break; case 2: hasExitedGate = ( enemyPosition[i].enemyPosition[1] < spawnPointRanges[2].top ); break; case 3: hasExitedGate = ( enemyPosition[i].enemyPosition[0] > spawnPointRanges[3].left + spawnPointRanges[3].width ); break; } enemyPosition[i].hasLeftGate = hasExitedGate; } } } void handleRabbitMovement( struct RabbitPosition *pos, struct KeyboardKeydownState *keyboardKeydownState ) { int i; if (keyboardKeydownState->KEY_W) { pos->rabbitVelocity[1] -= RABBIT_MOTION_ACCELERATION; if (pos->rabbitVelocity[1] < -RABBIT_MOTION_MAX_SPEED) { pos->rabbitVelocity[1] = -RABBIT_MOTION_MAX_SPEED; } } if (keyboardKeydownState->KEY_S) { pos->rabbitVelocity[1] += RABBIT_MOTION_ACCELERATION; if (pos->rabbitVelocity[1] > RABBIT_MOTION_MAX_SPEED) { pos->rabbitVelocity[1] = RABBIT_MOTION_MAX_SPEED; } } if (keyboardKeydownState->KEY_A) { pos->rabbitVelocity[0] -= RABBIT_MOTION_ACCELERATION; if (pos->rabbitVelocity[0] < -RABBIT_MOTION_MAX_SPEED) { pos->rabbitVelocity[0] = -RABBIT_MOTION_MAX_SPEED; } } if (keyboardKeydownState->KEY_D) { pos->rabbitVelocity[0] += RABBIT_MOTION_ACCELERATION; if (pos->rabbitVelocity[0] > RABBIT_MOTION_MAX_SPEED) { pos->rabbitVelocity[0] = RABBIT_MOTION_MAX_SPEED; } } for (i = 0; i < 2; ++i) { pos->oldRabbitPosition[i] = pos->rabbitPosition[i]; pos->rabbitPosition[i] += (pos->rabbitVelocity[i] / RABBIT_MOTION_VELOCITY_DECAY); if (pos->rabbitPosition[i] < pos->rabbitLimits[0][i]) { pos->rabbitPosition[i] = pos->rabbitLimits[0][i]; } if (pos->rabbitPosition[i] >= pos->rabbitLimits[1][i]) { pos->rabbitPosition[i] = pos->rabbitLimits[1][i]; } if (pos->rabbitVelocity[i] < 0) { pos->rabbitVelocity[i] += RABBIT_MOTION_DRAG; if (pos->rabbitVelocity[i] > 0) pos->rabbitVelocity[i] = 0; } if (pos->rabbitVelocity[i] > 0) { pos->rabbitVelocity[i] -= RABBIT_MOTION_DRAG; if (pos->rabbitVelocity[i] < 0) pos->rabbitVelocity[i] = 0; } } }