292 lines
8.3 KiB
C
292 lines
8.3 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#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;
|
|
}
|
|
}
|
|
}
|