firing works

This commit is contained in:
John Bintz 2024-02-21 08:25:55 -05:00
parent 129b1f7566
commit cf3cdad788
11 changed files with 341 additions and 126 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@
*.err
*.bak
*.lib
capture/

33
arena.c
View File

@ -61,6 +61,31 @@ void renderArenaTile(int x, int y) {
drawSprite(target);
}
char arenaRedrawRequests[ARENA_HEIGHT_TILES][ARENA_WIDTH_TILES];
void clearArenaRedrawRequests() {
int x, y;
for (y = 0; y < ARENA_HEIGHT_TILES; ++y) {
for (x = 0; x < ARENA_WIDTH_TILES; ++x) {
arenaRedrawRequests[y][x] = 0;
}
}
}
void redrawArena() {
int x, y;
for (y = 0; y < ARENA_HEIGHT_TILES; ++y) {
for (x = 0; x < ARENA_WIDTH_TILES; ++x) {
if (arenaRedrawRequests[y][x]) {
renderArenaTile(x, y);
arenaRedrawRequests[y][x] = 0;
}
}
}
}
void drawOnlyArena(struct SpriteBounds *bounds) {
int leftTileX, rightTileX,
topTileY, bottomTileY;
@ -70,10 +95,10 @@ void drawOnlyArena(struct SpriteBounds *bounds) {
topTileY = bounds->top / TILE_SIZE;
bottomTileY = bounds->bottom / TILE_SIZE;
renderArenaTile(leftTileX, topTileY);
renderArenaTile(rightTileX, topTileY);
renderArenaTile(rightTileX, bottomTileY);
renderArenaTile(leftTileX, bottomTileY);
arenaRedrawRequests[topTileY][leftTileX] = 1;
arenaRedrawRequests[topTileY][rightTileX] = 1;
arenaRedrawRequests[bottomTileY][leftTileX] = 1;
arenaRedrawRequests[bottomTileY][rightTileX] = 1;
}
void buildArena() {

View File

@ -1,6 +1,8 @@
#include "bmpload.h"
#include "system/vga.h"
void clearArenaRedrawRequests();
void redrawArena();
void drawOnlyArena(struct SpriteBounds *bounds);
void buildArena();
void setupWallSprites(struct BMPImage *);

23
const.h
View File

@ -1,5 +1,24 @@
#define TILE_SIZE (20)
#define RAD2DEG (180/3.14159)
#define DEG2RAD (3.14159/180)
#define ARENA_WIDTH_TILES (10)
#define ARENA_HEIGHT_TILES (10)
#define MOUSE_DISTANCE (32)
#define RABBIT_MOTION_DRAG (2)
#define RABBIT_MOTION_ACCELERATION (5)
#define RABBIT_MOTION_MAX_SPEED (12)
#define RABBIT_MOTION_VELOCITY_DECAY (5)
#define RABBIT_BULLET_LIMIT (12)
#define RABBIT_BULLET_VELOCITY (RABBIT_MOTION_ACCELERATION + 2)
#define RABBIT_BULLET_COOLDOWN (10)
#define RABBIT_BULLET_HEIGHT_START (8)
#define MOUSE_LIMIT_TOP (TILE_SIZE)
#define MOUSE_LIMIT_BOTTOM ((ARENA_HEIGHT_TILES - 1) * TILE_SIZE - 1)
#define MOUSE_LIMIT_LEFT (TILE_SIZE)
#define MOUSE_LIMIT_RIGHT ((ARENA_WIDTH_TILES - 1) * TILE_SIZE - 1)
#define RAD2DEG (180/3.14159)
#define DEG2RAD (3.14159/180)

257
game.c
View File

@ -6,14 +6,98 @@
#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"
struct BMPImage spritesheetImage;
struct VGAColor vgaColors[256];
struct SpriteRender rabbit, mouse;
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--;
}
void setupRabbitSprites() {
buildSpriteFromSpritesheet(
@ -33,116 +117,90 @@ void setupRabbitSprites() {
mouse.offsetX = 4;
mouse.offsetY = 4;
buildSpriteFromSpritesheet(
&spritesheetImage,
&bullet,
16, 28, 4, 4
);
bullet.offsetX = 1;
bullet.offsetY = 1;
}
#define RABBIT_MOTION_DRAG (2)
#define RABBIT_MOTION_ACCELERATION (5)
#define RABBIT_MOTION_MAX_SPEED (12)
int rabbitPosition[2] = { 60, 60 };
int oldRabbitPosition[2] = { 60, 60 };
int rabbitLimits[2][2] = {
{ 20, 20 },
{ 180, 180 }
};
signed char rabbitVelocity[2] = { 0, 0 };
struct MouseStatus mouseStatus;
char mousePosition[2] = { 0, 0 };
char oldMousePosition[2] = { 0, 0 };
char mouseDotPosition[2] = { 0, 0 };
char oldMouseDotPosition[2] = { 0, 0 };
void renderMouse() {
mouse.x = mousePosition[0];
mouse.y = mousePosition[1];
mouse.x = rabbitPosition.mousePosition[0];
mouse.y = rabbitPosition.mousePosition[1];
drawSprite(&mouse);
drawPixel(mouseDotPosition[0], mouseDotPosition[1], 2);
drawPixel(rabbitPosition.mouseDotPosition[0], rabbitPosition.mouseDotPosition[1], 2);
}
void renderRabbit() {
rabbit.x = rabbitPosition[0];
rabbit.y = rabbitPosition[1];
rabbit.x = rabbitPosition.rabbitPosition[0];
rabbit.y = rabbitPosition.rabbitPosition[1];
drawSprite(&rabbit);
}
void handleRabbitMovement() {
int i;
void renderRabbitBullets() {
char i;
if (keyboardKeydownState.KEY_W) {
rabbitVelocity[1] -= RABBIT_MOTION_ACCELERATION;
if (rabbitVelocity[1] < -RABBIT_MOTION_MAX_SPEED) {
rabbitVelocity[1] = -RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState.KEY_S) {
rabbitVelocity[1] += RABBIT_MOTION_ACCELERATION;
if (rabbitVelocity[1] > RABBIT_MOTION_MAX_SPEED) {
rabbitVelocity[1] = RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState.KEY_A) {
rabbitVelocity[0] -= RABBIT_MOTION_ACCELERATION;
if (rabbitVelocity[0] < -RABBIT_MOTION_MAX_SPEED) {
rabbitVelocity[0] = -RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState.KEY_D) {
rabbitVelocity[0] += RABBIT_MOTION_ACCELERATION;
if (rabbitVelocity[0] > RABBIT_MOTION_MAX_SPEED) {
rabbitVelocity[0] = RABBIT_MOTION_MAX_SPEED;
}
}
char buffer[20];
for (i = 0; i < 2; ++i) {
oldRabbitPosition[i] = rabbitPosition[i];
rabbitPosition[i] += (rabbitVelocity[i] / 5);
for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
if (!rabbitBulletPosition[i].isActive) continue;
if (rabbitPosition[i] < rabbitLimits[0][i]) {
rabbitPosition[i] = rabbitLimits[0][i];
}
if (rabbitPosition[i] >= rabbitLimits[1][i]) {
rabbitPosition[i] = rabbitLimits[1][i];
}
bullet.x = rabbitBulletPosition[i].x;
bullet.y = rabbitBulletPosition[i].y;
if (rabbitVelocity[i] < 0) {
rabbitVelocity[i] += RABBIT_MOTION_DRAG;
if (rabbitVelocity[i] > 0) rabbitVelocity[i] = 0;
}
if (rabbitVelocity[i] > 0) {
rabbitVelocity[i] -= RABBIT_MOTION_DRAG;
if (rabbitVelocity[i] < 0) rabbitVelocity[i] = 0;
}
sprintf(buffer, "%d %d", bullet.x, bullet.y);
writeString(buffer, 0, 10);
drawSprite(&bullet);
}
}
struct SpriteBounds bounds;
void drawOnlyMouseArena() {
mouse.x = oldMousePosition[0];
mouse.y = oldMousePosition[1];
mouse.x = rabbitPosition.oldMousePosition[0];
mouse.y = rabbitPosition.oldMousePosition[1];
getSpriteBounds(&mouse, &bounds);
drawOnlyArena(&bounds);
bounds.top = oldMouseDotPosition[1];
bounds.bottom = oldMouseDotPosition[1];
bounds.left = oldMouseDotPosition[0];
bounds.right = oldMouseDotPosition[0];
bounds.top = rabbitPosition.oldMouseDotPosition[1];
bounds.bottom = rabbitPosition.oldMouseDotPosition[1];
bounds.left = rabbitPosition.oldMouseDotPosition[0];
bounds.right = rabbitPosition.oldMouseDotPosition[0];
drawOnlyArena(&bounds);
}
void drawOnlyRabbitArena() {
rabbit.x = oldRabbitPosition[0];
rabbit.y = oldRabbitPosition[1];
rabbit.x = rabbitPosition.oldRabbitPosition[0];
rabbit.y = rabbitPosition.oldRabbitPosition[1];
getSpriteBounds(&rabbit, &bounds);
drawOnlyArena(&bounds);
}
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;
}
}
}
int main(void) {
FILE *fh;
int keepRunning = 1;
@ -158,26 +216,44 @@ int main(void) {
setupWallSprites(&spritesheetImage);
setupRabbitSprites();
setupRabbitBullets();
setVideoMode(VIDEO_MODE_VGA_256);
bmp256ColorPaletteToVGAColorPalette(&spritesheetImage, vgaColors);
setVGAColors(vgaColors, 256);
activateMouse(&mouseStatus);
limitMouseArea(0, 0, 199, 199);
buildArena();
clearArenaRedrawRequests();
while (keepRunning) {
readMouse(&mouseStatus);
populateKeyboardKeydownState();
handleRabbitMovement();
calculateTargetAngle();
handleRabbitMovement(
&rabbitPosition,
&keyboardKeydownState
);
captureAndLimitMousePosition(
&rabbitPosition,
&mouseStatus
);
calculateTargetAngle(
&rabbitPosition,
&mouseStatus
);
if (mouseStatus.leftButtonDown) attemptToFireRabbitBullet();
advanceRabbitBullets();
drawOnlyRabbitArena();
drawOnlyMouseArena();
drawOnlyRabbitBulletArena();
redrawArena();
renderRabbit();
renderMouse();
renderRabbitBullets();
waitStartVbl();
@ -188,33 +264,12 @@ int main(void) {
if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; }
}
// states:
// * main menu
// * play
// * quit
// * play
// * draw base map
// * draw sidebar
// * Game loop
// * get mouse
// * get keyboard
// * set character position
// * check for enemy spawn and spawn enemy if needed
// * check for character firing and able to fire, spawn bullet if allowed
// * check for each enemy firing and able to fire, spawn enemy bullet if allowed
// * check for bullet collisions
// * enemies are destroyed
// * character is damaged
// * check for bullets hitting the edges of the screen and remove
// *
//
freeBMP(&spritesheetImage);
setVideoMode(VIDEO_MODE_80x25_TEXT);
uninstallKeyboardHandler();
fprintf(stderr, "meow\n");
return 0;
}

View File

@ -1,4 +1,4 @@
obj = game.o bmpload.o arena.o
obj = game.o bmpload.o arena.o movement.o
all: system/system.lib game.exe .SYMBOLIC

View File

@ -1,28 +1,109 @@
#include "const.h"
#include <math.h>
void calculateTargetAngle() {
#include "const.h"
#include "movement.h"
#include "system/mouse_io.h"
#include "system/pc_stuff.h"
void captureAndLimitMousePosition(
struct RabbitPosition *pos,
struct MouseStatus *mouseStatus
) {
pos->oldMouseDotPosition[0] = pos->mouseDotPosition[0];
pos->oldMouseDotPosition[1] = pos->mouseDotPosition[1];
pos->mouseDotPosition[0] = mouseStatus->xPosition;
pos->mouseDotPosition[1] = mouseStatus->yPosition;
if (pos->mouseDotPosition[0] < MOUSE_LIMIT_LEFT) pos->mouseDotPosition[0] = MOUSE_LIMIT_LEFT;
if (pos->mouseDotPosition[0] >= MOUSE_LIMIT_RIGHT) pos->mouseDotPosition[0] = MOUSE_LIMIT_RIGHT;
if (pos->mouseDotPosition[1] < MOUSE_LIMIT_TOP) pos->mouseDotPosition[1] = MOUSE_LIMIT_TOP;
if (pos->mouseDotPosition[1] >= MOUSE_LIMIT_BOTTOM) pos->mouseDotPosition[1] = MOUSE_LIMIT_BOTTOM;
}
void calculateTargetAngle(
struct RabbitPosition *pos,
struct MouseStatus *mouseStatus
) {
float distanceX, distanceY;
float angle;
oldMouseDotPosition[0] = mouseDotPosition[0];
oldMouseDotPosition[1] = mouseDotPosition[1];
// Position the cursor
distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0];
distanceY = pos->mouseDotPosition[1] - pos->rabbitPosition[1] - RABBIT_BULLET_HEIGHT_START;
mouseDotPosition[0] = mouseStatus.xPosition;
mouseDotPosition[1] = mouseStatus.yPosition;
distanceX = mouseStatus.xPosition - rabbitPosition[0];
distanceY = mouseStatus.yPosition - rabbitPosition[1];
angle = atan2(distanceY, distanceX) * 180 / 3.14159 + 90;
angle = atan2(distanceY, distanceX) * RAD2DEG + 90;
if (angle < 0) angle += 360;
distanceX = sin(angle * DEG2RAD) * MOUSE_DISTANCE;
distanceY = -cos(angle * DEG2RAD) * MOUSE_DISTANCE;
oldMousePosition[0] = mousePosition[0];
oldMousePosition[1] = mousePosition[1];
pos->oldMousePosition[0] = pos->mousePosition[0];
pos->oldMousePosition[1] = pos->mousePosition[1];
mousePosition[0] = rabbitPosition[0] + distanceX;
mousePosition[1] = rabbitPosition[1] + distanceY;
pos->mousePosition[0] = pos->rabbitPosition[0] + distanceX;
pos->mousePosition[1] = pos->rabbitPosition[1] + distanceY;
// get the shot angle
distanceX = pos->mouseDotPosition[0] - pos->rabbitPosition[0];
distanceY = pos->mouseDotPosition[1] - pos->rabbitPosition[1];
angle = atan2(distanceY, distanceX) * RAD2DEG + 90;
if (angle < 0) angle += 360;
pos->mouseAngle = angle;
}
void handleRabbitMovement(
struct RabbitPosition *pos,
struct KeyboardKeydownState *keyboardKeydownState
) {
int i;
if (keyboardKeydownState->KEY_W) {
pos->rabbitVelocity[1] -= RABBIT_MOTION_ACCELERATION;
if (pos->rabbitVelocity[1] < -RABBIT_MOTION_MAX_SPEED) {
pos->rabbitVelocity[1] = -RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState->KEY_S) {
pos->rabbitVelocity[1] += RABBIT_MOTION_ACCELERATION;
if (pos->rabbitVelocity[1] > RABBIT_MOTION_MAX_SPEED) {
pos->rabbitVelocity[1] = RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState->KEY_A) {
pos->rabbitVelocity[0] -= RABBIT_MOTION_ACCELERATION;
if (pos->rabbitVelocity[0] < -RABBIT_MOTION_MAX_SPEED) {
pos->rabbitVelocity[0] = -RABBIT_MOTION_MAX_SPEED;
}
}
if (keyboardKeydownState->KEY_D) {
pos->rabbitVelocity[0] += RABBIT_MOTION_ACCELERATION;
if (pos->rabbitVelocity[0] > RABBIT_MOTION_MAX_SPEED) {
pos->rabbitVelocity[0] = RABBIT_MOTION_MAX_SPEED;
}
}
for (i = 0; i < 2; ++i) {
pos->oldRabbitPosition[i] = pos->rabbitPosition[i];
pos->rabbitPosition[i] += (pos->rabbitVelocity[i] / RABBIT_MOTION_VELOCITY_DECAY);
if (pos->rabbitPosition[i] < pos->rabbitLimits[0][i]) {
pos->rabbitPosition[i] = pos->rabbitLimits[0][i];
}
if (pos->rabbitPosition[i] >= pos->rabbitLimits[1][i]) {
pos->rabbitPosition[i] = pos->rabbitLimits[1][i];
}
if (pos->rabbitVelocity[i] < 0) {
pos->rabbitVelocity[i] += RABBIT_MOTION_DRAG;
if (pos->rabbitVelocity[i] > 0) pos->rabbitVelocity[i] = 0;
}
if (pos->rabbitVelocity[i] > 0) {
pos->rabbitVelocity[i] -= RABBIT_MOTION_DRAG;
if (pos->rabbitVelocity[i] < 0) pos->rabbitVelocity[i] = 0;
}
}
}

View File

@ -1,3 +1,35 @@
struct RabbitPositioning {
#include "system/keyboard.h"
struct RabbitPosition {
int rabbitPosition[2];
int oldRabbitPosition[2];
int rabbitLimits[2][2];
signed char rabbitVelocity[2];
int mousePosition[2];
int oldMousePosition[2];
int mouseDotPosition[2];
int oldMouseDotPosition[2];
int mouseAngle;
};
struct RabbitWeaponry {
char cooldown;
};
struct BulletPosition {
// 1 if the bullet should be rendered
char isActive;
// sweep up the bullet from the display
char willBeInactive;
int x, y;
int oldX, oldY;
signed char velocityXSteps[2], velocityYSteps[2];
char velocityStep;
};
void calculateTargetAngle(struct RabbitPosition*, struct MouseStatus*);
void captureAndLimitMousePosition(struct RabbitPosition*, struct MouseStatus*);
void handleRabbitMovement(struct RabbitPosition*, struct KeyboardKeydownState*);

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -15,11 +15,11 @@ void setVideoMode(byte videoMode) {
}
void waitStartVbl() {
while (inp(INPUT_STATUS) & VBLANK);
while (inp(INPUT_STATUS) & VBLANK);
}
void waitEndVbl() {
while (!(inp(INPUT_STATUS) & VBLANK));
while (!(inp(INPUT_STATUS) & VBLANK));
}
#define FAILSAFE (80)