dos-vga-arena-shooter-game/game.c

276 lines
7.1 KiB
C
Raw Normal View History

2024-02-15 13:34:50 +00:00
#include <stdio.h>
2024-02-20 11:48:12 +00:00
#include <math.h>
#include <conio.h>
2024-02-15 13:34:50 +00:00
2024-02-20 13:00:13 +00:00
#include "system/vga.h"
#include "system/keyboard.h"
#include "system/mouse_io.h"
#include "system/pc_stuff.h"
2024-02-21 13:25:55 +00:00
2024-02-15 13:34:50 +00:00
#include "bmpload.h"
2024-02-20 17:51:59 +00:00
#include "const.h"
#include "arena.h"
2024-02-21 13:25:55 +00:00
#include "movement.h"
2024-02-15 01:15:55 +00:00
2024-02-15 13:34:50 +00:00
struct BMPImage spritesheetImage;
struct VGAColor vgaColors[256];
2024-02-21 13:25:55 +00:00
struct SpriteRender rabbit, mouse, bullet;
struct RabbitPosition rabbitPosition = {
.rabbitPosition = { 60, 60 },
.rabbitLimits = { { 20, 20 }, { 180, 180 } },
.mousePosition = { 0, 0 },
.rabbitVelocity = { 0, 0 },
.mouseDotPosition = { 0, 0 }
};
struct BulletPosition rabbitBulletPosition[RABBIT_BULLET_LIMIT];
struct RabbitWeaponry rabbitWeaponry;
void setupRabbitBullets() {
char i;
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
rabbitBulletPosition[i].isActive = 0;
rabbitBulletPosition[i].willBeInactive = 0;
}
rabbitWeaponry.cooldown = 0;
}
void attemptToFireRabbitBullet() {
char okToFire = 0, availableBullet, i;
signed char doubleVelocityX, doubleVelocityY;
if (rabbitWeaponry.cooldown > 0) return;
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (rabbitBulletPosition[i].isActive == 0) {
okToFire = 1;
availableBullet = i;
break;
}
}
if (!okToFire) return;
rabbitWeaponry.cooldown = RABBIT_BULLET_COOLDOWN;
doubleVelocityX = sin(rabbitPosition.mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
doubleVelocityY = -cos(rabbitPosition.mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2);
rabbitBulletPosition[availableBullet].isActive = 1;
rabbitBulletPosition[availableBullet].willBeInactive = 0;
rabbitBulletPosition[availableBullet].x = rabbitPosition.rabbitPosition[0];
rabbitBulletPosition[availableBullet].y = rabbitPosition.rabbitPosition[1] - RABBIT_BULLET_HEIGHT_START;
rabbitBulletPosition[availableBullet].oldX = rabbitBulletPosition[availableBullet].x;
rabbitBulletPosition[availableBullet].oldY = rabbitBulletPosition[availableBullet].y;
rabbitBulletPosition[availableBullet].velocityXSteps[0] = doubleVelocityX / RABBIT_BULLET_VELOCITY;
rabbitBulletPosition[availableBullet].velocityXSteps[1] = doubleVelocityX % RABBIT_BULLET_VELOCITY;
rabbitBulletPosition[availableBullet].velocityYSteps[0] = doubleVelocityY / RABBIT_BULLET_VELOCITY;
rabbitBulletPosition[availableBullet].velocityYSteps[1] = doubleVelocityY % RABBIT_BULLET_VELOCITY;
rabbitBulletPosition[availableBullet].velocityStep = 0;
}
void advanceRabbitBullets() {
char i;
signed char velocityX, velocityY;
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (!rabbitBulletPosition[i].isActive) continue;
rabbitBulletPosition[i].oldX = rabbitBulletPosition[i].x;
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].x < MOUSE_LIMIT_LEFT) rabbitBulletPosition[i].willBeInactive = 1;
if (rabbitBulletPosition[i].x >= MOUSE_LIMIT_RIGHT) rabbitBulletPosition[i].willBeInactive = 1;
if (rabbitBulletPosition[i].y < MOUSE_LIMIT_TOP) rabbitBulletPosition[i].willBeInactive = 1;
if (rabbitBulletPosition[i].y >= MOUSE_LIMIT_BOTTOM) rabbitBulletPosition[i].willBeInactive = 1;
rabbitBulletPosition[i].velocityStep = 1 - rabbitBulletPosition[i].velocityStep;
}
if (rabbitWeaponry.cooldown > 0) rabbitWeaponry.cooldown--;
}
2024-02-16 02:18:15 +00:00
void setupRabbitSprites() {
buildSpriteFromSpritesheet(
&spritesheetImage,
&rabbit,
0, 20, 16, 16
);
2024-02-20 11:48:12 +00:00
rabbit.offsetX = 8;
rabbit.offsetY = 15;
buildSpriteFromSpritesheet(
&spritesheetImage,
&mouse,
16, 20, 8, 8
);
mouse.offsetX = 4;
mouse.offsetY = 4;
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
buildSpriteFromSpritesheet(
&spritesheetImage,
&bullet,
16, 28, 4, 4
);
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
bullet.offsetX = 1;
bullet.offsetY = 1;
}
2024-02-16 02:18:15 +00:00
2024-02-20 11:48:12 +00:00
struct MouseStatus mouseStatus;
2024-02-16 02:18:15 +00:00
2024-02-20 17:39:28 +00:00
void renderMouse() {
2024-02-21 13:25:55 +00:00
mouse.x = rabbitPosition.mousePosition[0];
mouse.y = rabbitPosition.mousePosition[1];
2024-02-20 11:48:12 +00:00
drawSprite(&mouse);
2024-02-21 13:25:55 +00:00
drawPixel(rabbitPosition.mouseDotPosition[0], rabbitPosition.mouseDotPosition[1], 2);
2024-02-20 11:48:12 +00:00
}
void renderRabbit() {
2024-02-21 13:25:55 +00:00
rabbit.x = rabbitPosition.rabbitPosition[0];
rabbit.y = rabbitPosition.rabbitPosition[1];
2024-02-20 17:39:28 +00:00
2024-02-16 02:18:15 +00:00
drawSprite(&rabbit);
}
2024-02-21 13:25:55 +00:00
void renderRabbitBullets() {
char i;
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
char buffer[20];
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (!rabbitBulletPosition[i].isActive) continue;
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
bullet.x = rabbitBulletPosition[i].x;
bullet.y = rabbitBulletPosition[i].y;
2024-02-16 02:18:15 +00:00
2024-02-21 13:25:55 +00:00
sprintf(buffer, "%d %d", bullet.x, bullet.y);
writeString(buffer, 0, 10);
drawSprite(&bullet);
2024-02-16 02:18:15 +00:00
}
}
2024-02-20 13:00:13 +00:00
struct SpriteBounds bounds;
2024-02-20 11:48:12 +00:00
void drawOnlyMouseArena() {
2024-02-21 13:25:55 +00:00
mouse.x = rabbitPosition.oldMousePosition[0];
mouse.y = rabbitPosition.oldMousePosition[1];
2024-02-20 11:48:12 +00:00
getSpriteBounds(&mouse, &bounds);
2024-02-20 17:51:59 +00:00
drawOnlyArena(&bounds);
2024-02-20 17:39:28 +00:00
2024-02-21 13:25:55 +00:00
bounds.top = rabbitPosition.oldMouseDotPosition[1];
bounds.bottom = rabbitPosition.oldMouseDotPosition[1];
bounds.left = rabbitPosition.oldMouseDotPosition[0];
bounds.right = rabbitPosition.oldMouseDotPosition[0];
2024-02-20 17:51:59 +00:00
drawOnlyArena(&bounds);
2024-02-20 11:48:12 +00:00
}
void drawOnlyRabbitArena() {
2024-02-21 13:25:55 +00:00
rabbit.x = rabbitPosition.oldRabbitPosition[0];
rabbit.y = rabbitPosition.oldRabbitPosition[1];
2024-02-20 11:48:12 +00:00
getSpriteBounds(&rabbit, &bounds);
2024-02-20 17:51:59 +00:00
drawOnlyArena(&bounds);
2024-02-20 11:48:12 +00:00
}
2024-02-21 13:25:55 +00:00
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;
getSpriteBounds(&bullet, &bounds);
drawOnlyArena(&bounds);
if (rabbitBulletPosition[i].willBeInactive) {
rabbitBulletPosition[i].isActive = 0;
}
}
}
2024-02-15 01:15:55 +00:00
int main(void) {
2024-02-15 13:34:50 +00:00
FILE *fh;
2024-02-15 01:15:55 +00:00
int keepRunning = 1;
installKeyboardHandler();
2024-02-15 13:34:50 +00:00
initializeDrawBuffer();
fh = fopen("sprtsht.bmp", "rb");
if (readBMPIntoNewMemory(fh, &spritesheetImage)) return 1;
fclose(fh);
spritesheetImage.transparentColor = 0;
2024-02-20 17:51:59 +00:00
setupWallSprites(&spritesheetImage);
2024-02-16 02:18:15 +00:00
setupRabbitSprites();
2024-02-21 13:25:55 +00:00
setupRabbitBullets();
2024-02-15 13:34:50 +00:00
setVideoMode(VIDEO_MODE_VGA_256);
bmp256ColorPaletteToVGAColorPalette(&spritesheetImage, vgaColors);
setVGAColors(vgaColors, 256);
2024-02-15 01:15:55 +00:00
2024-02-20 11:48:12 +00:00
activateMouse(&mouseStatus);
2024-02-16 02:18:15 +00:00
buildArena();
2024-02-21 13:25:55 +00:00
clearArenaRedrawRequests();
2024-02-15 13:34:50 +00:00
2024-02-16 02:18:15 +00:00
while (keepRunning) {
readMouse(&mouseStatus);
populateKeyboardKeydownState();
2024-02-21 13:25:55 +00:00
handleRabbitMovement(
&rabbitPosition,
&keyboardKeydownState
);
captureAndLimitMousePosition(
&rabbitPosition,
&mouseStatus
);
calculateTargetAngle(
&rabbitPosition,
&mouseStatus
);
if (mouseStatus.leftButtonDown) attemptToFireRabbitBullet();
advanceRabbitBullets();
2024-02-15 13:34:50 +00:00
2024-02-16 02:18:15 +00:00
drawOnlyRabbitArena();
2024-02-20 11:48:12 +00:00
drawOnlyMouseArena();
2024-02-21 13:25:55 +00:00
drawOnlyRabbitBulletArena();
redrawArena();
2024-02-16 02:18:15 +00:00
renderRabbit();
2024-02-20 11:48:12 +00:00
renderMouse();
2024-02-21 13:25:55 +00:00
renderRabbitBullets();
2024-02-20 13:20:35 +00:00
waitStartVbl();
2024-02-15 13:34:50 +00:00
copyDrawBufferToDisplay();
2024-02-15 01:15:55 +00:00
2024-02-15 13:34:50 +00:00
waitEndVbl();
2024-02-16 02:18:15 +00:00
2024-02-20 17:39:28 +00:00
if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; }
2024-02-15 01:15:55 +00:00
}
2024-02-16 02:18:15 +00:00
freeBMP(&spritesheetImage);
setVideoMode(VIDEO_MODE_80x25_TEXT);
uninstallKeyboardHandler();
fprintf(stderr, "meow\n");
2024-02-21 13:25:55 +00:00
2024-02-15 13:34:50 +00:00
return 0;
2024-02-15 01:15:55 +00:00
}