dos-vga-arena-shooter-game/movement.c

201 lines
6.1 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"
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;
}
void calculateTargetAngle(
struct RabbitPosition *pos
) {
int targetX, targetY;
float distanceX, distanceY;
float angle, fixHypotenuse, fixDistance;
// Position the cursor
distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0];
distanceY = pos->mouseDotPosition[1] - pos->rabbitPosition[1];
angle = atan2(distanceY, distanceX) * RAD2DEG + 90;
if (angle < 0) angle += 360;
distanceX = sin(angle * DEG2RAD) * MOUSE_DISTANCE;
distanceY = -cos(angle * DEG2RAD) * MOUSE_DISTANCE;
pos->oldMousePosition[0] = pos->mousePosition[0];
pos->oldMousePosition[1] = pos->mousePosition[1];
targetX = pos->rabbitPosition[0] + distanceX;
targetY = pos->rabbitPosition[1] + distanceY;
if (targetX > (ARENA_WIDTH_TILES - 1) * TILE_SIZE) {
fixDistance = targetX - ((ARENA_WIDTH_TILES - 1) * TILE_SIZE);
fixHypotenuse = fixDistance / sin(angle * DEG2RAD);
targetX = (ARENA_WIDTH_TILES - 1) * TILE_SIZE;
targetY = pos->rabbitPosition[1] + -cos(angle * DEG2RAD) * -fixHypotenuse;
}
pos->mousePosition[0] = targetX;
pos->mousePosition[1] = targetY;
pos->mouseAngle = angle;
}
#define SIGN(x) ((x > 0) - (x < 0))
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;
}
}
}