667 lines
15 KiB
C
667 lines
15 KiB
C
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <conio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#include "sprites.h"
|
|
#include "system/vga.h"
|
|
#include "system/keyboard.h"
|
|
#include "system/mouse_io.h"
|
|
#include "system/pc_stuff.h"
|
|
|
|
#include "bmpload.h"
|
|
#include "const.h"
|
|
#include "arena.h"
|
|
#include "movement.h"
|
|
#include "combat.h"
|
|
#include "game.h"
|
|
#include "spawn.h"
|
|
#include "powerup.h"
|
|
|
|
struct BMPImage spritesheetImage;
|
|
struct VGAColor vgaColors[256];
|
|
|
|
struct MouseStatus mouseStatus;
|
|
|
|
struct RabbitPosition rabbitPosition = {
|
|
.rabbitPosition = { 60, 60 },
|
|
.rabbitLimits = {
|
|
{ 20, 20 },
|
|
{ (ARENA_WIDTH_TILES - 1) * TILE_SIZE - 2, (ARENA_HEIGHT_TILES - 1) * TILE_SIZE - 2 }
|
|
},
|
|
.mousePosition = { 0, 0 },
|
|
.rabbitVelocity = { 0, 0 },
|
|
.mouseDotPosition = { 0, 0 }
|
|
};
|
|
struct EnemyPosition enemyPosition[ENEMY_MAX_COUNT];
|
|
struct BulletPosition rabbitBulletPosition[RABBIT_BULLET_LIMIT];
|
|
struct BulletPosition enemyBulletPosition[ENEMY_BULLET_LIMIT];
|
|
struct RabbitWeaponry rabbitWeaponry;
|
|
struct PlayerPowerup playerPowerup;
|
|
|
|
struct GlobalGameState globalGameState = {
|
|
.spawnCooldown = 0,
|
|
.difficulty = 0,
|
|
.kills = 0,
|
|
.coins = 0,
|
|
.health = RABBIT_HEALTH_MAX,
|
|
.maxHealth = RABBIT_HEALTH_MAX,
|
|
.healthGainPerKill = 1,
|
|
.damageUpgradeLevel = 0,
|
|
.healthUpgradeLevel = 0,
|
|
.healthGainUpgradeLevel = 0
|
|
};
|
|
|
|
void setupRabbitBullets() {
|
|
int i;
|
|
|
|
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
|
|
rabbitBulletPosition[i].isActive = 0;
|
|
rabbitBulletPosition[i].willBeInactive = 0;
|
|
}
|
|
|
|
rabbitWeaponry.cooldown = 0;
|
|
rabbitWeaponry.currentWeapon = WEAPON_TYPE_SINGLE_SHOT_GUN;
|
|
rabbitWeaponry.currentWeaponRemainingRounds = 0;
|
|
rabbitWeaponry.damage = 1;
|
|
}
|
|
|
|
void setupPowerup() {
|
|
playerPowerup.x = 100;
|
|
playerPowerup.y = 100;
|
|
playerPowerup.cooldown = determinePowerupCooldownTime(globalGameState.difficulty);
|
|
playerPowerup.type = POWERUP_TYPE_SHOTGUN;
|
|
playerPowerup.isActive = 0;
|
|
}
|
|
|
|
void setupEnemyBullets() {
|
|
int i;
|
|
|
|
for (i = 0; i < ENEMY_BULLET_LIMIT; ++i) {
|
|
enemyBulletPosition[i].isActive = 0;
|
|
enemyBulletPosition[i].willBeInactive = 0;
|
|
}
|
|
}
|
|
|
|
void setupEnemies() {
|
|
int i;
|
|
|
|
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
|
enemyPosition[i].isActive = 0;
|
|
enemyPosition[i].willBeInactive = 0;
|
|
}
|
|
}
|
|
|
|
void setupEnemySprites() {
|
|
buildCompiledSprite(
|
|
&sprite_enemy,
|
|
&enemy,
|
|
SPRITE_ENEMY_WIDTH,
|
|
SPRITE_ENEMY_HEIGHT,
|
|
SPRITE_ENEMY_OFFSET_X,
|
|
SPRITE_ENEMY_OFFSET_Y
|
|
);
|
|
|
|
buildCompiledSprite(
|
|
&sprite_bullet,
|
|
&enemyBullet,
|
|
SPRITE_BULLET_WIDTH,
|
|
SPRITE_BULLET_HEIGHT,
|
|
SPRITE_BULLET_OFFSET_X,
|
|
SPRITE_BULLET_OFFSET_Y
|
|
);
|
|
}
|
|
|
|
void setupRabbitSprites() {
|
|
buildCompiledSprite(
|
|
&sprite_rabbit,
|
|
&rabbit,
|
|
SPRITE_RABBIT_WIDTH,
|
|
SPRITE_RABBIT_HEIGHT,
|
|
SPRITE_RABBIT_OFFSET_X,
|
|
SPRITE_RABBIT_OFFSET_Y
|
|
);
|
|
|
|
buildCompiledSprite(
|
|
&sprite_mouse,
|
|
&mouse,
|
|
SPRITE_MOUSE_WIDTH,
|
|
SPRITE_MOUSE_HEIGHT,
|
|
SPRITE_MOUSE_OFFSET_X,
|
|
SPRITE_MOUSE_OFFSET_Y
|
|
);
|
|
|
|
buildCompiledSprite(
|
|
&sprite_bullet,
|
|
&bullet,
|
|
SPRITE_BULLET_WIDTH,
|
|
SPRITE_BULLET_HEIGHT,
|
|
SPRITE_BULLET_OFFSET_X,
|
|
SPRITE_BULLET_OFFSET_Y
|
|
);
|
|
}
|
|
|
|
void setupPowerupSprites() {
|
|
buildCompiledSprite(
|
|
&sprite_shotgun,
|
|
&shotgun,
|
|
SPRITE_SHOTGUN_WIDTH,
|
|
SPRITE_SHOTGUN_HEIGHT,
|
|
SPRITE_SHOTGUN_OFFSET_X,
|
|
SPRITE_SHOTGUN_OFFSET_Y
|
|
);
|
|
|
|
buildCompiledSprite(
|
|
&sprite_beam,
|
|
&beam,
|
|
SPRITE_BEAM_WIDTH,
|
|
SPRITE_BEAM_HEIGHT,
|
|
SPRITE_BEAM_OFFSET_X,
|
|
SPRITE_BEAM_OFFSET_Y
|
|
);
|
|
}
|
|
|
|
void renderMouse() {
|
|
mouse.x = rabbitPosition.mousePosition[0];
|
|
mouse.y = rabbitPosition.mousePosition[1];
|
|
drawCompiledSprite(&mouse);
|
|
|
|
mouse.x = rabbitPosition.mouseDotPosition[0];
|
|
mouse.y = rabbitPosition.mouseDotPosition[1];
|
|
drawCompiledSprite(&mouse);
|
|
}
|
|
|
|
void renderRabbit() {
|
|
rabbit.x = rabbitPosition.rabbitPosition[0];
|
|
rabbit.y = rabbitPosition.rabbitPosition[1];
|
|
drawCompiledSprite(&rabbit);
|
|
}
|
|
|
|
void renderEnemies() {
|
|
int i;
|
|
|
|
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
|
if (!enemyPosition[i].isActive) continue;
|
|
|
|
enemy.x = enemyPosition[i].enemyPosition[0];
|
|
enemy.y = enemyPosition[i].enemyPosition[1];
|
|
drawCompiledSprite(&enemy);
|
|
}
|
|
}
|
|
|
|
void renderRabbitBullets() {
|
|
char i;
|
|
|
|
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
|
|
if (!rabbitBulletPosition[i].isActive) continue;
|
|
|
|
bullet.x = rabbitBulletPosition[i].x;
|
|
bullet.y = rabbitBulletPosition[i].y;
|
|
drawCompiledSprite(&bullet);
|
|
}
|
|
}
|
|
|
|
void renderEnemyBullets() {
|
|
char i;
|
|
|
|
for (i = 0; i < ENEMY_BULLET_LIMIT; ++i) {
|
|
if (!enemyBulletPosition[i].isActive) continue;
|
|
|
|
enemyBullet.x = enemyBulletPosition[i].x;
|
|
enemyBullet.y = enemyBulletPosition[i].y;
|
|
drawCompiledSprite(&enemyBullet);
|
|
}
|
|
}
|
|
|
|
void renderPowerup() {
|
|
struct CompiledSpriteRender *which;
|
|
|
|
if (!playerPowerup.isActive) return;
|
|
|
|
switch (playerPowerup.type) {
|
|
case POWERUP_TYPE_SHOTGUN:
|
|
which = &shotgun;
|
|
break;
|
|
case POWERUP_TYPE_BEAM_WEAPON:
|
|
which = &beam;
|
|
break;
|
|
}
|
|
|
|
which->x = playerPowerup.x;
|
|
which->y = playerPowerup.y;
|
|
drawCompiledSprite(which);
|
|
}
|
|
|
|
void drawOnlyArenaForSprite(struct CompiledSpriteRender *sprite) {
|
|
getSpriteBounds(sprite, &bounds);
|
|
drawOnlyArena(&bounds);
|
|
}
|
|
|
|
void drawOnlyMouseArena() {
|
|
mouse.x = rabbitPosition.oldMousePosition[0];
|
|
mouse.y = rabbitPosition.oldMousePosition[1];
|
|
drawOnlyArenaForSprite(&mouse);
|
|
|
|
mouse.x = rabbitPosition.oldMouseDotPosition[0];
|
|
mouse.y = rabbitPosition.oldMouseDotPosition[1];
|
|
drawOnlyArenaForSprite(&mouse);
|
|
}
|
|
|
|
void drawOnlyRabbitArena() {
|
|
rabbit.x = rabbitPosition.oldRabbitPosition[0];
|
|
rabbit.y = rabbitPosition.oldRabbitPosition[1];
|
|
drawOnlyArenaForSprite(&rabbit);
|
|
}
|
|
|
|
void drawOnlyPowerupArena() {
|
|
struct CompiledSpriteRender *which;
|
|
|
|
if (!playerPowerup.isActive) return;
|
|
|
|
switch (playerPowerup.type) {
|
|
case POWERUP_TYPE_SHOTGUN:
|
|
which = &shotgun;
|
|
break;
|
|
case POWERUP_TYPE_BEAM_WEAPON:
|
|
which = &beam;
|
|
break;
|
|
}
|
|
|
|
which->x = playerPowerup.x;
|
|
which->y = playerPowerup.y;
|
|
drawOnlyArenaForSprite(which);
|
|
|
|
if (playerPowerup.willBeInactive) {
|
|
playerPowerup.isActive = 0;
|
|
}
|
|
}
|
|
|
|
void drawOnlyEnemiesArena() {
|
|
int i;
|
|
|
|
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
|
|
if (!enemyPosition[i].isActive) continue;
|
|
|
|
enemy.x = enemyPosition[i].oldEnemyPosition[0];
|
|
enemy.y = enemyPosition[i].oldEnemyPosition[1];
|
|
drawOnlyArenaForSprite(&enemy);
|
|
|
|
if (enemyPosition[i].willBeInactive) {
|
|
enemyPosition[i].isActive = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawOnlyRabbitBulletArena() {
|
|
int i;
|
|
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
|
|
if (!rabbitBulletPosition[i].isActive) continue;
|
|
|
|
bullet.x = rabbitBulletPosition[i].oldX;
|
|
bullet.y = rabbitBulletPosition[i].oldY;
|
|
drawOnlyArenaForSprite(&bullet);
|
|
|
|
if (rabbitBulletPosition[i].willBeInactive) {
|
|
rabbitBulletPosition[i].isActive = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawOnlyEnemyBulletArena() {
|
|
int i;
|
|
for (i = 0; i < ENEMY_BULLET_LIMIT; ++i) {
|
|
if (!enemyBulletPosition[i].isActive) continue;
|
|
|
|
enemyBullet.x = enemyBulletPosition[i].oldX;
|
|
enemyBullet.y = enemyBulletPosition[i].oldY;
|
|
drawOnlyArenaForSprite(&enemyBullet);
|
|
|
|
if (enemyBulletPosition[i].willBeInactive) {
|
|
enemyBulletPosition[i].isActive = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int setupGame() {
|
|
FILE *fh;
|
|
|
|
installKeyboardHandler();
|
|
initializeDrawBuffer();
|
|
|
|
buildDifficultyBands();
|
|
buildHitPointRages();
|
|
|
|
setupWallSprites();
|
|
setupRabbitSprites();
|
|
setupRabbitBullets();
|
|
setupEnemies();
|
|
setupEnemyBullets();
|
|
setupEnemySprites();
|
|
setupPowerup();
|
|
setupPowerupSprites();
|
|
|
|
setVideoMode(VIDEO_MODE_VGA_256);
|
|
|
|
setVGAColors(palette, PALETTE_COLOR_COUNT);
|
|
|
|
activateMouse(&mouseStatus);
|
|
|
|
buildArena();
|
|
clearArenaRedrawRequests();
|
|
|
|
srand(time(NULL));
|
|
|
|
return 0;
|
|
}
|
|
|
|
void handleMovement() {
|
|
handleRabbitMovement(
|
|
&rabbitPosition,
|
|
&keyboardKeydownState
|
|
);
|
|
handleEnemyMovement(
|
|
enemyPosition,
|
|
&rabbitPosition
|
|
);
|
|
captureAndLimitMousePosition(
|
|
&rabbitPosition,
|
|
&mouseStatus
|
|
);
|
|
calculateTargetAngle(
|
|
&rabbitPosition
|
|
);
|
|
}
|
|
|
|
void handleCombat() {
|
|
int didHitRabbit;
|
|
|
|
if (mouseStatus.leftButtonDown) {
|
|
if (attemptToFireRabbitBullet(
|
|
&rabbitPosition,
|
|
&rabbitWeaponry,
|
|
rabbitBulletPosition
|
|
)) {
|
|
fireCurrentWeaponOnce(
|
|
&rabbitWeaponry
|
|
);
|
|
}
|
|
}
|
|
|
|
attemptToFireEnemyBullets(
|
|
enemyPosition,
|
|
enemyBulletPosition,
|
|
&rabbitPosition,
|
|
globalGameState.difficulty
|
|
);
|
|
|
|
advanceRabbitBullets(
|
|
rabbitBulletPosition,
|
|
&rabbitWeaponry
|
|
);
|
|
|
|
advanceEnemyBullets(
|
|
enemyBulletPosition
|
|
);
|
|
|
|
buildCollisionGrids(
|
|
rabbitBulletPosition,
|
|
enemyBulletPosition,
|
|
&rabbitPosition,
|
|
enemyPosition,
|
|
&playerPowerup
|
|
);
|
|
|
|
didHitRabbit = handleRabbitToEnemyCollisions(
|
|
&rabbitPosition,
|
|
enemyPosition
|
|
);
|
|
|
|
if (didHitRabbit) {
|
|
globalGameState.health -= ENEMY_COLLISION_DAMAGE * didHitRabbit;
|
|
}
|
|
|
|
didHitRabbit = handleEnemyBulletToRabbitCollisions(
|
|
enemyBulletPosition,
|
|
&rabbitPosition
|
|
);
|
|
|
|
if (didHitRabbit) {
|
|
globalGameState.health -= ENEMY_BULLET_DAMAGE * didHitRabbit;
|
|
}
|
|
|
|
handleRabbitBulletToEnemyCollisions(
|
|
rabbitBulletPosition,
|
|
enemyPosition,
|
|
&rabbitWeaponry
|
|
);
|
|
|
|
if (handleRabbitToPowerupCollision(&rabbitPosition, &playerPowerup)) {
|
|
playerPowerup.willBeInactive = 1;
|
|
rabbitWeaponry.currentWeapon = playerPowerup.type;
|
|
rabbitWeaponry.currentWeaponRemainingRounds = determineWeaponRounds(globalGameState.difficulty);
|
|
}
|
|
}
|
|
|
|
void handleRedraw() {
|
|
drawOnlyRabbitArena();
|
|
drawOnlyEnemiesArena();
|
|
drawOnlyMouseArena();
|
|
drawOnlyRabbitBulletArena();
|
|
drawOnlyEnemyBulletArena();
|
|
drawOnlyPowerupArena();
|
|
|
|
redrawArena();
|
|
|
|
renderPowerup();
|
|
renderRabbit();
|
|
renderEnemies();
|
|
renderMouse();
|
|
renderRabbitBullets();
|
|
renderEnemyBullets();
|
|
}
|
|
|
|
/*
|
|
double speedCalcs[200];
|
|
int currentSpeedCalc = 0;
|
|
double averageSpeedCalc;
|
|
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) {
|
|
byte *drawBuffer;
|
|
int keepRunning = 1;
|
|
int i;
|
|
|
|
char buffer[20];
|
|
|
|
if (setupGame()) return 1;
|
|
|
|
drawBuffer = getDrawBuffer();
|
|
|
|
while (keepRunning) {
|
|
readMouse(&mouseStatus);
|
|
populateKeyboardKeydownState();
|
|
|
|
maybeSpawnEnemy(
|
|
&globalGameState,
|
|
enemyPosition,
|
|
&rabbitPosition
|
|
);
|
|
handleCombat();
|
|
handleRedraw();
|
|
handleEnemyKills(
|
|
enemyPosition,
|
|
&globalGameState,
|
|
&playerPowerup,
|
|
&rabbitWeaponry
|
|
);
|
|
handleMovement();
|
|
|
|
calculateUpgradesAvailable();
|
|
redrawGameStats();
|
|
|
|
if (keyboardKeydownState.KEY_P && upgradesAvailable.damage) {
|
|
globalGameState.coins -= damageUpgradeCosts[globalGameState.damageUpgradeLevel];
|
|
globalGameState.damageUpgradeLevel++;
|
|
rabbitWeaponry.damage++;
|
|
}
|
|
|
|
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();
|
|
copyDrawBufferToDisplay();
|
|
|
|
waitEndVbl();
|
|
|
|
if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; }
|
|
}
|
|
|
|
freeBMP(&spritesheetImage);
|
|
|
|
setVideoMode(VIDEO_MODE_80x25_TEXT);
|
|
uninstallKeyboardHandler();
|
|
|
|
/*
|
|
averageSpeedCalc = 0;
|
|
for (currentSpeedCalc = 0; currentSpeedCalc < 200; ++currentSpeedCalc) {
|
|
averageSpeedCalc += speedCalcs[currentSpeedCalc];
|
|
}
|
|
|
|
averageSpeedCalc /= 200;
|
|
|
|
fprintf(stderr, "average: %f\n", averageSpeedCalc);
|
|
*/
|
|
|
|
return 0;
|
|
}
|