starting on shotgun
This commit is contained in:
parent
36cb73a9b9
commit
71a6c65f3b
79
combat.c
79
combat.c
@ -15,6 +15,7 @@ void setupBullet(struct BulletPosition *bullet, int x, int y, signed int doubleV
|
||||
bullet->y = y;
|
||||
bullet->oldX = x;
|
||||
bullet->oldY = y;
|
||||
bullet->wallCooldown = 1;
|
||||
|
||||
bullet->velocityXSteps[0] = doubleVelocityX / velocity;
|
||||
bullet->velocityXSteps[1] = doubleVelocityX - bullet->velocityXSteps[0];
|
||||
@ -35,29 +36,47 @@ void attemptToFireRabbitBullet(
|
||||
|
||||
if (rabbitWeaponry->cooldown > 0) return;
|
||||
|
||||
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
|
||||
if (rabbitBulletPosition[i].isActive == 0) {
|
||||
okToFire = 1;
|
||||
availableBullet = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!okToFire) return;
|
||||
|
||||
rabbitWeaponry->cooldown = RABBIT_BULLET_COOLDOWN;
|
||||
|
||||
doubleVelocityX = sin(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
doubleVelocityY = -cos(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
if (rabbitWeaponry->currentWeapon == SINGLE_SHOT_GUN) {
|
||||
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
|
||||
if (rabbitBulletPosition[i].isActive == 0) {
|
||||
okToFire = 1;
|
||||
availableBullet = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setupBullet(
|
||||
&rabbitBulletPosition[availableBullet],
|
||||
rabbitPosition->rabbitPosition[0],
|
||||
rabbitPosition->rabbitPosition[1],
|
||||
doubleVelocityX,
|
||||
doubleVelocityY,
|
||||
RABBIT_BULLET_VELOCITY
|
||||
);
|
||||
if (!okToFire) return;
|
||||
|
||||
doubleVelocityX = sin(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
doubleVelocityY = -cos(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
|
||||
setupBullet(
|
||||
&rabbitBulletPosition[availableBullet],
|
||||
rabbitPosition->rabbitPosition[0],
|
||||
rabbitPosition->rabbitPosition[1],
|
||||
doubleVelocityX,
|
||||
doubleVelocityY,
|
||||
RABBIT_BULLET_VELOCITY
|
||||
);
|
||||
} else if (rabbitWeaponry->currentWeapon == SPREAD_SHOT_GUN) {
|
||||
// make sure three bullets are available
|
||||
// if so, fire away
|
||||
for (i = -1; i <= 1; ++i) {
|
||||
doubleVelocityX = sin(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
doubleVelocityY = -cos(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
|
||||
|
||||
setupBullet(
|
||||
&rabbitBulletPosition[availableBullet],
|
||||
rabbitPosition->rabbitPosition[0],
|
||||
rabbitPosition->rabbitPosition[1],
|
||||
doubleVelocityX,
|
||||
doubleVelocityY,
|
||||
RABBIT_BULLET_VELOCITY
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void advanceRabbitBullets(
|
||||
@ -75,10 +94,15 @@ void advanceRabbitBullets(
|
||||
rabbitBulletPosition[i].x += rabbitBulletPosition[i].velocityXSteps[rabbitBulletPosition[i].velocityStep];
|
||||
rabbitBulletPosition[i].y += rabbitBulletPosition[i].velocityYSteps[rabbitBulletPosition[i].velocityStep];
|
||||
|
||||
if (rabbitBulletPosition[i].x < MOUSE_LIMIT_LEFT) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].x >= MOUSE_LIMIT_RIGHT) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].y < MOUSE_LIMIT_TOP) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].y >= MOUSE_LIMIT_BOTTOM) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].wallCooldown == 0) {
|
||||
if (rabbitBulletPosition[i].x < MOUSE_LIMIT_LEFT) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].x >= MOUSE_LIMIT_RIGHT) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].y < MOUSE_LIMIT_TOP) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
if (rabbitBulletPosition[i].y >= MOUSE_LIMIT_BOTTOM) rabbitBulletPosition[i].willBeInactive = 1;
|
||||
} else {
|
||||
rabbitBulletPosition[i].wallCooldown--;
|
||||
}
|
||||
|
||||
|
||||
rabbitBulletPosition[i].velocityStep = 1 - rabbitBulletPosition[i].velocityStep;
|
||||
}
|
||||
@ -348,8 +372,11 @@ void handleRabbitBulletToEnemyCollisions(
|
||||
populateTargetCollision(&enemy);
|
||||
|
||||
if (isCollision()) {
|
||||
enemyPosition[resolvedEnemyIdx].willBeInactive = 1;
|
||||
enemyPosition[resolvedBulletIdx].wasKilled = 1;
|
||||
enemyPosition[resolvedEnemyIdx].hitPoints--;
|
||||
if (enemyPosition[resolvedEnemyIdx].hitPoints < 1) {
|
||||
enemyPosition[resolvedEnemyIdx].willBeInactive = 1;
|
||||
enemyPosition[resolvedBulletIdx].wasKilled = 1;
|
||||
}
|
||||
rabbitBulletPosition[resolvedBulletIdx].willBeInactive = 1;
|
||||
break;
|
||||
}
|
||||
|
9
const.h
9
const.h
@ -26,18 +26,19 @@
|
||||
#define DEG2RAD (3.14159/180)
|
||||
|
||||
#define ENEMY_MAX_COUNT (50)
|
||||
#define ENEMY_BULLET_LIMIT (ENEMY_MAX_COUNT / 2)
|
||||
#define ENEMY_BULLET_LIMIT (ENEMY_MAX_COUNT / 4)
|
||||
|
||||
#define ENEMY_MOVE_SPEED (1)
|
||||
#define ENEMY_MOVE_DELAY (3)
|
||||
#define ENEMY_BULLET_VELOCITY (RABBIT_BULLET_VELOCITY - 2)
|
||||
|
||||
#define ENEMY_FIRE_MIN_DELAY (35)
|
||||
#define ENEMY_FIRE_MIN_DELAY (45)
|
||||
#define ENEMY_FIRE_VARIABLE_DELAY (60)
|
||||
|
||||
#define ENEMY_BULLET_DAMAGE (4)
|
||||
#define ENEMY_COLLISION_DAMAGE (8)
|
||||
#define ENEMY_BULLET_DAMAGE (3)
|
||||
#define ENEMY_COLLISION_DAMAGE (6)
|
||||
#define ENEMY_KILL_HEALTH_GAIN (1)
|
||||
#define ENEMY_HIT_POINT_DIFFICULTY_INCREASE_EVERY (4)
|
||||
|
||||
#define BASE_ENEMY_SPAWN_COOLDOWN (30)
|
||||
#define DIFFICULTY_SPAWN_COOLDOWN_REDUCTION (2)
|
||||
|
51
game.c
51
game.c
@ -16,7 +16,7 @@
|
||||
#include "arena.h"
|
||||
#include "movement.h"
|
||||
#include "combat.h"
|
||||
|
||||
#include "game.h"
|
||||
|
||||
// TODO: centralize these outside of game.c
|
||||
struct CompiledSpriteRender rabbit, mouse, bullet, enemy, enemyBullet;
|
||||
@ -29,7 +29,10 @@ struct MouseStatus mouseStatus;
|
||||
|
||||
struct RabbitPosition rabbitPosition = {
|
||||
.rabbitPosition = { 60, 60 },
|
||||
.rabbitLimits = { { 20, 20 }, { 180, 180 } },
|
||||
.rabbitLimits = {
|
||||
{ 20, 20 },
|
||||
{ (ARENA_WIDTH_TILES - 1) * TILE_SIZE - 2, (ARENA_HEIGHT_TILES - 1) * TILE_SIZE - 2 }
|
||||
},
|
||||
.mousePosition = { 0, 0 },
|
||||
.rabbitVelocity = { 0, 0 },
|
||||
.mouseDotPosition = { 0, 0 }
|
||||
@ -39,19 +42,17 @@ struct BulletPosition rabbitBulletPosition[RABBIT_BULLET_LIMIT];
|
||||
struct BulletPosition enemyBulletPosition[ENEMY_BULLET_LIMIT];
|
||||
struct RabbitWeaponry rabbitWeaponry;
|
||||
|
||||
struct SpawnPointRange {
|
||||
int left, width;
|
||||
int top, height;
|
||||
};
|
||||
|
||||
struct SpawnPointRange spawnPointRanges[4] = {
|
||||
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = TILE_SIZE, .height = TILE_SIZE },
|
||||
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = (ARENA_HEIGHT_TILES - 2) * TILE_SIZE, .height = TILE_SIZE },
|
||||
{ .left = TILE_SIZE, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
|
||||
{ .left = (ARENA_WIDTH_TILES - 2) * TILE_SIZE, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
|
||||
// top
|
||||
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = TILE_SIZE - 8, .height = TILE_SIZE },
|
||||
// right
|
||||
{ .left = (ARENA_WIDTH_TILES - 1) * TILE_SIZE - 8, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
|
||||
// bottom
|
||||
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = (ARENA_HEIGHT_TILES - 1) * TILE_SIZE - 8, .height = TILE_SIZE },
|
||||
// left
|
||||
{ .left = TILE_SIZE - 8, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
|
||||
};
|
||||
|
||||
|
||||
void setupRabbitBullets() {
|
||||
int i;
|
||||
|
||||
@ -61,6 +62,7 @@ void setupRabbitBullets() {
|
||||
}
|
||||
|
||||
rabbitWeaponry.cooldown = 0;
|
||||
rabbitWeaponry.currentWeapon = SPREAD_SHOT_GUN;
|
||||
}
|
||||
|
||||
void setupEnemyBullets() {
|
||||
@ -113,8 +115,10 @@ void handleEnemyKills() {
|
||||
|
||||
void maybeSpawnEnemy() {
|
||||
char canSpawn;
|
||||
int i, availableEnemy;
|
||||
int spawnX, spawnY;
|
||||
int i, gate, availableEnemy, gatePlayerIsFacing;
|
||||
int spawnX, spawnY, spawnTry;
|
||||
|
||||
char buffer[20];
|
||||
|
||||
if (spawnCooldown-- > 0) return;
|
||||
|
||||
@ -128,14 +132,27 @@ void maybeSpawnEnemy() {
|
||||
|
||||
if (!canSpawn) return;
|
||||
|
||||
i = rand() % 4;
|
||||
// determine which gate the player is at and reduce the likelihood of
|
||||
// spawning from that gate
|
||||
// * 8 chances to spawn [0, 1] for each gate
|
||||
// * if the gate the player is looking at gets [0], reroll
|
||||
// * try three times max to limit cost of calculating
|
||||
for (spawnTry = 0; spawnTry < 3; ++spawnTry) {
|
||||
i = rand() % 12;
|
||||
gate = i / 3;
|
||||
|
||||
spawnX = spawnPointRanges[i].left + rand() % spawnPointRanges[i].width;
|
||||
spawnY = spawnPointRanges[i].top + rand() % spawnPointRanges[i].height;
|
||||
if (gatePlayerIsFacing == gate && i % 3 != 0) continue;
|
||||
}
|
||||
|
||||
spawnX = spawnPointRanges[gate].left + rand() % spawnPointRanges[gate].width;
|
||||
spawnY = spawnPointRanges[gate].top + rand() % spawnPointRanges[gate].height;
|
||||
|
||||
enemyPosition[availableEnemy].isActive = 1;
|
||||
enemyPosition[availableEnemy].willBeInactive = 0;
|
||||
enemyPosition[availableEnemy].wasKilled = 0;
|
||||
enemyPosition[availableEnemy].hitPoints = 1 + difficulty / ENEMY_HIT_POINT_DIFFICULTY_INCREASE_EVERY;
|
||||
enemyPosition[availableEnemy].hasLeftGate = 0;
|
||||
enemyPosition[availableEnemy].gateExitedFrom = gate;
|
||||
enemyPosition[availableEnemy].enemyMoveDelayStep = 0;
|
||||
enemyPosition[availableEnemy].enemyFireDelayStep = ENEMY_FIRE_MIN_DELAY + rand() % ENEMY_FIRE_VARIABLE_DELAY;
|
||||
enemyPosition[availableEnemy].enemyPosition[0] = spawnX;
|
||||
|
11
game.h
11
game.h
@ -1,4 +1,15 @@
|
||||
#ifndef __GAME_H__
|
||||
#define __GAME_H__
|
||||
|
||||
#include "system/vga.h"
|
||||
|
||||
struct SpawnPointRange {
|
||||
int left, width;
|
||||
int top, height;
|
||||
};
|
||||
|
||||
extern struct CompiledSpriteRender rabbit, mouse, bullet, enemy, enemyBullet;
|
||||
extern struct SpriteBounds bounds;
|
||||
extern struct SpawnPointRange spawnPointRanges[];
|
||||
|
||||
#endif
|
||||
|
69
movement.c
69
movement.c
@ -1,6 +1,7 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "game.h"
|
||||
#include "const.h"
|
||||
#include "movement.h"
|
||||
#include "system/mouse_io.h"
|
||||
@ -55,6 +56,7 @@ void handleEnemyMovement(
|
||||
struct EnemyPosition enemyPosition[],
|
||||
struct RabbitPosition *pos
|
||||
) {
|
||||
char hasExitedGate;
|
||||
int i, xDistance, yDistance;
|
||||
|
||||
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
||||
@ -64,17 +66,70 @@ void handleEnemyMovement(
|
||||
if (enemyPosition[i].enemyMoveDelayStep < ENEMY_MOVE_DELAY) continue;
|
||||
enemyPosition[i].enemyMoveDelayStep = 0;
|
||||
|
||||
// which straight directon is the player closest to
|
||||
xDistance = pos->rabbitPosition[0] - enemyPosition[i].enemyPosition[0];
|
||||
yDistance = pos->rabbitPosition[1] - enemyPosition[i].enemyPosition[1];
|
||||
|
||||
enemyPosition[i].oldEnemyPosition[0] = enemyPosition[i].enemyPosition[0];
|
||||
enemyPosition[i].oldEnemyPosition[1] = enemyPosition[i].enemyPosition[1];
|
||||
|
||||
if (abs(xDistance) > abs(yDistance)) {
|
||||
enemyPosition[i].enemyPosition[0] += SIGN(xDistance) * ENEMY_MOVE_SPEED;
|
||||
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 {
|
||||
enemyPosition[i].enemyPosition[1] += SIGN(yDistance) * ENEMY_MOVE_SPEED;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
movement.h
15
movement.h
@ -1,3 +1,6 @@
|
||||
#ifndef __MOVEMENT_H__
|
||||
#define __MOVEMENT_H__
|
||||
|
||||
#include "system/keyboard.h"
|
||||
|
||||
struct RabbitPosition {
|
||||
@ -15,8 +18,12 @@ struct RabbitPosition {
|
||||
int mouseAngle;
|
||||
};
|
||||
|
||||
#define SINGLE_SHOT_GUN (0)
|
||||
#define SPREAD_SHOT_GUN (1)
|
||||
|
||||
struct RabbitWeaponry {
|
||||
char cooldown;
|
||||
char currentWeapon;
|
||||
};
|
||||
|
||||
struct BulletPosition {
|
||||
@ -27,6 +34,8 @@ struct BulletPosition {
|
||||
int x, y;
|
||||
int oldX, oldY;
|
||||
|
||||
int wallCooldown;
|
||||
|
||||
signed int velocityXSteps[2], velocityYSteps[2];
|
||||
int velocityStep;
|
||||
};
|
||||
@ -37,6 +46,10 @@ struct EnemyPosition {
|
||||
char willBeInactive;
|
||||
char wasKilled;
|
||||
|
||||
char hitPoints;
|
||||
char hasLeftGate;
|
||||
char gateExitedFrom;
|
||||
|
||||
int enemyPosition[2];
|
||||
int oldEnemyPosition[2];
|
||||
|
||||
@ -48,3 +61,5 @@ void calculateTargetAngle(struct RabbitPosition*, struct MouseStatus*);
|
||||
void captureAndLimitMousePosition(struct RabbitPosition*, struct MouseStatus*);
|
||||
void handleRabbitMovement(struct RabbitPosition*, struct KeyboardKeydownState*);
|
||||
void handleEnemyMovement(struct EnemyPosition[], struct RabbitPosition*);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user