ready for push to public git?
This commit is contained in:
parent
a144f4fc47
commit
d0ccb689a9
32
combat.c
32
combat.c
|
@ -105,15 +105,15 @@ int attemptToFireRabbitBullet(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (rabbitWeaponry->currentWeapon == WEAPON_TYPE_BEAM_SHOT_GUN) {
|
} else if (rabbitWeaponry->currentWeapon == WEAPON_TYPE_BEAM_SHOT_GUN) {
|
||||||
// make sure three bullets are available
|
// make sure two bullets are available
|
||||||
if (!maybeFireShotCount(
|
if (!maybeFireShotCount(
|
||||||
rabbitBulletPosition,
|
rabbitBulletPosition,
|
||||||
availableBullets,
|
availableBullets,
|
||||||
4
|
2
|
||||||
)) return 0;
|
)) return 0;
|
||||||
|
|
||||||
// if so, fire away
|
// if so, fire away
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 2; ++i) {
|
||||||
beamOffsetX = sin(mouseAngle * DEG2RAD) * i * 2;
|
beamOffsetX = sin(mouseAngle * DEG2RAD) * i * 2;
|
||||||
beamOffsetY = -cos(mouseAngle * DEG2RAD) * i * 2;
|
beamOffsetY = -cos(mouseAngle * DEG2RAD) * i * 2;
|
||||||
|
|
||||||
|
@ -267,8 +267,8 @@ 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];
|
||||||
int rabbitBulletGridIndex[4],
|
int rabbitBulletGridIndex[4],
|
||||||
enemyGridIndex[4],
|
enemyGridIndex[4],
|
||||||
enemyBulletGridIndex[4];
|
enemyBulletGridIndex[4];
|
||||||
int gridPosition[4];
|
int gridPosition[4];
|
||||||
|
|
||||||
#define CALCULATE_GRID_POS(x,y) ((x / COLLISION_GRID_SIZE) + (y / COLLISION_GRID_SIZE) * 2)
|
#define CALCULATE_GRID_POS(x,y) ((x / COLLISION_GRID_SIZE) + (y / COLLISION_GRID_SIZE) * 2)
|
||||||
|
@ -424,7 +424,8 @@ void knockbackEnemy(
|
||||||
|
|
||||||
void handleRabbitBulletToEnemyCollisions(
|
void handleRabbitBulletToEnemyCollisions(
|
||||||
struct BulletPosition rabbitBulletPosition[],
|
struct BulletPosition rabbitBulletPosition[],
|
||||||
struct EnemyPosition enemyPosition[]
|
struct EnemyPosition enemyPosition[],
|
||||||
|
struct RabbitWeaponry *rabbitWeaponry
|
||||||
) {
|
) {
|
||||||
int bulletIdx, enemyIdx, grid;
|
int bulletIdx, enemyIdx, grid;
|
||||||
int resolvedBulletIdx, resolvedEnemyIdx;
|
int resolvedBulletIdx, resolvedEnemyIdx;
|
||||||
|
@ -447,7 +448,7 @@ void handleRabbitBulletToEnemyCollisions(
|
||||||
populateTargetCollision(&enemy);
|
populateTargetCollision(&enemy);
|
||||||
|
|
||||||
if (isCollision()) {
|
if (isCollision()) {
|
||||||
enemyPosition[resolvedEnemyIdx].hitPoints--;
|
enemyPosition[resolvedEnemyIdx].hitPoints -= rabbitWeaponry->damage;
|
||||||
if (enemyPosition[resolvedEnemyIdx].hitPoints < 1) {
|
if (enemyPosition[resolvedEnemyIdx].hitPoints < 1) {
|
||||||
enemyPosition[resolvedEnemyIdx].willBeInactive = 1;
|
enemyPosition[resolvedEnemyIdx].willBeInactive = 1;
|
||||||
enemyPosition[resolvedEnemyIdx].wasKilled = 1;
|
enemyPosition[resolvedEnemyIdx].wasKilled = 1;
|
||||||
|
@ -543,11 +544,18 @@ void handleEnemyKills(
|
||||||
struct RabbitWeaponry *rabbitWeaponry
|
struct RabbitWeaponry *rabbitWeaponry
|
||||||
) {
|
) {
|
||||||
int i, currentKillCount;
|
int i, currentKillCount;
|
||||||
|
int originalDifficulty;
|
||||||
|
int healthIncrease;
|
||||||
|
|
||||||
currentKillCount = processEnemyKillStates(enemyPosition);
|
currentKillCount = processEnemyKillStates(enemyPosition);
|
||||||
|
|
||||||
globalGameState->health += ENEMY_KILL_HEALTH_GAIN * currentKillCount;
|
healthIncrease = globalGameState->healthGainPerKill * currentKillCount;
|
||||||
if (globalGameState->health > RABBIT_HEALTH_MAX) globalGameState->health = RABBIT_HEALTH_MAX;
|
if (healthIncrease > 0) {
|
||||||
|
healthIncrease = rand() % healthIncrease + 1;
|
||||||
|
|
||||||
|
globalGameState->health += healthIncrease;
|
||||||
|
if (globalGameState->health > globalGameState->maxHealth) globalGameState->health = globalGameState->maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
globalGameState->kills += currentKillCount;
|
globalGameState->kills += currentKillCount;
|
||||||
|
|
||||||
|
@ -559,11 +567,17 @@ void handleEnemyKills(
|
||||||
currentKillCount
|
currentKillCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
originalDifficulty = globalGameState->difficulty;
|
||||||
|
|
||||||
for (i = 0; i < MAX_DIFFICULTY; ++i) {
|
for (i = 0; i < MAX_DIFFICULTY; ++i) {
|
||||||
if (globalGameState->kills > difficultyBands[i]) {
|
if (globalGameState->kills > difficultyBands[i]) {
|
||||||
globalGameState->difficulty = i + 1;
|
globalGameState->difficulty = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (originalDifficulty != globalGameState->difficulty) {
|
||||||
|
globalGameState->coins += (globalGameState->difficulty - originalDifficulty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
combat.h
3
combat.h
|
@ -12,7 +12,8 @@ void advanceRabbitBullets(
|
||||||
|
|
||||||
void handleRabbitBulletToEnemyCollisions(
|
void handleRabbitBulletToEnemyCollisions(
|
||||||
struct BulletPosition[],
|
struct BulletPosition[],
|
||||||
struct EnemyPosition[]
|
struct EnemyPosition[],
|
||||||
|
struct RabbitWeaponry*
|
||||||
);
|
);
|
||||||
|
|
||||||
int handleRabbitToEnemyCollisions(
|
int handleRabbitToEnemyCollisions(
|
||||||
|
|
11
const.c
11
const.c
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
int difficultyBands[MAX_DIFFICULTY];
|
int difficultyBands[MAX_DIFFICULTY];
|
||||||
int hitPointRanges[MAX_DIFFICULTY][4];
|
int hitPointRanges[MAX_DIFFICULTY][4];
|
||||||
|
int damageUpgradeCosts[3] = { 5, 11, 18 };
|
||||||
|
int healthUpgradeCosts[3] = { 4, 9, 15 };
|
||||||
|
int healthGainUpgradeCosts[3] = { 6, 13, 21 };
|
||||||
|
|
||||||
struct SpriteBounds bounds;
|
struct SpriteBounds bounds;
|
||||||
|
|
||||||
|
@ -17,11 +20,15 @@ struct CompiledSpriteRender rabbit,
|
||||||
|
|
||||||
void buildDifficultyBands() {
|
void buildDifficultyBands() {
|
||||||
int i;
|
int i;
|
||||||
float current = BASE_KILLS;
|
float current = 0;
|
||||||
|
float increaseBy = BASE_KILLS;
|
||||||
|
|
||||||
for (i = 0; i < MAX_DIFFICULTY; ++i) {
|
for (i = 0; i < MAX_DIFFICULTY; ++i) {
|
||||||
|
current += increaseBy;
|
||||||
|
|
||||||
difficultyBands[i] = (int)current;
|
difficultyBands[i] = (int)current;
|
||||||
current *= KILLS_NEEDED_FOR_NEXT_LEVEL_MULTIPLIER;
|
|
||||||
|
increaseBy *= KILLS_NEEDED_FOR_NEXT_LEVEL_MULTIPLIER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
const.h
26
const.h
|
@ -8,6 +8,11 @@
|
||||||
#define ARENA_HEIGHT_TILES (10)
|
#define ARENA_HEIGHT_TILES (10)
|
||||||
#define COLLISION_GRID_SIZE (ARENA_WIDTH_TILES / 2 * TILE_SIZE)
|
#define COLLISION_GRID_SIZE (ARENA_WIDTH_TILES / 2 * TILE_SIZE)
|
||||||
|
|
||||||
|
#define ARENA_LEFT_EDGE (TILE_SIZE)
|
||||||
|
#define ARENA_TOP_EDGE (TILE_SIZE)
|
||||||
|
#define ARENA_RIGHT_EDGE (ARENA_WIDTH_TILES - 1) * TILE_SIZE
|
||||||
|
#define ARENA_BOTTOM_EDGE (ARENA_WIDTH_TILES - 1) * TILE_SIZE
|
||||||
|
|
||||||
#define MOUSE_DISTANCE (32)
|
#define MOUSE_DISTANCE (32)
|
||||||
|
|
||||||
#define RABBIT_MOTION_DRAG (2)
|
#define RABBIT_MOTION_DRAG (2)
|
||||||
|
@ -33,22 +38,21 @@
|
||||||
#define DEG2RAD (3.14159/180)
|
#define DEG2RAD (3.14159/180)
|
||||||
|
|
||||||
#define ENEMY_MAX_COUNT (50)
|
#define ENEMY_MAX_COUNT (50)
|
||||||
#define ENEMY_BULLET_LIMIT (ENEMY_MAX_COUNT / 4)
|
#define ENEMY_BULLET_LIMIT (ENEMY_MAX_COUNT / 5)
|
||||||
|
|
||||||
#define ENEMY_MOVE_SPEED (1)
|
#define ENEMY_MOVE_SPEED (1)
|
||||||
#define ENEMY_MOVE_DELAY (3)
|
#define ENEMY_MOVE_DELAY (3)
|
||||||
#define ENEMY_BULLET_VELOCITY (RABBIT_BULLET_VELOCITY - 2)
|
#define ENEMY_BULLET_VELOCITY (RABBIT_BULLET_VELOCITY - 1)
|
||||||
|
|
||||||
#define ENEMY_FIRE_MIN_DELAY (45)
|
#define ENEMY_FIRE_MIN_DELAY (50)
|
||||||
#define ENEMY_FIRE_VARIABLE_DELAY (60)
|
#define ENEMY_FIRE_VARIABLE_DELAY (60)
|
||||||
|
|
||||||
#define ENEMY_BULLET_DAMAGE (3)
|
#define ENEMY_BULLET_DAMAGE (3)
|
||||||
#define ENEMY_COLLISION_DAMAGE (6)
|
#define ENEMY_COLLISION_DAMAGE (6)
|
||||||
#define ENEMY_KILL_HEALTH_GAIN (1)
|
|
||||||
#define ENEMY_HIT_POINT_DIFFICULTY_INCREASE_EVERY (4)
|
#define ENEMY_HIT_POINT_DIFFICULTY_INCREASE_EVERY (4)
|
||||||
|
|
||||||
#define BASE_ENEMY_SPAWN_COOLDOWN (30)
|
#define BASE_ENEMY_SPAWN_COOLDOWN (30)
|
||||||
#define DIFFICULTY_SPAWN_COOLDOWN_REDUCTION (2)
|
#define DIFFICULTY_SPAWN_COOLDOWN_REDUCTION (1)
|
||||||
#define MINIMUM_ENEMY_SPAWN_COOLDOWN (3)
|
#define MINIMUM_ENEMY_SPAWN_COOLDOWN (3)
|
||||||
#define VARIABLE_ENEMY_SPAWN_COOLDOWN (10)
|
#define VARIABLE_ENEMY_SPAWN_COOLDOWN (10)
|
||||||
|
|
||||||
|
@ -56,8 +60,8 @@
|
||||||
|
|
||||||
#define SHOTGUN_ROUNDS_PER_LEVEL (25)
|
#define SHOTGUN_ROUNDS_PER_LEVEL (25)
|
||||||
#define MAX_DIFFICULTY (40)
|
#define MAX_DIFFICULTY (40)
|
||||||
#define BASE_KILLS (30)
|
#define BASE_KILLS (20)
|
||||||
#define KILLS_NEEDED_FOR_NEXT_LEVEL_MULTIPLIER (1.25)
|
#define KILLS_NEEDED_FOR_NEXT_LEVEL_MULTIPLIER (1.06)
|
||||||
#define HIT_POINT_DIFFICULTY_INCREASE_DELAY (4)
|
#define HIT_POINT_DIFFICULTY_INCREASE_DELAY (4)
|
||||||
|
|
||||||
#define WEAPON_TYPE_SINGLE_SHOT_GUN (0)
|
#define WEAPON_TYPE_SINGLE_SHOT_GUN (0)
|
||||||
|
@ -69,10 +73,16 @@
|
||||||
|
|
||||||
#define KNOCKBACK_DISTANCE (3)
|
#define KNOCKBACK_DISTANCE (3)
|
||||||
|
|
||||||
|
#define HEALTH_UPGRADE_GAIN (10)
|
||||||
|
|
||||||
extern int difficultyBands[];
|
extern int difficultyBands[];
|
||||||
extern int hitPointRanges[MAX_DIFFICULTY][4];
|
extern int hitPointRanges[MAX_DIFFICULTY][4];
|
||||||
extern struct SpriteBounds bounds;
|
|
||||||
|
|
||||||
|
extern int damageUpgradeCosts[];
|
||||||
|
extern int healthUpgradeCosts[];
|
||||||
|
extern int healthGainUpgradeCosts[];
|
||||||
|
|
||||||
|
extern struct SpriteBounds bounds;
|
||||||
extern struct CompiledSpriteRender rabbit,
|
extern struct CompiledSpriteRender rabbit,
|
||||||
mouse,
|
mouse,
|
||||||
bullet,
|
bullet,
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void TestBuildDifficultyBands(CuTest *tc) {
|
void TestBuildDifficultyBands(CuTest *tc) {
|
||||||
|
|
||||||
buildDifficultyBands();
|
buildDifficultyBands();
|
||||||
|
|
||||||
CuAssertIntEquals(tc, 30, difficultyBands[0]);
|
CuAssertIntEquals(tc, 20, difficultyBands[0]);
|
||||||
CuAssertIntEquals(tc, 37, difficultyBands[1]);
|
CuAssertIntEquals(tc, 41, difficultyBands[1]);
|
||||||
CuAssertIntEquals(tc, 46, difficultyBands[2]);
|
CuAssertIntEquals(tc, 3095, difficultyBands[MAX_DIFFICULTY - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestBuildHitPointRanges(CuTest *tc) {
|
void TestBuildHitPointRanges(CuTest *tc) {
|
||||||
|
|
178
game.c
178
game.c
|
@ -45,7 +45,13 @@ struct GlobalGameState globalGameState = {
|
||||||
.spawnCooldown = 0,
|
.spawnCooldown = 0,
|
||||||
.difficulty = 0,
|
.difficulty = 0,
|
||||||
.kills = 0,
|
.kills = 0,
|
||||||
.health = RABBIT_HEALTH_MAX
|
.coins = 0,
|
||||||
|
.health = RABBIT_HEALTH_MAX,
|
||||||
|
.maxHealth = RABBIT_HEALTH_MAX,
|
||||||
|
.healthGainPerKill = 1,
|
||||||
|
.damageUpgradeLevel = 0,
|
||||||
|
.healthUpgradeLevel = 0,
|
||||||
|
.healthGainUpgradeLevel = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
void setupRabbitBullets() {
|
void setupRabbitBullets() {
|
||||||
|
@ -59,6 +65,7 @@ void setupRabbitBullets() {
|
||||||
rabbitWeaponry.cooldown = 0;
|
rabbitWeaponry.cooldown = 0;
|
||||||
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
||||||
rabbitWeaponry.currentWeaponRemainingRounds = 0;
|
rabbitWeaponry.currentWeaponRemainingRounds = 0;
|
||||||
|
rabbitWeaponry.damage = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPowerup() {
|
void setupPowerup() {
|
||||||
|
@ -160,7 +167,10 @@ 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);
|
|
||||||
|
mouse.x = rabbitPosition.mouseDotPosition[0];
|
||||||
|
mouse.y = rabbitPosition.mouseDotPosition[1];
|
||||||
|
drawCompiledSprite(&mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderRabbit() {
|
void renderRabbit() {
|
||||||
|
@ -234,11 +244,9 @@ void drawOnlyMouseArena() {
|
||||||
mouse.y = rabbitPosition.oldMousePosition[1];
|
mouse.y = rabbitPosition.oldMousePosition[1];
|
||||||
drawOnlyArenaForSprite(&mouse);
|
drawOnlyArenaForSprite(&mouse);
|
||||||
|
|
||||||
bounds.top = rabbitPosition.oldMouseDotPosition[1];
|
mouse.x = rabbitPosition.oldMouseDotPosition[0];
|
||||||
bounds.bottom = rabbitPosition.oldMouseDotPosition[1];
|
mouse.y = rabbitPosition.oldMouseDotPosition[1];
|
||||||
bounds.left = rabbitPosition.oldMouseDotPosition[0];
|
drawOnlyArenaForSprite(&mouse);
|
||||||
bounds.right = rabbitPosition.oldMouseDotPosition[0];
|
|
||||||
drawOnlyArena(&bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawOnlyRabbitArena() {
|
void drawOnlyRabbitArena() {
|
||||||
|
@ -425,7 +433,8 @@ void handleCombat() {
|
||||||
|
|
||||||
handleRabbitBulletToEnemyCollisions(
|
handleRabbitBulletToEnemyCollisions(
|
||||||
rabbitBulletPosition,
|
rabbitBulletPosition,
|
||||||
enemyPosition
|
enemyPosition,
|
||||||
|
&rabbitWeaponry
|
||||||
);
|
);
|
||||||
|
|
||||||
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
|
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
|
||||||
|
@ -460,6 +469,123 @@ double averageSpeedCalc;
|
||||||
clock_t startTime;
|
clock_t startTime;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct PriorStats {
|
||||||
|
int kills;
|
||||||
|
int health;
|
||||||
|
int remainingRounds;
|
||||||
|
int coins;
|
||||||
|
|
||||||
|
int damageUpgradeAvailable;
|
||||||
|
int healthUpgradeAvailable;
|
||||||
|
int healthGainUpgradeAvailable;
|
||||||
|
} priorStats = {
|
||||||
|
.kills = -1,
|
||||||
|
.health = -1,
|
||||||
|
.remainingRounds = -1,
|
||||||
|
.coins = -1,
|
||||||
|
.damageUpgradeAvailable = -1,
|
||||||
|
.healthUpgradeAvailable = -1,
|
||||||
|
.healthGainUpgradeAvailable = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UpgradesAvailable {
|
||||||
|
char damage;
|
||||||
|
char health;
|
||||||
|
char healthGain;
|
||||||
|
} upgradesAvailable = {
|
||||||
|
.damage = 0,
|
||||||
|
.health = 0,
|
||||||
|
.healthGain = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void calculateUpgradesAvailable() {
|
||||||
|
if (globalGameState.damageUpgradeLevel < 3) {
|
||||||
|
upgradesAvailable.damage = globalGameState.coins >= damageUpgradeCosts[globalGameState.damageUpgradeLevel];
|
||||||
|
} else {
|
||||||
|
upgradesAvailable.damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalGameState.healthUpgradeLevel < 3) {
|
||||||
|
upgradesAvailable.health = globalGameState.coins >= healthUpgradeCosts[globalGameState.healthUpgradeLevel];
|
||||||
|
} else {
|
||||||
|
upgradesAvailable.health = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalGameState.healthGainUpgradeLevel < 3) {
|
||||||
|
upgradesAvailable.healthGain = globalGameState.coins >= healthGainUpgradeCosts[globalGameState.healthGainUpgradeLevel];
|
||||||
|
} else {
|
||||||
|
upgradesAvailable.healthGain = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void redrawGameStats() {
|
||||||
|
char buffer[20];
|
||||||
|
|
||||||
|
if (priorStats.kills != globalGameState.kills) {
|
||||||
|
sprintf(buffer, "Hit: %d", globalGameState.kills);
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 20);
|
||||||
|
|
||||||
|
priorStats.kills = globalGameState.kills;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.health != globalGameState.health) {
|
||||||
|
sprintf(buffer, "Health: %d ", globalGameState.health);
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 30);
|
||||||
|
|
||||||
|
priorStats.health = globalGameState.health;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.remainingRounds != rabbitWeaponry.currentWeaponRemainingRounds) {
|
||||||
|
sprintf(buffer, "Rnds: %d ", rabbitWeaponry.currentWeaponRemainingRounds);
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 40);
|
||||||
|
|
||||||
|
priorStats.remainingRounds = rabbitWeaponry.currentWeaponRemainingRounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.coins != globalGameState.coins) {
|
||||||
|
sprintf(buffer, "Coins: %d ", globalGameState.coins);
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 50);
|
||||||
|
|
||||||
|
priorStats.coins = globalGameState.coins;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.damageUpgradeAvailable != upgradesAvailable.damage) {
|
||||||
|
if (upgradesAvailable.damage) {
|
||||||
|
sprintf(buffer, "[P] Dmg up");
|
||||||
|
} else {
|
||||||
|
sprintf(buffer, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 100);
|
||||||
|
|
||||||
|
priorStats.damageUpgradeAvailable = upgradesAvailable.damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.healthUpgradeAvailable != upgradesAvailable.health) {
|
||||||
|
if (upgradesAvailable.health) {
|
||||||
|
sprintf(buffer, "[O] Health up");
|
||||||
|
} else {
|
||||||
|
sprintf(buffer, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 110);
|
||||||
|
|
||||||
|
priorStats.healthUpgradeAvailable = upgradesAvailable.health;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorStats.healthGainUpgradeAvailable != upgradesAvailable.healthGain) {
|
||||||
|
if (upgradesAvailable.healthGain) {
|
||||||
|
sprintf(buffer, "[I] HGain up");
|
||||||
|
} else {
|
||||||
|
sprintf(buffer, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStringToDrawBuffer(buffer, 1, 0, 210, 120);
|
||||||
|
|
||||||
|
priorStats.healthGainUpgradeAvailable = upgradesAvailable.healthGain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
byte *drawBuffer;
|
byte *drawBuffer;
|
||||||
int keepRunning = 1;
|
int keepRunning = 1;
|
||||||
|
@ -480,27 +606,37 @@ int main(void) {
|
||||||
enemyPosition,
|
enemyPosition,
|
||||||
&rabbitPosition
|
&rabbitPosition
|
||||||
);
|
);
|
||||||
|
|
||||||
handleMovement();
|
|
||||||
handleRedraw();
|
|
||||||
handleCombat();
|
handleCombat();
|
||||||
|
handleRedraw();
|
||||||
handleEnemyKills(
|
handleEnemyKills(
|
||||||
enemyPosition,
|
enemyPosition,
|
||||||
&globalGameState,
|
&globalGameState,
|
||||||
&playerPowerup,
|
&playerPowerup,
|
||||||
&rabbitWeaponry
|
&rabbitWeaponry
|
||||||
);
|
);
|
||||||
|
handleMovement();
|
||||||
|
|
||||||
sprintf(buffer, "Hit: %d", globalGameState.kills);
|
calculateUpgradesAvailable();
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 20);
|
redrawGameStats();
|
||||||
sprintf(buffer, "Health: %d ", globalGameState.health);
|
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 30);
|
if (keyboardKeydownState.KEY_P && upgradesAvailable.damage) {
|
||||||
sprintf(buffer, "Rnds: %d ", rabbitWeaponry.currentWeaponRemainingRounds);
|
globalGameState.coins -= damageUpgradeCosts[globalGameState.damageUpgradeLevel];
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 40);
|
globalGameState.damageUpgradeLevel++;
|
||||||
sprintf(buffer, "Cool: %d ", playerPowerup.cooldown);
|
rabbitWeaponry.damage++;
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 50);
|
}
|
||||||
sprintf(buffer, "Lvl: %d ", globalGameState.difficulty);
|
|
||||||
renderStringToDrawBuffer(buffer, 1, 0, 210, 60);
|
if (keyboardKeydownState.KEY_O && upgradesAvailable.health) {
|
||||||
|
globalGameState.coins -= healthUpgradeCosts[globalGameState.healthUpgradeLevel];
|
||||||
|
globalGameState.healthUpgradeLevel++;
|
||||||
|
globalGameState.maxHealth += HEALTH_UPGRADE_GAIN;
|
||||||
|
globalGameState.health = globalGameState.maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyboardKeydownState.KEY_I && upgradesAvailable.healthGain) {
|
||||||
|
globalGameState.coins -= healthGainUpgradeCosts[globalGameState.healthGainUpgradeLevel];
|
||||||
|
globalGameState.healthGainUpgradeLevel++;
|
||||||
|
globalGameState.healthGainPerKill++;
|
||||||
|
}
|
||||||
|
|
||||||
waitStartVbl();
|
waitStartVbl();
|
||||||
copyDrawBufferToDisplay();
|
copyDrawBufferToDisplay();
|
||||||
|
|
7
game.h
7
game.h
|
@ -11,6 +11,13 @@ struct GlobalGameState {
|
||||||
int spawnCooldown;
|
int spawnCooldown;
|
||||||
int kills;
|
int kills;
|
||||||
int health;
|
int health;
|
||||||
|
int maxHealth;
|
||||||
|
int healthGainPerKill;
|
||||||
|
int coins;
|
||||||
|
|
||||||
|
int damageUpgradeLevel;
|
||||||
|
int healthUpgradeLevel;
|
||||||
|
int healthGainUpgradeLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
123
movement.c
123
movement.c
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include "system/mouse_io.h"
|
#include "system/mouse_io.h"
|
||||||
#include "system/pc_stuff.h"
|
#include "system/pc_stuff.h"
|
||||||
|
#include "system/vga.h"
|
||||||
|
|
||||||
|
#define SIGN(x) ((x > 0) - (x < 0))
|
||||||
|
|
||||||
void captureAndLimitMousePosition(
|
void captureAndLimitMousePosition(
|
||||||
struct RabbitPosition *pos,
|
struct RabbitPosition *pos,
|
||||||
|
@ -26,43 +29,131 @@ void captureAndLimitMousePosition(
|
||||||
if (pos->mouseDotPosition[1] >= MOUSE_LIMIT_BOTTOM) pos->mouseDotPosition[1] = MOUSE_LIMIT_BOTTOM;
|
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(
|
void calculateTargetAngle(
|
||||||
struct RabbitPosition *pos
|
struct RabbitPosition *pos
|
||||||
) {
|
) {
|
||||||
int targetX, targetY;
|
|
||||||
float distanceX, distanceY;
|
float distanceX, distanceY;
|
||||||
float angle, fixHypotenuse, fixDistance;
|
float angle, fixHypotenuse, fixDistance;
|
||||||
|
struct TargetMousePosition targetMousePosition;
|
||||||
|
|
||||||
// Position the cursor
|
// Position the cursor
|
||||||
distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0];
|
distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0];
|
||||||
distanceY = pos->mouseDotPosition[1] - pos->rabbitPosition[1];
|
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;
|
angle = atan2(distanceY, distanceX) * RAD2DEG + 90;
|
||||||
if (angle < 0) angle += 360;
|
if (angle < 0) angle += 360;
|
||||||
|
}
|
||||||
|
|
||||||
distanceX = sin(angle * DEG2RAD) * MOUSE_DISTANCE;
|
pos->mouseAngle = angle;
|
||||||
distanceY = -cos(angle * DEG2RAD) * MOUSE_DISTANCE;
|
|
||||||
|
|
||||||
pos->oldMousePosition[0] = pos->mousePosition[0];
|
pos->oldMousePosition[0] = pos->mousePosition[0];
|
||||||
pos->oldMousePosition[1] = pos->mousePosition[1];
|
pos->oldMousePosition[1] = pos->mousePosition[1];
|
||||||
|
|
||||||
targetX = pos->rabbitPosition[0] + distanceX;
|
targetMousePosition.x = pos->rabbitPosition[0];
|
||||||
targetY = pos->rabbitPosition[1] + distanceY;
|
targetMousePosition.y = pos->rabbitPosition[1];
|
||||||
|
|
||||||
if (targetX > (ARENA_WIDTH_TILES - 1) * TILE_SIZE) {
|
constrainMousePosition(pos, &targetMousePosition);
|
||||||
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[0] = targetMousePosition.x;
|
||||||
pos->mousePosition[1] = targetY;
|
pos->mousePosition[1] = targetMousePosition.y;
|
||||||
|
|
||||||
pos->mouseAngle = angle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SIGN(x) ((x > 0) - (x < 0))
|
|
||||||
|
|
||||||
void handleEnemyMovement(
|
void handleEnemyMovement(
|
||||||
struct EnemyPosition enemyPosition[],
|
struct EnemyPosition enemyPosition[],
|
||||||
|
|
19
movement.h
19
movement.h
|
@ -22,6 +22,7 @@ struct RabbitWeaponry {
|
||||||
char cooldown;
|
char cooldown;
|
||||||
char currentWeapon;
|
char currentWeapon;
|
||||||
int currentWeaponRemainingRounds;
|
int currentWeaponRemainingRounds;
|
||||||
|
char damage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerPowerup {
|
struct PlayerPowerup {
|
||||||
|
@ -48,20 +49,20 @@ struct BulletPosition {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EnemyPosition {
|
struct EnemyPosition {
|
||||||
char isActive;
|
int hitPoints;
|
||||||
|
|
||||||
char willBeInactive;
|
|
||||||
char wasKilled;
|
|
||||||
|
|
||||||
char hitPoints;
|
|
||||||
char hasLeftGate;
|
|
||||||
char gateExitedFrom;
|
|
||||||
|
|
||||||
int enemyPosition[2];
|
int enemyPosition[2];
|
||||||
int oldEnemyPosition[2];
|
int oldEnemyPosition[2];
|
||||||
|
|
||||||
int enemyMoveDelayStep;
|
int enemyMoveDelayStep;
|
||||||
int enemyFireDelayStep;
|
int enemyFireDelayStep;
|
||||||
|
|
||||||
|
char isActive;
|
||||||
|
|
||||||
|
char willBeInactive;
|
||||||
|
char wasKilled;
|
||||||
|
|
||||||
|
char hasLeftGate;
|
||||||
|
char gateExitedFrom;
|
||||||
};
|
};
|
||||||
|
|
||||||
void calculateTargetAngle(struct RabbitPosition*);
|
void calculateTargetAngle(struct RabbitPosition*);
|
||||||
|
|
|
@ -3,28 +3,28 @@
|
||||||
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
|
||||||
void TestCalculateTargetAngle_AgainstRightWall(CuTest *tc) {
|
void TestCalculateTargetAngle_AgainstTopRight(CuTest *tc) {
|
||||||
struct RabbitPosition rabbitPosition;
|
struct RabbitPosition rabbitPosition;
|
||||||
|
|
||||||
// mouse against very edge
|
// mouse against very edge
|
||||||
rabbitPosition.mouseDotPosition[0] = 199;
|
rabbitPosition.mouseDotPosition[0] = 199;
|
||||||
rabbitPosition.mouseDotPosition[1] = 30;
|
rabbitPosition.mouseDotPosition[1] = 0;
|
||||||
|
|
||||||
// rabbit against wall
|
// rabbit against wall
|
||||||
rabbitPosition.rabbitPosition[0] = 179;
|
rabbitPosition.rabbitPosition[0] = 177;
|
||||||
rabbitPosition.rabbitPosition[1] = 80;
|
rabbitPosition.rabbitPosition[1] = 25;
|
||||||
|
|
||||||
calculateTargetAngle(&rabbitPosition);
|
calculateTargetAngle(&rabbitPosition);
|
||||||
|
|
||||||
// mouse should not extend (tile width - mouse width) past player
|
// mouse should not extend (tile width - mouse width) past player
|
||||||
|
|
||||||
CuAssertIntEquals(tc, 180, rabbitPosition.mousePosition[0]);
|
CuAssertIntEquals(tc, 180, rabbitPosition.mousePosition[0]);
|
||||||
CuAssertIntEquals(tc, 105, rabbitPosition.mousePosition[1]);
|
CuAssertIntEquals(tc, 21, rabbitPosition.mousePosition[1]);
|
||||||
CuAssertIntEquals(tc, 21, rabbitPosition.mouseAngle);
|
CuAssertIntEquals(tc, 41, rabbitPosition.mouseAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
CuSuite *MovementGetSuite() {
|
CuSuite *MovementGetSuite() {
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, TestCalculateTargetAngle_AgainstRightWall);
|
SUITE_ADD_TEST(suite, TestCalculateTargetAngle_AgainstTopRight);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
11
powerup.c
11
powerup.c
|
@ -11,7 +11,7 @@
|
||||||
int determinePowerupCooldownTime(int difficulty) {
|
int determinePowerupCooldownTime(int difficulty) {
|
||||||
if (difficulty > MAX_DIFFICULTY) exit(1);
|
if (difficulty > MAX_DIFFICULTY) exit(1);
|
||||||
|
|
||||||
return difficultyBands[difficulty] + rand() % difficultyBands[difficulty];
|
return difficulty * 10 + rand() % 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if every shot lands, you should run out slightly before the next powerup
|
// if every shot lands, you should run out slightly before the next powerup
|
||||||
|
@ -20,9 +20,8 @@ int determinePowerupCooldownTime(int difficulty) {
|
||||||
int determineWeaponRounds(int difficulty) {
|
int determineWeaponRounds(int difficulty) {
|
||||||
if (difficulty > MAX_DIFFICULTY) exit(1);
|
if (difficulty > MAX_DIFFICULTY) exit(1);
|
||||||
|
|
||||||
return difficultyBands[difficulty] +
|
return difficultyBands[difficulty] / 2 +
|
||||||
difficultyBands[difficulty] / 2 +
|
rand() % (difficultyBands[difficulty] / 8);
|
||||||
rand() % (difficultyBands[difficulty] / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void processPowerupCooldown(
|
void processPowerupCooldown(
|
||||||
|
@ -32,7 +31,7 @@ void processPowerupCooldown(
|
||||||
int killCount
|
int killCount
|
||||||
) {
|
) {
|
||||||
if (playerPowerup->isActive) return;
|
if (playerPowerup->isActive) return;
|
||||||
if (rabbitWeaponry->currentWeapon != WEAPON_TYPE_SINGLE_SHOT_GUN) return;
|
//if (rabbitWeaponry->currentWeapon != WEAPON_TYPE_SINGLE_SHOT_GUN) return;
|
||||||
|
|
||||||
playerPowerup->cooldown -= killCount;
|
playerPowerup->cooldown -= killCount;
|
||||||
if (playerPowerup->cooldown <= 0) {
|
if (playerPowerup->cooldown <= 0) {
|
||||||
|
@ -40,7 +39,7 @@ void processPowerupCooldown(
|
||||||
playerPowerup->y = TILE_SIZE + rand() % ((ARENA_HEIGHT_TILES - 2) * TILE_SIZE);
|
playerPowerup->y = TILE_SIZE + rand() % ((ARENA_HEIGHT_TILES - 2) * TILE_SIZE);
|
||||||
playerPowerup->isActive = 1;
|
playerPowerup->isActive = 1;
|
||||||
playerPowerup->willBeInactive = 0;
|
playerPowerup->willBeInactive = 0;
|
||||||
playerPowerup->type = 2;
|
playerPowerup->type = rand() % 2 + 1;
|
||||||
|
|
||||||
playerPowerup->cooldown = determinePowerupCooldownTime(globalGameState->difficulty);
|
playerPowerup->cooldown = determinePowerupCooldownTime(globalGameState->difficulty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,17 @@
|
||||||
void TestDeterminePowerupCooldownTime(CuTest *tc) {
|
void TestDeterminePowerupCooldownTime(CuTest *tc) {
|
||||||
srand(1);
|
srand(1);
|
||||||
|
|
||||||
CuAssertIntEquals(tc, 38, determinePowerupCooldownTime(0));
|
CuAssertIntEquals(tc, 18, determinePowerupCooldownTime(0));
|
||||||
CuAssertIntEquals(tc, 60, determinePowerupCooldownTime(1));
|
CuAssertIntEquals(tc, 28, determinePowerupCooldownTime(1));
|
||||||
CuAssertIntEquals(tc, 85, determinePowerupCooldownTime(2));
|
CuAssertIntEquals(tc, 33, determinePowerupCooldownTime(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDetermineWeaponRounds(CuTest *tc) {
|
void TestDetermineWeaponRounds(CuTest *tc) {
|
||||||
srand(1);
|
srand(1);
|
||||||
|
|
||||||
CuAssertIntEquals(tc, 53, determineWeaponRounds(0));
|
CuAssertIntEquals(tc, 10, determineWeaponRounds(0));
|
||||||
CuAssertIntEquals(tc, 71, determineWeaponRounds(1));
|
CuAssertIntEquals(tc, 23, determineWeaponRounds(1));
|
||||||
CuAssertIntEquals(tc, 85, determineWeaponRounds(2));
|
CuAssertIntEquals(tc, 36, determineWeaponRounds(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ void TestProcessPowerupCooldown_WeaponActive(CuTest *tc) {
|
||||||
10
|
10
|
||||||
);
|
);
|
||||||
|
|
||||||
CuAssertIntEquals(tc, 100, playerPowerup.cooldown);
|
CuAssertIntEquals(tc, 90, playerPowerup.cooldown);
|
||||||
CuAssertIntEquals(tc, 0, playerPowerup.isActive);
|
CuAssertIntEquals(tc, 0, playerPowerup.isActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ void TestProcessPowerupCooldown_Triggered(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 0, playerPowerup.willBeInactive);
|
CuAssertIntEquals(tc, 0, playerPowerup.willBeInactive);
|
||||||
|
|
||||||
// rand
|
// rand
|
||||||
CuAssertIntEquals(tc, 33, playerPowerup.cooldown);
|
CuAssertIntEquals(tc, 15, playerPowerup.cooldown);
|
||||||
CuAssertIntEquals(tc, 58, playerPowerup.x);
|
CuAssertIntEquals(tc, 58, playerPowerup.x);
|
||||||
CuAssertIntEquals(tc, 178, playerPowerup.y);
|
CuAssertIntEquals(tc, 178, playerPowerup.y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ void TestSpawnEnemy(CuTest *tc) {
|
||||||
|
|
||||||
// randomized values
|
// randomized values
|
||||||
CuAssertIntEquals(tc, 1, enemyPosition.hitPoints);
|
CuAssertIntEquals(tc, 1, enemyPosition.hitPoints);
|
||||||
CuAssertIntEquals(tc, 103, enemyPosition.enemyFireDelayStep);
|
CuAssertIntEquals(tc, 108, enemyPosition.enemyFireDelayStep);
|
||||||
|
|
||||||
// from spawndetails
|
// from spawndetails
|
||||||
CuAssertIntEquals(tc, 1, enemyPosition.gateExitedFrom);
|
CuAssertIntEquals(tc, 1, enemyPosition.gateExitedFrom);
|
||||||
|
|
|
@ -1391,10 +1391,10 @@ sprite_bullet_:
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
|
||||||
|
|
||||||
|
mov BYTE PTR [eax + -321], 5
|
||||||
|
mov BYTE PTR [eax + -320], 5
|
||||||
|
mov BYTE PTR [eax + -1], 5
|
||||||
mov BYTE PTR [eax + 0], 5
|
mov BYTE PTR [eax + 0], 5
|
||||||
mov BYTE PTR [eax + 1], 5
|
|
||||||
mov BYTE PTR [eax + 320], 5
|
|
||||||
mov BYTE PTR [eax + 321], 5
|
|
||||||
|
|
||||||
pop ebp
|
pop ebp
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -66,9 +66,9 @@ extern void sprite_mouse(byte *);
|
||||||
|
|
||||||
extern void sprite_bullet(byte *);
|
extern void sprite_bullet(byte *);
|
||||||
|
|
||||||
#define SPRITE_BULLET_WIDTH (4)
|
#define SPRITE_BULLET_WIDTH (2)
|
||||||
|
|
||||||
#define SPRITE_BULLET_HEIGHT (4)
|
#define SPRITE_BULLET_HEIGHT (2)
|
||||||
|
|
||||||
#define SPRITE_BULLET_OFFSET_X (1)
|
#define SPRITE_BULLET_OFFSET_X (1)
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ files:
|
||||||
dimensions: [8, 8]
|
dimensions: [8, 8]
|
||||||
offset: [4, 4]
|
offset: [4, 4]
|
||||||
bullet:
|
bullet:
|
||||||
position: [16, 28]
|
position: [17, 29]
|
||||||
dimensions: [4, 4]
|
dimensions: [2, 2]
|
||||||
offset: [1, 1]
|
offset: [1, 1]
|
||||||
enemy:
|
enemy:
|
||||||
position: [0, 20]
|
position: [0, 20]
|
||||||
|
|
|
@ -13,6 +13,9 @@ void populateKeyboardKeydownState() {
|
||||||
keyboardKeydownState.KEY_A = keystateBits[3] & 0x40;
|
keyboardKeydownState.KEY_A = keystateBits[3] & 0x40;
|
||||||
keyboardKeydownState.KEY_S = keystateBits[3] & 0x80;
|
keyboardKeydownState.KEY_S = keystateBits[3] & 0x80;
|
||||||
keyboardKeydownState.KEY_D = keystateBits[4] & 0x01;
|
keyboardKeydownState.KEY_D = keystateBits[4] & 0x01;
|
||||||
|
keyboardKeydownState.KEY_I = keystateBits[2] & 0x80;
|
||||||
|
keyboardKeydownState.KEY_O = keystateBits[3] & 0x01;
|
||||||
|
keyboardKeydownState.KEY_P = keystateBits[3] & 0x02;
|
||||||
keyboardKeydownState.KEY_ESC = keystateBits[0] & 0x02;
|
keyboardKeydownState.KEY_ESC = keystateBits[0] & 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ struct KeyboardKeydownState {
|
||||||
byte KEY_A;
|
byte KEY_A;
|
||||||
byte KEY_S;
|
byte KEY_S;
|
||||||
byte KEY_D;
|
byte KEY_D;
|
||||||
|
byte KEY_I;
|
||||||
|
byte KEY_O;
|
||||||
|
byte KEY_P;
|
||||||
byte KEY_ESC;
|
byte KEY_ESC;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
63
system/vga.c
63
system/vga.c
|
@ -2,6 +2,7 @@
|
||||||
#include "pc_stuff.h"
|
#include "pc_stuff.h"
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -128,26 +129,68 @@ void setVGAColors(struct VGAColor colors[], int totalColors) {
|
||||||
|
|
||||||
#define RENDER_STRING_FAILSAFE (80)
|
#define RENDER_STRING_FAILSAFE (80)
|
||||||
|
|
||||||
|
struct CharRowDetails {
|
||||||
|
char c;
|
||||||
|
char color;
|
||||||
|
char backgroundColor;
|
||||||
|
char writeBackgroundColor;
|
||||||
|
char* pos;
|
||||||
|
} charRowDetails;
|
||||||
|
|
||||||
|
// Write this in inline assembler for practice!
|
||||||
|
void plotCharRow();
|
||||||
|
#pragma aux plotCharRow = \
|
||||||
|
"mov al, [edi]" \
|
||||||
|
"mov ah, 8" \
|
||||||
|
"mov bl, [edi+1]" \
|
||||||
|
"mov bh, [edi+2]" \
|
||||||
|
"mov cl, [edi+3]" \
|
||||||
|
"mov edi, [edi + 4]" \
|
||||||
|
"nextBit: mov ch, al" \
|
||||||
|
"and ch,1" \
|
||||||
|
"cmp ch,1" \
|
||||||
|
"jne background" \
|
||||||
|
"mov [edi], bl" \
|
||||||
|
"jmp maybeKeepGoing" \
|
||||||
|
"background: cmp cl,0" \
|
||||||
|
"je maybeKeepGoing" \
|
||||||
|
"mov [edi], bh" \
|
||||||
|
"maybeKeepGoing: ror al, 1" \
|
||||||
|
"inc edi" \
|
||||||
|
"dec ah" \
|
||||||
|
"jnz nextBit" \
|
||||||
|
parm [edi] \
|
||||||
|
modify [eax ebx ecx edi];
|
||||||
|
|
||||||
void renderStringToDrawBuffer(char* buffer, int color, int backgroundColor, int x, int y) {
|
void renderStringToDrawBuffer(char* buffer, int color, int backgroundColor, int x, int y) {
|
||||||
char *bufferPos = buffer, currentCharacter, charRow;
|
char *bufferPos = buffer, currentCharacter, charRow;
|
||||||
int i, fontX, fontY, currentX = x;
|
int i, fontX, fontY, currentX = x;
|
||||||
|
|
||||||
|
int charX, fontYs[8];
|
||||||
|
|
||||||
|
charRowDetails.color = color;
|
||||||
|
if (backgroundColor == -1) {
|
||||||
|
charRowDetails.backgroundColor = 0;
|
||||||
|
}
|
||||||
|
charRowDetails.writeBackgroundColor = backgroundColor != -1;
|
||||||
|
|
||||||
|
for (fontY = 0; fontY < 8; ++fontY) {
|
||||||
|
fontYs[fontY] = (y + fontY) * VGA_DISPLAY_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
charX = x;
|
||||||
|
|
||||||
for (i = 0; i < RENDER_STRING_FAILSAFE; ++i) {
|
for (i = 0; i < RENDER_STRING_FAILSAFE; ++i) {
|
||||||
currentCharacter = *(bufferPos++);
|
currentCharacter = *(bufferPos++);
|
||||||
if (!currentCharacter) break;
|
if (!currentCharacter) break;
|
||||||
|
|
||||||
for (fontY = 0; fontY < 8; ++fontY) {
|
for (fontY = 0; fontY < 8; ++fontY) {
|
||||||
charRow = font8x8_basic[currentCharacter][fontY];
|
charRowDetails.c = font8x8_basic[currentCharacter][fontY];
|
||||||
|
charRowDetails.pos = drawBuffer + fontYs[fontY] + charX;
|
||||||
|
|
||||||
for (fontX = 0; fontX < 8; ++fontX) {
|
plotCharRow(&charRowDetails);
|
||||||
if (charRow & (1 << fontX)) {
|
|
||||||
drawBuffer[(y + fontY) * VGA_DISPLAY_WIDTH + (i * 8 + x + fontX)] = color;
|
|
||||||
} else {
|
|
||||||
if (backgroundColor > -1) {
|
|
||||||
drawBuffer[(y + fontY) * VGA_DISPLAY_WIDTH + (i * 8 + x + fontX)] = backgroundColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
charX += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue