way more stuff

This commit is contained in:
John Bintz 2024-02-27 08:16:16 -05:00
parent 20bf569dac
commit 7039359067
10 changed files with 251 additions and 83 deletions

160
combat.c
View File

@ -8,7 +8,18 @@
#include "const.h" #include "const.h"
#include "system/vga.h" #include "system/vga.h"
void setupBullet(struct BulletPosition *bullet, int x, int y, signed int doubleVelocityX, signed int doubleVelocityY, int velocity) { void setupBullet(
struct BulletPosition *bullet,
int x,
int y,
int angle,
int velocity
) {
signed int doubleVelocityX, doubleVelocityY;
doubleVelocityX = sin(angle * DEG2RAD) * (velocity * 2);
doubleVelocityY = -cos(angle * DEG2RAD) * (velocity * 2);
bullet->isActive = 1; bullet->isActive = 1;
bullet->willBeInactive = 0; bullet->willBeInactive = 0;
bullet->x = x; bullet->x = x;
@ -16,6 +27,7 @@ void setupBullet(struct BulletPosition *bullet, int x, int y, signed int doubleV
bullet->oldX = x; bullet->oldX = x;
bullet->oldY = y; bullet->oldY = y;
bullet->wallCooldown = 1; bullet->wallCooldown = 1;
bullet->angle = angle;
bullet->velocityXSteps[0] = doubleVelocityX / velocity; bullet->velocityXSteps[0] = doubleVelocityX / velocity;
bullet->velocityXSteps[1] = doubleVelocityX - bullet->velocityXSteps[0]; bullet->velocityXSteps[1] = doubleVelocityX - bullet->velocityXSteps[0];
@ -26,21 +38,20 @@ void setupBullet(struct BulletPosition *bullet, int x, int y, signed int doubleV
bullet->velocityStep = 0; bullet->velocityStep = 0;
} }
void attemptToFireRabbitBullet( int attemptToFireRabbitBullet(
struct RabbitPosition *rabbitPosition, struct RabbitPosition *rabbitPosition,
struct RabbitWeaponry *rabbitWeaponry, struct RabbitWeaponry *rabbitWeaponry,
struct BulletPosition rabbitBulletPosition[] struct BulletPosition rabbitBulletPosition[]
) { ) {
int okToFire = 0, i, mouseAngle; int okToFire = 0, i, mouseAngle;
signed int doubleVelocityX, doubleVelocityY;
int availableBullets[3]; int availableBullets[3];
if (rabbitWeaponry->cooldown > 0) return; if (rabbitWeaponry->cooldown > 0) return 0;
mouseAngle = rabbitPosition->mouseAngle; mouseAngle = rabbitPosition->mouseAngle;
rabbitWeaponry->cooldown = RABBIT_BULLET_COOLDOWN; rabbitWeaponry->cooldown = RABBIT_BULLET_COOLDOWN;
if (rabbitWeaponry->currentWeapon == SINGLE_SHOT_GUN) { if (rabbitWeaponry->currentWeapon == WEAPON_TYPE_SINGLE_SHOT_GUN) {
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (rabbitBulletPosition[i].isActive == 0) { if (rabbitBulletPosition[i].isActive == 0) {
okToFire = 1; okToFire = 1;
@ -49,20 +60,16 @@ void attemptToFireRabbitBullet(
} }
} }
if (!okToFire) return; if (!okToFire) return 0;
doubleVelocityX = sin(mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
doubleVelocityY = -cos(mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
setupBullet( setupBullet(
&rabbitBulletPosition[availableBullets[0]], &rabbitBulletPosition[availableBullets[0]],
rabbitPosition->rabbitPosition[0], rabbitPosition->rabbitPosition[0],
rabbitPosition->rabbitPosition[1], rabbitPosition->rabbitPosition[1],
doubleVelocityX, mouseAngle,
doubleVelocityY,
RABBIT_BULLET_VELOCITY RABBIT_BULLET_VELOCITY
); );
} else if (rabbitWeaponry->currentWeapon == SPREAD_SHOT_GUN) { } else if (rabbitWeaponry->currentWeapon == WEAPON_TYPE_SPREAD_SHOT_GUN) {
// make sure three bullets are available // make sure three bullets are available
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (rabbitBulletPosition[i].isActive == 0) { if (rabbitBulletPosition[i].isActive == 0) {
@ -71,23 +78,38 @@ void attemptToFireRabbitBullet(
} }
} }
if (okToFire < 3) return; if (okToFire < 3) return 0;
// if so, fire away // if so, fire away
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
doubleVelocityX = sin((mouseAngle + (i - 1) * RABBIT_BULLET_SHOTGUN_SPREAD) * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
doubleVelocityY = -cos((mouseAngle + (i - 1) * RABBIT_BULLET_SHOTGUN_SPREAD) * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
setupBullet( setupBullet(
&rabbitBulletPosition[availableBullets[i]], &rabbitBulletPosition[availableBullets[i]],
rabbitPosition->rabbitPosition[0], rabbitPosition->rabbitPosition[0],
rabbitPosition->rabbitPosition[1], rabbitPosition->rabbitPosition[1],
doubleVelocityX, mouseAngle + (i - 1) * RABBIT_BULLET_SHOTGUN_SPREAD,
doubleVelocityY,
RABBIT_BULLET_VELOCITY RABBIT_BULLET_VELOCITY
); );
} }
} }
return 1;
}
void limitBulletToArena(struct BulletPosition *bullet) {
if (bullet->x < MOUSE_LIMIT_LEFT) bullet->willBeInactive = 1;
if (bullet->x >= MOUSE_LIMIT_RIGHT) bullet->willBeInactive = 1;
if (bullet->y < MOUSE_LIMIT_TOP) bullet->willBeInactive = 1;
if (bullet->y >= MOUSE_LIMIT_BOTTOM) bullet->willBeInactive = 1;
}
void moveBullet(struct BulletPosition *bullet) {
bullet->oldX = bullet->x;
bullet->oldY = bullet->y;
bullet->x += bullet->velocityXSteps[bullet->velocityStep];
bullet->y += bullet->velocityYSteps[bullet->velocityStep];
bullet->velocityStep = 1 - bullet->velocityStep;
} }
void advanceRabbitBullets( void advanceRabbitBullets(
@ -99,23 +121,13 @@ void advanceRabbitBullets(
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (!rabbitBulletPosition[i].isActive) continue; if (!rabbitBulletPosition[i].isActive) continue;
rabbitBulletPosition[i].oldX = rabbitBulletPosition[i].x; moveBullet(&rabbitBulletPosition[i]);
rabbitBulletPosition[i].oldY = rabbitBulletPosition[i].y;
rabbitBulletPosition[i].x += rabbitBulletPosition[i].velocityXSteps[rabbitBulletPosition[i].velocityStep];
rabbitBulletPosition[i].y += rabbitBulletPosition[i].velocityYSteps[rabbitBulletPosition[i].velocityStep];
if (rabbitBulletPosition[i].wallCooldown == 0) { if (rabbitBulletPosition[i].wallCooldown == 0) {
if (rabbitBulletPosition[i].x < MOUSE_LIMIT_LEFT) rabbitBulletPosition[i].willBeInactive = 1; limitBulletToArena(&rabbitBulletPosition[i]);
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 { } else {
rabbitBulletPosition[i].wallCooldown--; rabbitBulletPosition[i].wallCooldown--;
} }
rabbitBulletPosition[i].velocityStep = 1 - rabbitBulletPosition[i].velocityStep;
} }
if (rabbitWeaponry->cooldown > 0) rabbitWeaponry->cooldown--; if (rabbitWeaponry->cooldown > 0) rabbitWeaponry->cooldown--;
@ -129,18 +141,8 @@ void advanceEnemyBullets(
for (i = 0; i < ENEMY_BULLET_LIMIT; ++i) { for (i = 0; i < ENEMY_BULLET_LIMIT; ++i) {
if (!enemyBulletPosition[i].isActive) continue; if (!enemyBulletPosition[i].isActive) continue;
enemyBulletPosition[i].oldX = enemyBulletPosition[i].x; moveBullet(&enemyBulletPosition[i]);
enemyBulletPosition[i].oldY = enemyBulletPosition[i].y; limitBulletToArena(&enemyBulletPosition[i]);
enemyBulletPosition[i].x += enemyBulletPosition[i].velocityXSteps[enemyBulletPosition[i].velocityStep];
enemyBulletPosition[i].y += enemyBulletPosition[i].velocityYSteps[enemyBulletPosition[i].velocityStep];
if (enemyBulletPosition[i].x < MOUSE_LIMIT_LEFT) enemyBulletPosition[i].willBeInactive = 1;
if (enemyBulletPosition[i].x >= MOUSE_LIMIT_RIGHT) enemyBulletPosition[i].willBeInactive = 1;
if (enemyBulletPosition[i].y < MOUSE_LIMIT_TOP) enemyBulletPosition[i].willBeInactive = 1;
if (enemyBulletPosition[i].y >= MOUSE_LIMIT_BOTTOM) enemyBulletPosition[i].willBeInactive = 1;
enemyBulletPosition[i].velocityStep = 1 - enemyBulletPosition[i].velocityStep;
} }
} }
@ -173,17 +175,13 @@ void attemptToFireEnemyBullets(
angle = atan2(distanceY, distanceX) * RAD2DEG + 90; angle = atan2(distanceY, distanceX) * RAD2DEG + 90;
if (angle < 0) angle += 360; if (angle < 0) angle += 360;
doubleVelocityX = sin(angle * DEG2RAD) * (ENEMY_BULLET_VELOCITY * 2);
doubleVelocityY = -cos(angle * DEG2RAD) * (ENEMY_BULLET_VELOCITY * 2);
availableBullet = availableBullets[--maxAvailableBulletIndex]; availableBullet = availableBullets[--maxAvailableBulletIndex];
setupBullet( setupBullet(
&enemyBulletPosition[availableBullet], &enemyBulletPosition[availableBullet],
enemyPosition[i].enemyPosition[0], enemyPosition[i].enemyPosition[0],
enemyPosition[i].enemyPosition[1], enemyPosition[i].enemyPosition[1],
doubleVelocityX, angle,
doubleVelocityY,
ENEMY_BULLET_VELOCITY ENEMY_BULLET_VELOCITY
); );
@ -229,7 +227,7 @@ void populateTargetCollision(struct CompiledSpriteRender *sprite) {
// We are hardcoding a 2x2 grid on the screen as our collision partitioning // We are hardcoding a 2x2 grid on the screen as our collision partitioning
// scheme. // scheme.
int rabbitGrid[4]; int rabbitGrid[4], powerupGrid[4];
int rabbitBulletGrid[4][RABBIT_BULLET_LIMIT]; int rabbitBulletGrid[4][RABBIT_BULLET_LIMIT];
int enemyGrid[4][ENEMY_MAX_COUNT]; int enemyGrid[4][ENEMY_MAX_COUNT];
int enemyBulletGrid[4][ENEMY_BULLET_LIMIT]; int enemyBulletGrid[4][ENEMY_BULLET_LIMIT];
@ -259,7 +257,8 @@ void buildCollisionGrids(
struct BulletPosition rabbitBulletPosition[], struct BulletPosition rabbitBulletPosition[],
struct BulletPosition enemyBulletPosition[], struct BulletPosition enemyBulletPosition[],
struct RabbitPosition *rabbitPosition, struct RabbitPosition *rabbitPosition,
struct EnemyPosition enemyPosition[] struct EnemyPosition enemyPosition[],
struct PlayerPowerup *playerPowerup
) { ) {
int grid, i; int grid, i;
@ -277,6 +276,23 @@ void buildCollisionGrids(
rabbitGrid[grid] = gridPosition[grid]; rabbitGrid[grid] = gridPosition[grid];
} }
switch (playerPowerup->type) {
case POWERUP_TYPE_SHOTGUN:
shotgun.x = playerPowerup->x;
shotgun.y = playerPowerup->y;
determineGridPositionsForSprite(&shotgun);
break;
case POWERUP_TYPE_SHIELD_KILLER:
shieldKiller.x = playerPowerup->x;
shieldKiller.y = playerPowerup->y;
determineGridPositionsForSprite(&shieldKiller);
break;
}
for (grid = 0; grid < 4; ++grid) {
powerupGrid[grid] = gridPosition[grid];
}
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (!rabbitBulletPosition[i].isActive) continue; if (!rabbitBulletPosition[i].isActive) continue;
if (rabbitBulletPosition[i].willBeInactive) continue; if (rabbitBulletPosition[i].willBeInactive) continue;
@ -358,6 +374,20 @@ int handleEnemyBulletToRabbitCollisions(
return hitCount; return hitCount;
} }
#define KNOCKBACK_DISTANCE (3)
void knockbackEnemy(
struct EnemyPosition *enemy,
int angle
) {
int distanceX, distanceY;
distanceX = sin(angle * DEG2RAD) * (KNOCKBACK_DISTANCE * 2);
distanceY = -cos(angle * DEG2RAD) * (KNOCKBACK_DISTANCE * 2);
enemy->enemyPosition[0] += distanceX;
enemy->enemyPosition[1] += distanceY;
}
void handleRabbitBulletToEnemyCollisions( void handleRabbitBulletToEnemyCollisions(
struct BulletPosition rabbitBulletPosition[], struct BulletPosition rabbitBulletPosition[],
struct EnemyPosition enemyPosition[] struct EnemyPosition enemyPosition[]
@ -386,7 +416,9 @@ void handleRabbitBulletToEnemyCollisions(
enemyPosition[resolvedEnemyIdx].hitPoints--; enemyPosition[resolvedEnemyIdx].hitPoints--;
if (enemyPosition[resolvedEnemyIdx].hitPoints < 1) { if (enemyPosition[resolvedEnemyIdx].hitPoints < 1) {
enemyPosition[resolvedEnemyIdx].willBeInactive = 1; enemyPosition[resolvedEnemyIdx].willBeInactive = 1;
enemyPosition[resolvedBulletIdx].wasKilled = 1; enemyPosition[resolvedEnemyIdx].wasKilled = 1;
} else {
knockbackEnemy(&enemyPosition[resolvedEnemyIdx], rabbitBulletPosition[resolvedBulletIdx].angle);
} }
rabbitBulletPosition[resolvedBulletIdx].willBeInactive = 1; rabbitBulletPosition[resolvedBulletIdx].willBeInactive = 1;
break; break;
@ -402,9 +434,6 @@ int handleRabbitToEnemyCollisions(
) { ) {
int enemyIdx, grid, resolvedEnemyIdx, hitCount = 0; int enemyIdx, grid, resolvedEnemyIdx, hitCount = 0;
// to start: brute force items
// possible performance improvements:
// * grid partitioning
rabbit.x = rabbitPosition->rabbitPosition[0]; rabbit.x = rabbitPosition->rabbitPosition[0];
rabbit.y = rabbitPosition->rabbitPosition[1]; rabbit.y = rabbitPosition->rabbitPosition[1];
populateSourceCollision(&rabbit); populateSourceCollision(&rabbit);
@ -430,3 +459,28 @@ int handleRabbitToEnemyCollisions(
return hitCount; return hitCount;
} }
int handleRabbitToPowerupCollision(
struct RabbitPosition *rabbitPosition,
struct PlayerPowerup *playerPowerup
) {
if (!playerPowerup->isActive) return 0;
rabbit.x = rabbitPosition->rabbitPosition[0];
rabbit.y = rabbitPosition->rabbitPosition[1];
populateSourceCollision(&rabbit);
switch (playerPowerup->type) {
case POWERUP_TYPE_SHOTGUN:
shotgun.x = playerPowerup->x;
shotgun.y = playerPowerup->y;
populateTargetCollision(&shotgun);
break;
case POWERUP_TYPE_SHIELD_KILLER:
shieldKiller.x = playerPowerup->x;
shieldKiller.y = playerPowerup->y;
populateTargetCollision(&shieldKiller);
break;
}
return isCollision();
}

View File

@ -1,4 +1,5 @@
void attemptToFireRabbitBullet( #include "movement.h"
int attemptToFireRabbitBullet(
struct RabbitPosition*, struct RabbitPosition*,
struct RabbitWeaponry*, struct RabbitWeaponry*,
struct BulletPosition[] struct BulletPosition[]
@ -28,7 +29,8 @@ void buildCollisionGrids(
struct BulletPosition rabbitBulletPosition[], struct BulletPosition rabbitBulletPosition[],
struct BulletPosition enemyBulletPosition[], struct BulletPosition enemyBulletPosition[],
struct RabbitPosition *rabbitPosition, struct RabbitPosition *rabbitPosition,
struct EnemyPosition enemyPosition[] struct EnemyPosition enemyPosition[],
struct PlayerPowerup *playerPowerup
); );
void attemptToFireEnemyBullets( void attemptToFireEnemyBullets(
@ -41,3 +43,8 @@ void attemptToFireEnemyBullets(
void advanceEnemyBullets( void advanceEnemyBullets(
struct BulletPosition[] struct BulletPosition[]
); );
int handleRabbitToPowerupCollision(
struct RabbitPosition *rabbitPosition,
struct PlayerPowerup *playerPowerup
);

View File

@ -46,3 +46,7 @@
#define DIFFICULTY_SPAWN_COOLDOWN_REDUCTION (2) #define DIFFICULTY_SPAWN_COOLDOWN_REDUCTION (2)
#define MINIMUM_ENEMY_SPAWN_COOLDOWN (3) #define MINIMUM_ENEMY_SPAWN_COOLDOWN (3)
#define VARIABLE_ENEMY_SPAWN_COOLDOWN (10) #define VARIABLE_ENEMY_SPAWN_COOLDOWN (10)
#define POWERUP_RESPAWN_COOLDOWN_PER_LEVEL (10)
#define SHOTGUN_ROUNDS_PER_LEVEL (25)

122
game.c
View File

@ -24,7 +24,8 @@ struct CompiledSpriteRender rabbit,
bullet, bullet,
enemy, enemy,
enemyBullet, enemyBullet,
shotgun; shotgun,
shieldKiller;
struct SpriteBounds bounds; struct SpriteBounds bounds;
struct BMPImage spritesheetImage; struct BMPImage spritesheetImage;
@ -68,12 +69,15 @@ void setupRabbitBullets() {
} }
rabbitWeaponry.cooldown = 0; rabbitWeaponry.cooldown = 0;
rabbitWeaponry.currentWeapon = SPREAD_SHOT_GUN; rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
rabbitWeaponry.currentWeaponRemainingRounds = 0;
} }
void setupPowerup() { void setupPowerup() {
playerPowerup.x = 100; playerPowerup.x = 100;
playerPowerup.y = 100; playerPowerup.y = 100;
playerPowerup.cooldown = 20 + rand() % 10;
playerPowerup.type = POWERUP_TYPE_SHOTGUN;
playerPowerup.isActive = 0; playerPowerup.isActive = 0;
} }
@ -103,12 +107,15 @@ int health = RABBIT_HEALTH_MAX;
int difficultyBands[10] = { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890 }; int difficultyBands[10] = { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890 };
void handleEnemyKills() { void handleEnemyKills() {
int i, hadKill; int i, hadKill, currentKillCount;
currentKillCount = 0;
for (i = 0; i < ENEMY_MAX_COUNT; ++i) { for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
if (enemyPosition[i].wasKilled) { if (enemyPosition[i].wasKilled) {
enemyPosition[i].wasKilled = 0; enemyPosition[i].wasKilled = 0;
kills++; kills++;
currentKillCount++;
health += ENEMY_KILL_HEALTH_GAIN; health += ENEMY_KILL_HEALTH_GAIN;
if (health > RABBIT_HEALTH_MAX) health = RABBIT_HEALTH_MAX; if (health > RABBIT_HEALTH_MAX) health = RABBIT_HEALTH_MAX;
@ -116,6 +123,18 @@ void handleEnemyKills() {
} }
} }
kills += currentKillCount;
playerPowerup.cooldown -= currentKillCount;
if (playerPowerup.cooldown <= 0) {
playerPowerup.x = TILE_SIZE + rand() % ((ARENA_WIDTH_TILES - 2) * TILE_SIZE);
playerPowerup.y = TILE_SIZE + rand() % ((ARENA_HEIGHT_TILES - 2) * TILE_SIZE);
playerPowerup.isActive = 1;
playerPowerup.cooldown = POWERUP_RESPAWN_COOLDOWN_PER_LEVEL * difficulty +
rand() % (POWERUP_RESPAWN_COOLDOWN_PER_LEVEL * difficulty);
}
if (hadKill) { if (hadKill) {
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
if (kills > difficultyBands[i]) { if (kills > difficultyBands[i]) {
@ -233,12 +252,20 @@ void setupPowerupSprites() {
SPRITE_SHOTGUN_OFFSET_X, SPRITE_SHOTGUN_OFFSET_X,
SPRITE_SHOTGUN_OFFSET_Y SPRITE_SHOTGUN_OFFSET_Y
); );
buildCompiledSprite(
&sprite_shieldKiller,
&shieldKiller,
SPRITE_SHIELDKILLER_WIDTH,
SPRITE_SHIELDKILLER_HEIGHT,
SPRITE_SHIELDKILLER_OFFSET_X,
SPRITE_SHIELDKILLER_OFFSET_Y
);
} }
void renderMouse() { void renderMouse() {
mouse.x = rabbitPosition.mousePosition[0]; mouse.x = rabbitPosition.mousePosition[0];
mouse.y = rabbitPosition.mousePosition[1]; mouse.y = rabbitPosition.mousePosition[1];
drawCompiledSprite(&mouse); drawCompiledSprite(&mouse);
drawPixel(rabbitPosition.mouseDotPosition[0], rabbitPosition.mouseDotPosition[1], 2); drawPixel(rabbitPosition.mouseDotPosition[0], rabbitPosition.mouseDotPosition[1], 2);
} }
@ -246,7 +273,6 @@ void renderMouse() {
void renderRabbit() { void renderRabbit() {
rabbit.x = rabbitPosition.rabbitPosition[0]; rabbit.x = rabbitPosition.rabbitPosition[0];
rabbit.y = rabbitPosition.rabbitPosition[1]; rabbit.y = rabbitPosition.rabbitPosition[1];
drawCompiledSprite(&rabbit); drawCompiledSprite(&rabbit);
} }
@ -258,7 +284,6 @@ void renderEnemies() {
enemy.x = enemyPosition[i].enemyPosition[0]; enemy.x = enemyPosition[i].enemyPosition[0];
enemy.y = enemyPosition[i].enemyPosition[1]; enemy.y = enemyPosition[i].enemyPosition[1];
drawCompiledSprite(&enemy); drawCompiledSprite(&enemy);
} }
} }
@ -271,7 +296,6 @@ void renderRabbitBullets() {
bullet.x = rabbitBulletPosition[i].x; bullet.x = rabbitBulletPosition[i].x;
bullet.y = rabbitBulletPosition[i].y; bullet.y = rabbitBulletPosition[i].y;
drawCompiledSprite(&bullet); drawCompiledSprite(&bullet);
} }
} }
@ -284,23 +308,36 @@ void renderEnemyBullets() {
enemyBullet.x = enemyBulletPosition[i].x; enemyBullet.x = enemyBulletPosition[i].x;
enemyBullet.y = enemyBulletPosition[i].y; enemyBullet.y = enemyBulletPosition[i].y;
drawCompiledSprite(&enemyBullet); drawCompiledSprite(&enemyBullet);
} }
} }
void renderPowerup() { void renderPowerup() {
shotgun.x = playerPowerup.x; if (!playerPowerup.isActive) return;
shotgun.y = playerPowerup.y;
drawCompiledSprite(&shotgun); switch (playerPowerup.type) {
case POWERUP_TYPE_SHOTGUN:
shotgun.x = playerPowerup.x;
shotgun.y = playerPowerup.y;
drawCompiledSprite(&shotgun);
break;
case POWERUP_TYPE_SHIELD_KILLER:
shieldKiller.x = playerPowerup.x;
shieldKiller.y = playerPowerup.y;
drawCompiledSprite(&shieldKiller);
break;
}
}
void drawOnlyArenaForSprite(struct CompiledSpriteRender *sprite) {
getSpriteBounds(sprite, &bounds);
drawOnlyArena(&bounds);
} }
void drawOnlyMouseArena() { void drawOnlyMouseArena() {
mouse.x = rabbitPosition.oldMousePosition[0]; mouse.x = rabbitPosition.oldMousePosition[0];
mouse.y = rabbitPosition.oldMousePosition[1]; mouse.y = rabbitPosition.oldMousePosition[1];
getSpriteBounds(&mouse, &bounds); drawOnlyArenaForSprite(&mouse);
drawOnlyArena(&bounds);
bounds.top = rabbitPosition.oldMouseDotPosition[1]; bounds.top = rabbitPosition.oldMouseDotPosition[1];
bounds.bottom = rabbitPosition.oldMouseDotPosition[1]; bounds.bottom = rabbitPosition.oldMouseDotPosition[1];
@ -312,8 +349,28 @@ void drawOnlyMouseArena() {
void drawOnlyRabbitArena() { void drawOnlyRabbitArena() {
rabbit.x = rabbitPosition.oldRabbitPosition[0]; rabbit.x = rabbitPosition.oldRabbitPosition[0];
rabbit.y = rabbitPosition.oldRabbitPosition[1]; rabbit.y = rabbitPosition.oldRabbitPosition[1];
getSpriteBounds(&rabbit, &bounds); drawOnlyArenaForSprite(&rabbit);
drawOnlyArena(&bounds); }
void drawOnlyPowerupArena() {
if (!playerPowerup.isActive) return;
switch (playerPowerup.type) {
case POWERUP_TYPE_SHOTGUN:
shotgun.x = playerPowerup.x;
shotgun.y = playerPowerup.y;
drawOnlyArenaForSprite(&shotgun);
break;
case POWERUP_TYPE_SHIELD_KILLER:
shieldKiller.x = playerPowerup.x;
shieldKiller.y = playerPowerup.y;
drawOnlyArenaForSprite(&shieldKiller);
break;
}
if (playerPowerup.willBeInactive) {
playerPowerup.isActive = 0;
}
} }
void drawOnlyEnemiesArena() { void drawOnlyEnemiesArena() {
@ -324,8 +381,7 @@ void drawOnlyEnemiesArena() {
enemy.x = enemyPosition[i].oldEnemyPosition[0]; enemy.x = enemyPosition[i].oldEnemyPosition[0];
enemy.y = enemyPosition[i].oldEnemyPosition[1]; enemy.y = enemyPosition[i].oldEnemyPosition[1];
getSpriteBounds(&enemy, &bounds); drawOnlyArenaForSprite(&enemy);
drawOnlyArena(&bounds);
if (enemyPosition[i].willBeInactive) { if (enemyPosition[i].willBeInactive) {
enemyPosition[i].isActive = 0; enemyPosition[i].isActive = 0;
@ -340,8 +396,7 @@ void drawOnlyRabbitBulletArena() {
bullet.x = rabbitBulletPosition[i].oldX; bullet.x = rabbitBulletPosition[i].oldX;
bullet.y = rabbitBulletPosition[i].oldY; bullet.y = rabbitBulletPosition[i].oldY;
getSpriteBounds(&bullet, &bounds); drawOnlyArenaForSprite(&bullet);
drawOnlyArena(&bounds);
if (rabbitBulletPosition[i].willBeInactive) { if (rabbitBulletPosition[i].willBeInactive) {
rabbitBulletPosition[i].isActive = 0; rabbitBulletPosition[i].isActive = 0;
@ -356,8 +411,7 @@ void drawOnlyEnemyBulletArena() {
enemyBullet.x = enemyBulletPosition[i].oldX; enemyBullet.x = enemyBulletPosition[i].oldX;
enemyBullet.y = enemyBulletPosition[i].oldY; enemyBullet.y = enemyBulletPosition[i].oldY;
getSpriteBounds(&enemyBullet, &bounds); drawOnlyArenaForSprite(&enemyBullet);
drawOnlyArena(&bounds);
if (enemyBulletPosition[i].willBeInactive) { if (enemyBulletPosition[i].willBeInactive) {
enemyBulletPosition[i].isActive = 0; enemyBulletPosition[i].isActive = 0;
@ -380,7 +434,10 @@ int setupGame() {
setupWallSprites(); setupWallSprites();
setupRabbitSprites(); setupRabbitSprites();
setupRabbitBullets(); setupRabbitBullets();
setupEnemies();
setupEnemyBullets();
setupEnemySprites(); setupEnemySprites();
setupPowerup();
setupPowerupSprites(); setupPowerupSprites();
setVideoMode(VIDEO_MODE_VGA_256); setVideoMode(VIDEO_MODE_VGA_256);
@ -420,11 +477,18 @@ void handleCombat() {
int didHitRabbit; int didHitRabbit;
if (mouseStatus.leftButtonDown) { if (mouseStatus.leftButtonDown) {
attemptToFireRabbitBullet( if (attemptToFireRabbitBullet(
&rabbitPosition, &rabbitPosition,
&rabbitWeaponry, &rabbitWeaponry,
rabbitBulletPosition rabbitBulletPosition
); )) {
if (rabbitWeaponry.currentWeaponRemainingRounds > 0) {
rabbitWeaponry.currentWeaponRemainingRounds--;
if (rabbitWeaponry.currentWeaponRemainingRounds == 0) {
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
}
}
}
} }
attemptToFireEnemyBullets( attemptToFireEnemyBullets(
@ -447,7 +511,8 @@ void handleCombat() {
rabbitBulletPosition, rabbitBulletPosition,
enemyBulletPosition, enemyBulletPosition,
&rabbitPosition, &rabbitPosition,
enemyPosition enemyPosition,
&playerPowerup
); );
didHitRabbit = handleRabbitToEnemyCollisions( didHitRabbit = handleRabbitToEnemyCollisions(
@ -472,6 +537,12 @@ void handleCombat() {
rabbitBulletPosition, rabbitBulletPosition,
enemyPosition enemyPosition
); );
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
playerPowerup.willBeInactive = 1;
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SPREAD_SHOT_GUN;
rabbitWeaponry.currentWeaponRemainingRounds = (difficulty + 1) * SHOTGUN_ROUNDS_PER_LEVEL;
}
} }
void handleRedraw() { void handleRedraw() {
@ -480,6 +551,7 @@ void handleRedraw() {
drawOnlyMouseArena(); drawOnlyMouseArena();
drawOnlyRabbitBulletArena(); drawOnlyRabbitBulletArena();
drawOnlyEnemyBulletArena(); drawOnlyEnemyBulletArena();
drawOnlyPowerupArena();
redrawArena(); redrawArena();
@ -524,6 +596,8 @@ int main(void) {
renderStringToDrawBuffer(buffer, 1, 0, 210, 20); renderStringToDrawBuffer(buffer, 1, 0, 210, 20);
sprintf(buffer, "Health: %d ", health); sprintf(buffer, "Health: %d ", health);
renderStringToDrawBuffer(buffer, 1, 0, 210, 30); renderStringToDrawBuffer(buffer, 1, 0, 210, 30);
sprintf(buffer, "Rnds: %d ", rabbitWeaponry.currentWeaponRemainingRounds);
renderStringToDrawBuffer(buffer, 1, 0, 210, 40);
waitStartVbl(); waitStartVbl();
copyDrawBufferToDisplay(); copyDrawBufferToDisplay();

2
game.h
View File

@ -8,7 +8,7 @@ struct SpawnPointRange {
int top, height; int top, height;
}; };
extern struct CompiledSpriteRender rabbit, mouse, bullet, enemy, enemyBullet; extern struct CompiledSpriteRender rabbit, mouse, bullet, enemy, enemyBullet, shotgun, shieldKiller;
extern struct SpriteBounds bounds; extern struct SpriteBounds bounds;
extern struct SpawnPointRange spawnPointRanges[]; extern struct SpawnPointRange spawnPointRanges[];

View File

@ -18,8 +18,8 @@ struct RabbitPosition {
int mouseAngle; int mouseAngle;
}; };
#define SINGLE_SHOT_GUN (0) #define WEAPON_TYPE_SINGLE_SHOT_GUN (0)
#define SPREAD_SHOT_GUN (1) #define WEAPON_TYPE_SPREAD_SHOT_GUN (1)
struct RabbitWeaponry { struct RabbitWeaponry {
char cooldown; char cooldown;
@ -27,12 +27,14 @@ struct RabbitWeaponry {
int currentWeaponRemainingRounds; int currentWeaponRemainingRounds;
}; };
#define POWERUP_SHOTGUN (0); #define POWERUP_TYPE_SHOTGUN (0)
#define POWERUP_TYPE_SHIELD_KILLER (1)
struct PlayerPowerup { struct PlayerPowerup {
int x, y; int x, y;
int cooldown; int cooldown;
char isActive; char isActive;
char willBeInactive;
char type; char type;
}; };
@ -48,6 +50,7 @@ struct BulletPosition {
signed int velocityXSteps[2], velocityYSteps[2]; signed int velocityXSteps[2], velocityYSteps[2];
int velocityStep; int velocityStep;
int angle;
}; };
struct EnemyPosition { struct EnemyPosition {

View File

@ -7,6 +7,7 @@ PUBLIC sprite_mouse_
PUBLIC sprite_bullet_ PUBLIC sprite_bullet_
PUBLIC sprite_enemy_ PUBLIC sprite_enemy_
PUBLIC sprite_shotgun_ PUBLIC sprite_shotgun_
PUBLIC sprite_shieldKiller_
.386 .386
.model flat,c .model flat,c
@ -1558,4 +1559,14 @@ sprite_shotgun_:
ret ret
sprite_shieldKiller_:
push ebp
mov ebp, esp
pop ebp
ret
end end

View File

@ -92,5 +92,16 @@ extern void sprite_shotgun(byte *);
#define SPRITE_SHOTGUN_OFFSET_Y (6) #define SPRITE_SHOTGUN_OFFSET_Y (6)
extern void sprite_shieldKiller(byte *);
#define SPRITE_SHIELDKILLER_WIDTH (12)
#define SPRITE_SHIELDKILLER_HEIGHT (12)
#define SPRITE_SHIELDKILLER_OFFSET_X (6)
#define SPRITE_SHIELDKILLER_OFFSET_Y (6)
#endif #endif

Binary file not shown.

View File

@ -37,3 +37,7 @@ files:
position: [32, 20] position: [32, 20]
dimensions: [12, 12] dimensions: [12, 12]
offset: [6, 6] offset: [6, 6]
shieldKiller:
position: [44, 20]
dimensions: [12, 12]
offset: [6, 6]