continuing on unit tests, this is so easy
This commit is contained in:
parent
dd4fdad4be
commit
64de129fc4
|
@ -39,10 +39,15 @@ MovBytePtr = Data.define(:offset, :data)
|
||||||
ASM_TEMPLATE = <<~ASM
|
ASM_TEMPLATE = <<~ASM
|
||||||
<% sprites.each do |sprite| %>
|
<% sprites.each do |sprite| %>
|
||||||
PUBLIC <%= sprite.exported_name %><% end %>
|
PUBLIC <%= sprite.exported_name %><% end %>
|
||||||
|
PUBLIC _palette
|
||||||
|
|
||||||
.386
|
.386
|
||||||
.model flat,c
|
.model flat,c
|
||||||
|
|
||||||
|
.DATA
|
||||||
|
_palette:
|
||||||
|
<%= palette.flat_map { |color| color.to_asm_struct }.join("\n") %>
|
||||||
|
|
||||||
.CODE
|
.CODE
|
||||||
|
|
||||||
<% sprites.each do |sprite| %>
|
<% sprites.each do |sprite| %>
|
||||||
|
@ -69,9 +74,7 @@ H_TEMPLATE = <<~H
|
||||||
|
|
||||||
#define PALETTE_COLOR_COUNT (<%= palette.length %>)
|
#define PALETTE_COLOR_COUNT (<%= palette.length %>)
|
||||||
|
|
||||||
struct VGAColor palette[<%= palette.length %>] = {
|
extern struct VGAColor palette[<%= palette.length %>];
|
||||||
<%= palette.map(&:to_struct).join(",\n") %>
|
|
||||||
};
|
|
||||||
|
|
||||||
<% sprites.each do |sprite| %>
|
<% sprites.each do |sprite| %>
|
||||||
extern void <%= sprite.function_name %>(byte *);
|
extern void <%= sprite.function_name %>(byte *);
|
||||||
|
@ -154,8 +157,12 @@ sprite_data = []
|
||||||
palette = nil
|
palette = nil
|
||||||
|
|
||||||
VGAColor = Data.define(:red, :green, :blue) do
|
VGAColor = Data.define(:red, :green, :blue) do
|
||||||
def to_struct
|
def to_asm_struct
|
||||||
"{ #{red}, #{green}, #{blue} }"
|
[
|
||||||
|
" BYTE #{red}",
|
||||||
|
" BYTE #{green}",
|
||||||
|
" BYTE #{blue}"
|
||||||
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
wmake clean && wmake && dosbox-x -nolog game.exe
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
wmake clean && wmake test && dosbox-x -nolog test.exe
|
||||||
|
|
60
combat.c
60
combat.c
|
@ -2,11 +2,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "game.h"
|
#include "system/vga.h"
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "powerup.h"
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "system/vga.h"
|
|
||||||
|
|
||||||
void setupBullet(
|
void setupBullet(
|
||||||
struct BulletPosition *bullet,
|
struct BulletPosition *bullet,
|
||||||
|
@ -484,3 +485,58 @@ int handleRabbitToPowerupCollision(
|
||||||
|
|
||||||
return isCollision();
|
return isCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int processEnemyKillStates(
|
||||||
|
struct EnemyPosition enemyPosition[]
|
||||||
|
) {
|
||||||
|
int i, currentKillCount = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
||||||
|
if (enemyPosition[i].wasKilled) {
|
||||||
|
enemyPosition[i].wasKilled = 0;
|
||||||
|
currentKillCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentKillCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEnemyKills(
|
||||||
|
struct EnemyPosition enemyPosition[],
|
||||||
|
struct GlobalGameState *globalGameState,
|
||||||
|
struct PlayerPowerup *playerPowerup,
|
||||||
|
struct RabbitWeaponry *rabbitWeaponry
|
||||||
|
) {
|
||||||
|
int i, hadKill, currentKillCount;
|
||||||
|
|
||||||
|
currentKillCount = processEnemyKillStates(enemyPosition);
|
||||||
|
|
||||||
|
globalGameState->health += ENEMY_KILL_HEALTH_GAIN * currentKillCount;
|
||||||
|
if (globalGameState->health > RABBIT_HEALTH_MAX) globalGameState->health = RABBIT_HEALTH_MAX;
|
||||||
|
|
||||||
|
globalGameState->kills += currentKillCount;
|
||||||
|
|
||||||
|
processPowerupCooldown(
|
||||||
|
playerPowerup,
|
||||||
|
globalGameState,
|
||||||
|
rabbitWeaponry,
|
||||||
|
currentKillCount
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hadKill) {
|
||||||
|
for (i = 0; i < 10; ++i) {
|
||||||
|
if (globalGameState->kills > difficultyBands[i]) {
|
||||||
|
globalGameState->difficulty = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fireCurrentWeaponOnce(struct RabbitWeaponry *rabbitWeaponry) {
|
||||||
|
if (rabbitWeaponry->currentWeaponRemainingRounds > 0) {
|
||||||
|
rabbitWeaponry->currentWeaponRemainingRounds--;
|
||||||
|
if (rabbitWeaponry->currentWeaponRemainingRounds == 0) {
|
||||||
|
rabbitWeaponry->currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
8
combat.h
8
combat.h
|
@ -48,3 +48,11 @@ int handleRabbitToPowerupCollision(
|
||||||
struct RabbitPosition *rabbitPosition,
|
struct RabbitPosition *rabbitPosition,
|
||||||
struct PlayerPowerup *playerPowerup
|
struct PlayerPowerup *playerPowerup
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void handleEnemyKills(
|
||||||
|
struct EnemyPosition enemyPosition[],
|
||||||
|
struct GlobalGameState *globalGameState,
|
||||||
|
struct PlayerPowerup *playerPowerup
|
||||||
|
);
|
||||||
|
|
||||||
|
void fireCurrentWeaponOnce(struct RabbitWeaponry*);
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include "cutest-1.5/CuTest.h"
|
||||||
|
#include "combat.h"
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "movement.h"
|
||||||
|
#include "const.h"
|
||||||
|
#include "powerup.h"
|
||||||
|
|
||||||
|
int processEnemyKillStates(struct EnemyPosition[]);
|
||||||
|
|
||||||
|
void TestProcessEmenyKillStates(CuTest *tc) {
|
||||||
|
struct EnemyPosition enemyPosition[ENEMY_MAX_COUNT];
|
||||||
|
int i, result;
|
||||||
|
|
||||||
|
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
||||||
|
enemyPosition[i].wasKilled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enemyPosition[0].wasKilled = 1;
|
||||||
|
enemyPosition[ENEMY_MAX_COUNT - 1].wasKilled = 1;
|
||||||
|
|
||||||
|
result = processEnemyKillStates(enemyPosition);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFireCurrentWeaponOnce_NoRoundsRemaining(CuTest *tc) {
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
rabbitWeaponry.currentWeaponRemainingRounds = 0;
|
||||||
|
rabbitWeaponry.currentWeapon = 99;
|
||||||
|
|
||||||
|
fireCurrentWeaponOnce(&rabbitWeaponry);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 99, rabbitWeaponry.currentWeapon);
|
||||||
|
CuAssertIntEquals(tc, 0, rabbitWeaponry.currentWeaponRemainingRounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFireCurrentWeaponOnce_OneRoundRemaining(CuTest *tc) {
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
rabbitWeaponry.currentWeaponRemainingRounds = 1;
|
||||||
|
rabbitWeaponry.currentWeapon = 99;
|
||||||
|
|
||||||
|
fireCurrentWeaponOnce(&rabbitWeaponry);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, WEAPON_TYPE_SINGLE_SHOT_GUN, rabbitWeaponry.currentWeapon);
|
||||||
|
CuAssertIntEquals(tc, 0, rabbitWeaponry.currentWeaponRemainingRounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFireCurrentWeaponOnce_TwoRoundsRemaining(CuTest *tc) {
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
rabbitWeaponry.currentWeaponRemainingRounds = 2;
|
||||||
|
rabbitWeaponry.currentWeapon = 99;
|
||||||
|
|
||||||
|
fireCurrentWeaponOnce(&rabbitWeaponry);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 99, rabbitWeaponry.currentWeapon);
|
||||||
|
CuAssertIntEquals(tc, 1, rabbitWeaponry.currentWeaponRemainingRounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CuSuite *CombatGetSuite() {
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, TestProcessEmenyKillStates);
|
||||||
|
SUITE_ADD_TEST(suite, TestFireCurrentWeaponOnce_NoRoundsRemaining);
|
||||||
|
SUITE_ADD_TEST(suite, TestFireCurrentWeaponOnce_OneRoundRemaining);
|
||||||
|
SUITE_ADD_TEST(suite, TestFireCurrentWeaponOnce_TwoRoundsRemaining);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "system/vga.h"
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
int difficultyBands[MAX_DIFFICULTY] = { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890 };
|
||||||
|
struct SpriteBounds bounds;
|
||||||
|
|
||||||
|
// TODO: centralize these outside of game.c
|
||||||
|
struct CompiledSpriteRender rabbit,
|
||||||
|
mouse,
|
||||||
|
bullet,
|
||||||
|
enemy,
|
||||||
|
enemyBullet,
|
||||||
|
shotgun,
|
||||||
|
shieldKiller;
|
19
const.h
19
const.h
|
@ -1,3 +1,8 @@
|
||||||
|
#ifndef __CONST_H__
|
||||||
|
#define __CONST_H__
|
||||||
|
|
||||||
|
#include "system/vga.h"
|
||||||
|
|
||||||
#define TILE_SIZE (20)
|
#define TILE_SIZE (20)
|
||||||
#define ARENA_WIDTH_TILES (10)
|
#define ARENA_WIDTH_TILES (10)
|
||||||
#define ARENA_HEIGHT_TILES (10)
|
#define ARENA_HEIGHT_TILES (10)
|
||||||
|
@ -50,3 +55,17 @@
|
||||||
#define POWERUP_RESPAWN_COOLDOWN_PER_LEVEL (10)
|
#define POWERUP_RESPAWN_COOLDOWN_PER_LEVEL (10)
|
||||||
|
|
||||||
#define SHOTGUN_ROUNDS_PER_LEVEL (25)
|
#define SHOTGUN_ROUNDS_PER_LEVEL (25)
|
||||||
|
#define MAX_DIFFICULTY (10)
|
||||||
|
|
||||||
|
extern int difficultyBands[];
|
||||||
|
extern struct SpriteBounds bounds;
|
||||||
|
|
||||||
|
extern struct CompiledSpriteRender rabbit,
|
||||||
|
mouse,
|
||||||
|
bullet,
|
||||||
|
enemy,
|
||||||
|
enemyBullet,
|
||||||
|
shotgun,
|
||||||
|
shieldKiller;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
95
game.c
95
game.c
|
@ -18,16 +18,7 @@
|
||||||
#include "combat.h"
|
#include "combat.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "spawn.h"
|
#include "spawn.h"
|
||||||
|
#include "powerup.h"
|
||||||
// TODO: centralize these outside of game.c
|
|
||||||
struct CompiledSpriteRender rabbit,
|
|
||||||
mouse,
|
|
||||||
bullet,
|
|
||||||
enemy,
|
|
||||||
enemyBullet,
|
|
||||||
shotgun,
|
|
||||||
shieldKiller;
|
|
||||||
struct SpriteBounds bounds;
|
|
||||||
|
|
||||||
struct BMPImage spritesheetImage;
|
struct BMPImage spritesheetImage;
|
||||||
struct VGAColor vgaColors[256];
|
struct VGAColor vgaColors[256];
|
||||||
|
@ -50,6 +41,13 @@ struct BulletPosition enemyBulletPosition[ENEMY_BULLET_LIMIT];
|
||||||
struct RabbitWeaponry rabbitWeaponry;
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
struct PlayerPowerup playerPowerup;
|
struct PlayerPowerup playerPowerup;
|
||||||
|
|
||||||
|
struct GlobalGameState globalGameState = {
|
||||||
|
.spawnCooldown = 0,
|
||||||
|
.difficulty = 0,
|
||||||
|
.kills = 0,
|
||||||
|
.health = RABBIT_HEALTH_MAX
|
||||||
|
};
|
||||||
|
|
||||||
void setupRabbitBullets() {
|
void setupRabbitBullets() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -66,7 +64,7 @@ void setupRabbitBullets() {
|
||||||
void setupPowerup() {
|
void setupPowerup() {
|
||||||
playerPowerup.x = 100;
|
playerPowerup.x = 100;
|
||||||
playerPowerup.y = 100;
|
playerPowerup.y = 100;
|
||||||
playerPowerup.cooldown = 20 + rand() % 10;
|
playerPowerup.cooldown = determinePowerupCooldownTime(globalGameState.difficulty);
|
||||||
playerPowerup.type = POWERUP_TYPE_SHOTGUN;
|
playerPowerup.type = POWERUP_TYPE_SHOTGUN;
|
||||||
playerPowerup.isActive = 0;
|
playerPowerup.isActive = 0;
|
||||||
}
|
}
|
||||||
|
@ -89,54 +87,6 @@ void setupEnemies() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GlobalGameState globalGameState = {
|
|
||||||
.spawnCooldown = 0,
|
|
||||||
.difficulty = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
int kills = 0;
|
|
||||||
int health = RABBIT_HEALTH_MAX;
|
|
||||||
|
|
||||||
int difficultyBands[10] = { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890 };
|
|
||||||
|
|
||||||
void handleEnemyKills() {
|
|
||||||
int i, hadKill, currentKillCount;
|
|
||||||
|
|
||||||
currentKillCount = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
|
||||||
if (enemyPosition[i].wasKilled) {
|
|
||||||
enemyPosition[i].wasKilled = 0;
|
|
||||||
kills++;
|
|
||||||
currentKillCount++;
|
|
||||||
health += ENEMY_KILL_HEALTH_GAIN;
|
|
||||||
if (health > RABBIT_HEALTH_MAX) health = RABBIT_HEALTH_MAX;
|
|
||||||
|
|
||||||
hadKill = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 * globalGameState.difficulty +
|
|
||||||
rand() % (POWERUP_RESPAWN_COOLDOWN_PER_LEVEL * globalGameState.difficulty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hadKill) {
|
|
||||||
for (i = 0; i < 10; ++i) {
|
|
||||||
if (kills > difficultyBands[i]) {
|
|
||||||
globalGameState.difficulty = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupEnemySprites() {
|
void setupEnemySprites() {
|
||||||
buildCompiledSprite(
|
buildCompiledSprite(
|
||||||
&sprite_enemy,
|
&sprite_enemy,
|
||||||
|
@ -419,12 +369,9 @@ void handleCombat() {
|
||||||
&rabbitWeaponry,
|
&rabbitWeaponry,
|
||||||
rabbitBulletPosition
|
rabbitBulletPosition
|
||||||
)) {
|
)) {
|
||||||
if (rabbitWeaponry.currentWeaponRemainingRounds > 0) {
|
fireCurrentWeaponOnce(
|
||||||
rabbitWeaponry.currentWeaponRemainingRounds--;
|
&rabbitWeaponry
|
||||||
if (rabbitWeaponry.currentWeaponRemainingRounds == 0) {
|
);
|
||||||
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +405,7 @@ void handleCombat() {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (didHitRabbit) {
|
if (didHitRabbit) {
|
||||||
health -= ENEMY_COLLISION_DAMAGE * didHitRabbit;
|
globalGameState.health -= ENEMY_COLLISION_DAMAGE * didHitRabbit;
|
||||||
}
|
}
|
||||||
|
|
||||||
didHitRabbit = handleEnemyBulletToRabbitCollisions(
|
didHitRabbit = handleEnemyBulletToRabbitCollisions(
|
||||||
|
@ -467,7 +414,7 @@ void handleCombat() {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (didHitRabbit) {
|
if (didHitRabbit) {
|
||||||
health -= ENEMY_BULLET_DAMAGE * didHitRabbit;
|
globalGameState.health -= ENEMY_BULLET_DAMAGE * didHitRabbit;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRabbitBulletToEnemyCollisions(
|
handleRabbitBulletToEnemyCollisions(
|
||||||
|
@ -478,7 +425,7 @@ void handleCombat() {
|
||||||
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
|
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
|
||||||
playerPowerup.willBeInactive = 1;
|
playerPowerup.willBeInactive = 1;
|
||||||
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SPREAD_SHOT_GUN;
|
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SPREAD_SHOT_GUN;
|
||||||
rabbitWeaponry.currentWeaponRemainingRounds = (globalGameState.difficulty + 1) * SHOTGUN_ROUNDS_PER_LEVEL;
|
rabbitWeaponry.currentWeaponRemainingRounds = determineShotgunRounds(globalGameState.difficulty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,14 +478,20 @@ int main(void) {
|
||||||
handleMovement();
|
handleMovement();
|
||||||
handleRedraw();
|
handleRedraw();
|
||||||
handleCombat();
|
handleCombat();
|
||||||
handleEnemyKills();
|
handleEnemyKills(
|
||||||
|
enemyPosition,
|
||||||
|
&globalGameState,
|
||||||
|
&playerPowerup
|
||||||
|
);
|
||||||
|
|
||||||
sprintf(buffer, "Hit: %d", kills);
|
sprintf(buffer, "Hit: %d", globalGameState.kills);
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 20);
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 20);
|
||||||
sprintf(buffer, "Health: %d ", health);
|
sprintf(buffer, "Health: %d ", globalGameState.health);
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 30);
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 30);
|
||||||
sprintf(buffer, "Rnds: %d ", rabbitWeaponry.currentWeaponRemainingRounds);
|
sprintf(buffer, "Rnds: %d ", rabbitWeaponry.currentWeaponRemainingRounds);
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 40);
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 40);
|
||||||
|
sprintf(buffer, "Cool: %d ", playerPowerup.cooldown);
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 50);
|
||||||
|
|
||||||
waitStartVbl();
|
waitStartVbl();
|
||||||
copyDrawBufferToDisplay();
|
copyDrawBufferToDisplay();
|
||||||
|
|
2
game.h
2
game.h
|
@ -9,6 +9,8 @@ extern struct SpriteBounds bounds;
|
||||||
struct GlobalGameState {
|
struct GlobalGameState {
|
||||||
int difficulty;
|
int difficulty;
|
||||||
int spawnCooldown;
|
int spawnCooldown;
|
||||||
|
int kills;
|
||||||
|
int health;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
makefile
10
makefile
|
@ -1,4 +1,5 @@
|
||||||
obj = sprites.o game.o bmpload.o arena.o movement.o combat.o spawn.o
|
obj = sprites.o game.o bmpload.o arena.o movement.o combat.o spawn.o const.o powerup.o
|
||||||
|
test_obj = test.o spawn.o spawn_test.o powerup.o powerup_test.o const.o combat.o combat_test.o
|
||||||
|
|
||||||
all: system/system.lib game.exe test .SYMBOLIC
|
all: system/system.lib game.exe test .SYMBOLIC
|
||||||
|
|
||||||
|
@ -19,11 +20,14 @@ sprites.asm: sprtsht.bmp spritesheet.yml
|
||||||
game.exe: $(obj) system/system.lib
|
game.exe: $(obj) system/system.lib
|
||||||
wcl386 -q -fe=game -bt=dos -l=dos4g $(obj) system/system.lib
|
wcl386 -q -fe=game -bt=dos -l=dos4g $(obj) system/system.lib
|
||||||
|
|
||||||
test: test.c spawn_test.c spawn.c .SYMBOLIC
|
test: $(test_obj) system/system.lib .SYMBOLIC
|
||||||
wcl386 -fe=test -bt=dos -l=dos4g test.c spawn.c spawn_test.c cutest-1.5/CuTest.c
|
wcl386 -fe=test -bt=dos -l=dos4g $(test_obj) cutest-1.5/CuTest.c system/system.lib
|
||||||
|
|
||||||
clean: .SYMBOLIC
|
clean: .SYMBOLIC
|
||||||
|
rm -f game.exe
|
||||||
|
rm -f test.exe
|
||||||
rm *.o
|
rm *.o
|
||||||
rm *.err
|
rm *.err
|
||||||
rm system/*.o
|
rm system/*.o
|
||||||
rm system/*.lib
|
rm system/*.lib
|
||||||
|
rm system/*.err
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "movement.h"
|
||||||
|
#include "powerup.h"
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
// powerup should spawn every other difficulty band
|
||||||
|
// so the first spawn should happen somewhere 10 + (20 * rand())
|
||||||
|
int determinePowerupCooldownTime(int difficulty) {
|
||||||
|
if (difficulty > MAX_DIFFICULTY) exit(1);
|
||||||
|
|
||||||
|
return difficultyBands[difficulty] + rand() % difficultyBands[difficulty];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if every shot lands, you should run out slightly before the next powerup
|
||||||
|
// should be available
|
||||||
|
// so for the first rounds should be difficulty(1) + difficulty(2) % rand() or so
|
||||||
|
int determineShotgunRounds(int difficulty) {
|
||||||
|
if (difficulty > MAX_DIFFICULTY) exit(1);
|
||||||
|
|
||||||
|
return difficultyBands[difficulty] +
|
||||||
|
difficultyBands[difficulty] / 2 +
|
||||||
|
rand() % (difficultyBands[difficulty] / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void processPowerupCooldown(
|
||||||
|
struct PlayerPowerup *playerPowerup,
|
||||||
|
struct GlobalGameState *globalGameState,
|
||||||
|
struct RabbitWeaponry *rabbitWeaponry,
|
||||||
|
int killCount
|
||||||
|
) {
|
||||||
|
if (playerPowerup->isActive) return;
|
||||||
|
if (rabbitWeaponry->currentWeapon != WEAPON_TYPE_SINGLE_SHOT_GUN) return;
|
||||||
|
|
||||||
|
playerPowerup->cooldown -= killCount;
|
||||||
|
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->willBeInactive = 0;
|
||||||
|
|
||||||
|
playerPowerup->cooldown = determinePowerupCooldownTime(globalGameState->difficulty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef __POWERUP_H__
|
||||||
|
#define __POWERUP_H__
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "movement.h"
|
||||||
|
|
||||||
|
int determinePowerupCooldownTime(int difficulty);
|
||||||
|
int determineShotgunRounds(int difficulty);
|
||||||
|
void processPowerupCooldown(
|
||||||
|
struct PlayerPowerup*,
|
||||||
|
struct GlobalGameState*,
|
||||||
|
struct RabbitWeaponry*,
|
||||||
|
int killCount
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,125 @@
|
||||||
|
#include "cutest-1.5/CuTest.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "movement.h"
|
||||||
|
#include "powerup.h"
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
void TestDeterminePowerupCooldownTime(CuTest *tc) {
|
||||||
|
srand(1);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 18, determinePowerupCooldownTime(0));
|
||||||
|
CuAssertIntEquals(tc, 38, determinePowerupCooldownTime(1));
|
||||||
|
CuAssertIntEquals(tc, 33, determinePowerupCooldownTime(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDetermineShotgunRounds(CuTest *tc) {
|
||||||
|
srand(1);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 18, determineShotgunRounds(0));
|
||||||
|
CuAssertIntEquals(tc, 38, determineShotgunRounds(1));
|
||||||
|
CuAssertIntEquals(tc, 48, determineShotgunRounds(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TestProcessPowerupCooldown_PowerupActive(CuTest *tc) {
|
||||||
|
struct PlayerPowerup playerPowerup;
|
||||||
|
struct GlobalGameState globalGameState;
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
playerPowerup.isActive = 1;
|
||||||
|
playerPowerup.cooldown = 100;
|
||||||
|
|
||||||
|
processPowerupCooldown(
|
||||||
|
&playerPowerup,
|
||||||
|
&globalGameState,
|
||||||
|
&rabbitWeaponry,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 100, playerPowerup.cooldown);
|
||||||
|
CuAssertIntEquals(tc, 1, playerPowerup.isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestProcessPowerupCooldown_WeaponActive(CuTest *tc) {
|
||||||
|
struct PlayerPowerup playerPowerup;
|
||||||
|
struct GlobalGameState globalGameState;
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
playerPowerup.isActive = 0;
|
||||||
|
playerPowerup.cooldown = 100;
|
||||||
|
rabbitWeaponry.currentWeapon = 99;
|
||||||
|
|
||||||
|
processPowerupCooldown(
|
||||||
|
&playerPowerup,
|
||||||
|
&globalGameState,
|
||||||
|
&rabbitWeaponry,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 100, playerPowerup.cooldown);
|
||||||
|
CuAssertIntEquals(tc, 0, playerPowerup.isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestProcessPowerupCooldown_NotTriggered(CuTest *tc) {
|
||||||
|
struct PlayerPowerup playerPowerup;
|
||||||
|
struct GlobalGameState globalGameState;
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
playerPowerup.isActive = 0;
|
||||||
|
playerPowerup.cooldown = 100;
|
||||||
|
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
||||||
|
|
||||||
|
processPowerupCooldown(
|
||||||
|
&playerPowerup,
|
||||||
|
&globalGameState,
|
||||||
|
&rabbitWeaponry,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 90, playerPowerup.cooldown);
|
||||||
|
CuAssertIntEquals(tc, 0, playerPowerup.isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestProcessPowerupCooldown_Triggered(CuTest *tc) {
|
||||||
|
struct PlayerPowerup playerPowerup;
|
||||||
|
struct GlobalGameState globalGameState;
|
||||||
|
struct RabbitWeaponry rabbitWeaponry;
|
||||||
|
|
||||||
|
srand(1);
|
||||||
|
|
||||||
|
playerPowerup.isActive = 0;
|
||||||
|
playerPowerup.cooldown = 100;
|
||||||
|
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
||||||
|
playerPowerup.willBeInactive = 1;
|
||||||
|
globalGameState.difficulty = 0;
|
||||||
|
|
||||||
|
processPowerupCooldown(
|
||||||
|
&playerPowerup,
|
||||||
|
&globalGameState,
|
||||||
|
&rabbitWeaponry,
|
||||||
|
101
|
||||||
|
);
|
||||||
|
|
||||||
|
CuAssertIntEquals(tc, 1, playerPowerup.isActive);
|
||||||
|
CuAssertIntEquals(tc, 0, playerPowerup.willBeInactive);
|
||||||
|
|
||||||
|
// rand
|
||||||
|
CuAssertIntEquals(tc, 13, playerPowerup.cooldown);
|
||||||
|
CuAssertIntEquals(tc, 58, playerPowerup.x);
|
||||||
|
CuAssertIntEquals(tc, 178, playerPowerup.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *PowerupGetSuite() {
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, TestDeterminePowerupCooldownTime);
|
||||||
|
SUITE_ADD_TEST(suite, TestDetermineShotgunRounds);
|
||||||
|
SUITE_ADD_TEST(suite, TestProcessPowerupCooldown_PowerupActive);
|
||||||
|
SUITE_ADD_TEST(suite, TestProcessPowerupCooldown_WeaponActive);
|
||||||
|
SUITE_ADD_TEST(suite, TestProcessPowerupCooldown_NotTriggered);
|
||||||
|
SUITE_ADD_TEST(suite, TestProcessPowerupCooldown_Triggered);
|
||||||
|
return suite;
|
||||||
|
}
|
55
sprites.asm
55
sprites.asm
|
@ -8,10 +8,65 @@ PUBLIC sprite_bullet_
|
||||||
PUBLIC sprite_enemy_
|
PUBLIC sprite_enemy_
|
||||||
PUBLIC sprite_shotgun_
|
PUBLIC sprite_shotgun_
|
||||||
PUBLIC sprite_shieldKiller_
|
PUBLIC sprite_shieldKiller_
|
||||||
|
PUBLIC _palette
|
||||||
|
|
||||||
.386
|
.386
|
||||||
.model flat,c
|
.model flat,c
|
||||||
|
|
||||||
|
.DATA
|
||||||
|
_palette:
|
||||||
|
BYTE 63
|
||||||
|
BYTE 0
|
||||||
|
BYTE 63
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 15
|
||||||
|
BYTE 16
|
||||||
|
BYTE 49
|
||||||
|
BYTE 16
|
||||||
|
BYTE 16
|
||||||
|
BYTE 33
|
||||||
|
BYTE 16
|
||||||
|
BYTE 16
|
||||||
|
BYTE 16
|
||||||
|
BYTE 63
|
||||||
|
BYTE 63
|
||||||
|
BYTE 63
|
||||||
|
BYTE 38
|
||||||
|
BYTE 31
|
||||||
|
BYTE 12
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
BYTE 0
|
||||||
|
|
||||||
.CODE
|
.CODE
|
||||||
|
|
||||||
|
|
||||||
|
|
20
sprites.h
20
sprites.h
|
@ -6,25 +6,7 @@
|
||||||
|
|
||||||
#define PALETTE_COLOR_COUNT (17)
|
#define PALETTE_COLOR_COUNT (17)
|
||||||
|
|
||||||
struct VGAColor palette[17] = {
|
extern struct VGAColor palette[17];
|
||||||
{ 63, 0, 63 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 15, 16, 49 },
|
|
||||||
{ 16, 16, 33 },
|
|
||||||
{ 16, 16, 16 },
|
|
||||||
{ 63, 63, 63 },
|
|
||||||
{ 38, 31, 12 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 },
|
|
||||||
{ 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern void sprite_arenaWallTop(byte *);
|
extern void sprite_arenaWallTop(byte *);
|
||||||
|
|
10
test.c
10
test.c
|
@ -2,19 +2,25 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
CuSuite *SpawnGetSuite();
|
CuSuite *SpawnGetSuite();
|
||||||
|
CuSuite *PowerupGetSuite();
|
||||||
|
CuSuite *CombatGetSuite();
|
||||||
|
|
||||||
void RunAllTests(void) {
|
int RunAllTests(void) {
|
||||||
CuString *output = CuStringNew();
|
CuString *output = CuStringNew();
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
|
||||||
CuSuiteAddSuite(suite, SpawnGetSuite());
|
CuSuiteAddSuite(suite, SpawnGetSuite());
|
||||||
|
CuSuiteAddSuite(suite, PowerupGetSuite());
|
||||||
|
CuSuiteAddSuite(suite, CombatGetSuite());
|
||||||
|
|
||||||
CuSuiteRun(suite);
|
CuSuiteRun(suite);
|
||||||
CuSuiteSummary(suite, output);
|
CuSuiteSummary(suite, output);
|
||||||
CuSuiteDetails(suite, output);
|
CuSuiteDetails(suite, output);
|
||||||
printf("%s\n", output->buffer);
|
printf("%s\n", output->buffer);
|
||||||
|
|
||||||
|
return suite->failCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
RunAllTests();
|
return RunAllTests();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue