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-15 13:34:50 +00:00
|
|
|
#include "bmpload.h"
|
2024-02-15 01:15:55 +00:00
|
|
|
|
2024-02-15 13:34:50 +00:00
|
|
|
struct BMPImage spritesheetImage;
|
|
|
|
struct VGAColor vgaColors[256];
|
|
|
|
|
|
|
|
struct SpriteRender arenaWallTop, arenaWallSide, arenaFloor;
|
2024-02-20 11:48:12 +00:00
|
|
|
struct SpriteRender rabbit, mouse;
|
2024-02-16 02:18:15 +00:00
|
|
|
|
|
|
|
void setupWallSprites() {
|
|
|
|
buildSpriteFromSpritesheet(
|
|
|
|
&spritesheetImage,
|
|
|
|
&arenaWallTop,
|
|
|
|
0, 0, 20, 20
|
|
|
|
);
|
|
|
|
|
|
|
|
buildSpriteFromSpritesheet(
|
|
|
|
&spritesheetImage,
|
|
|
|
&arenaWallSide,
|
|
|
|
20, 0, 20, 20
|
|
|
|
);
|
|
|
|
|
|
|
|
buildSpriteFromSpritesheet(
|
|
|
|
&spritesheetImage,
|
|
|
|
&arenaFloor,
|
|
|
|
40, 0, 20, 20
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
char arenaLayout[10][10] = {
|
|
|
|
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
|
|
|
|
{ 1, 2, 2, 2, 0, 0, 2, 2, 2, 1 },
|
|
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
|
|
{ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
|
|
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|
|
|
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
void renderArenaTile(int x, int y) {
|
|
|
|
char tile;
|
|
|
|
struct SpriteRender *target;
|
|
|
|
|
|
|
|
tile = arenaLayout[y][x];
|
|
|
|
|
|
|
|
switch (tile) {
|
|
|
|
case 0:
|
|
|
|
target = &arenaFloor;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
target = &arenaWallTop;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
target = &arenaWallSide;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
target->x = x * 20;
|
|
|
|
target->y = y * 20;
|
|
|
|
|
|
|
|
drawSprite(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
void buildArena() {
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (y = 0; y < 10; ++y) {
|
|
|
|
for (x = 0; x < 10; ++x) {
|
|
|
|
renderArenaTile(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-20 17:39:28 +00:00
|
|
|
#define RABBIT_MOTION_DRAG (2)
|
|
|
|
#define RABBIT_MOTION_ACCELERATION (5)
|
|
|
|
#define RABBIT_MOTION_MAX_SPEED (12)
|
|
|
|
|
2024-02-16 02:18:15 +00:00
|
|
|
int rabbitPosition[2] = { 60, 60 };
|
2024-02-20 13:20:35 +00:00
|
|
|
int oldRabbitPosition[2] = { 60, 60 };
|
2024-02-16 02:18:15 +00:00
|
|
|
int rabbitLimits[2][2] = {
|
|
|
|
{ 20, 20 },
|
|
|
|
{ 180, 180 }
|
|
|
|
};
|
|
|
|
|
|
|
|
signed char rabbitVelocity[2] = { 0, 0 };
|
|
|
|
|
2024-02-20 11:48:12 +00:00
|
|
|
struct MouseStatus mouseStatus;
|
|
|
|
char mousePosition[2] = { 0, 0 };
|
2024-02-20 13:20:35 +00:00
|
|
|
char oldMousePosition[2] = { 0, 0 };
|
2024-02-20 11:48:12 +00:00
|
|
|
|
2024-02-20 17:39:28 +00:00
|
|
|
char mouseDotPosition[2] = { 0, 0 };
|
|
|
|
char oldMouseDotPosition[2] = { 0, 0 };
|
2024-02-16 02:18:15 +00:00
|
|
|
|
2024-02-20 17:39:28 +00:00
|
|
|
void renderMouse() {
|
2024-02-20 11:48:12 +00:00
|
|
|
mouse.x = mousePosition[0];
|
|
|
|
mouse.y = mousePosition[1];
|
|
|
|
|
|
|
|
drawSprite(&mouse);
|
2024-02-20 17:39:28 +00:00
|
|
|
drawPixel(mouseDotPosition[0], mouseDotPosition[1], 2);
|
2024-02-20 11:48:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void renderRabbit() {
|
2024-02-20 17:39:28 +00:00
|
|
|
rabbit.x = rabbitPosition[0];
|
|
|
|
rabbit.y = rabbitPosition[1];
|
|
|
|
|
2024-02-16 02:18:15 +00:00
|
|
|
drawSprite(&rabbit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleRabbitMovement() {
|
|
|
|
int 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; ++i) {
|
2024-02-20 13:20:35 +00:00
|
|
|
oldRabbitPosition[i] = rabbitPosition[i];
|
2024-02-16 02:18:15 +00:00
|
|
|
rabbitPosition[i] += (rabbitVelocity[i] / 5);
|
|
|
|
|
|
|
|
if (rabbitPosition[i] < rabbitLimits[0][i]) {
|
|
|
|
rabbitPosition[i] = rabbitLimits[0][i];
|
|
|
|
}
|
|
|
|
if (rabbitPosition[i] >= rabbitLimits[1][i]) {
|
|
|
|
rabbitPosition[i] = rabbitLimits[1][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-20 13:00:13 +00:00
|
|
|
#define TILE_SIZE (20)
|
|
|
|
|
|
|
|
struct SpriteBounds bounds;
|
|
|
|
|
2024-02-20 13:20:35 +00:00
|
|
|
char tileRenderQueue[400];
|
|
|
|
|
2024-02-20 11:48:12 +00:00
|
|
|
void drawOnlyArena() {
|
|
|
|
int leftTileX, rightTileX,
|
|
|
|
topTileY, bottomTileY;
|
|
|
|
|
2024-02-20 13:00:13 +00:00
|
|
|
leftTileX = bounds.left / TILE_SIZE;
|
|
|
|
rightTileX = bounds.right / TILE_SIZE;
|
|
|
|
topTileY = bounds.top / TILE_SIZE;
|
|
|
|
bottomTileY = bounds.bottom / TILE_SIZE;
|
2024-02-20 11:48:12 +00:00
|
|
|
|
|
|
|
renderArenaTile(leftTileX, topTileY);
|
2024-02-20 13:20:35 +00:00
|
|
|
renderArenaTile(rightTileX, topTileY);
|
|
|
|
renderArenaTile(rightTileX, bottomTileY);
|
|
|
|
renderArenaTile(leftTileX, bottomTileY);
|
2024-02-16 02:18:15 +00:00
|
|
|
}
|
2024-02-15 01:15:55 +00:00
|
|
|
|
2024-02-20 11:48:12 +00:00
|
|
|
void drawOnlyMouseArena() {
|
2024-02-20 13:20:35 +00:00
|
|
|
mouse.x = oldMousePosition[0];
|
|
|
|
mouse.y = oldMousePosition[1];
|
2024-02-20 11:48:12 +00:00
|
|
|
getSpriteBounds(&mouse, &bounds);
|
|
|
|
drawOnlyArena();
|
2024-02-20 17:39:28 +00:00
|
|
|
|
|
|
|
bounds.top = oldMouseDotPosition[1];
|
|
|
|
bounds.bottom = oldMouseDotPosition[1];
|
|
|
|
bounds.left = oldMouseDotPosition[0];
|
|
|
|
bounds.right = oldMouseDotPosition[0];
|
|
|
|
drawOnlyArena();
|
2024-02-20 11:48:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void drawOnlyRabbitArena() {
|
2024-02-20 13:20:35 +00:00
|
|
|
rabbit.x = oldRabbitPosition[0];
|
|
|
|
rabbit.y = oldRabbitPosition[1];
|
2024-02-20 11:48:12 +00:00
|
|
|
getSpriteBounds(&rabbit, &bounds);
|
|
|
|
drawOnlyArena();
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RAD2DEG (180/3.14159)
|
|
|
|
#define DEG2RAD (3.14159/180)
|
|
|
|
#define MOUSE_DISTANCE (32)
|
|
|
|
|
2024-02-20 13:00:13 +00:00
|
|
|
void calculateTargetAngle() {
|
2024-02-20 11:48:12 +00:00
|
|
|
float distanceX, distanceY;
|
|
|
|
float angle;
|
|
|
|
|
2024-02-20 17:39:28 +00:00
|
|
|
oldMouseDotPosition[0] = mouseDotPosition[0];
|
|
|
|
oldMouseDotPosition[1] = mouseDotPosition[1];
|
|
|
|
|
|
|
|
mouseDotPosition[0] = mouseStatus.xPosition;
|
|
|
|
mouseDotPosition[1] = mouseStatus.yPosition;
|
|
|
|
|
2024-02-20 11:48:12 +00:00
|
|
|
distanceX = mouseStatus.xPosition - rabbitPosition[0];
|
|
|
|
distanceY = mouseStatus.yPosition - rabbitPosition[1];
|
|
|
|
|
2024-02-20 13:00:13 +00:00
|
|
|
angle = atan2(distanceY, distanceX) * 180 / 3.14159 + 90;
|
|
|
|
if (angle < 0) angle += 360;
|
2024-02-20 11:48:12 +00:00
|
|
|
|
2024-02-20 13:00:13 +00:00
|
|
|
distanceX = sin(angle * DEG2RAD) * MOUSE_DISTANCE;
|
|
|
|
distanceY = -cos(angle * DEG2RAD) * MOUSE_DISTANCE;
|
2024-02-20 11:48:12 +00:00
|
|
|
|
2024-02-20 13:20:35 +00:00
|
|
|
oldMousePosition[0] = mousePosition[0];
|
|
|
|
oldMousePosition[1] = mousePosition[1];
|
|
|
|
|
2024-02-20 11:48:12 +00:00
|
|
|
mousePosition[0] = rabbitPosition[0] + distanceX;
|
|
|
|
mousePosition[1] = rabbitPosition[1] + distanceY;
|
|
|
|
}
|
|
|
|
|
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-16 02:18:15 +00:00
|
|
|
setupWallSprites();
|
|
|
|
setupRabbitSprites();
|
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-20 17:39:28 +00:00
|
|
|
limitMouseArea(0, 0, 199, 199);
|
2024-02-20 11:48:12 +00:00
|
|
|
|
2024-02-16 02:18:15 +00:00
|
|
|
buildArena();
|
2024-02-15 13:34:50 +00:00
|
|
|
|
2024-02-16 02:18:15 +00:00
|
|
|
while (keepRunning) {
|
|
|
|
readMouse(&mouseStatus);
|
|
|
|
populateKeyboardKeydownState();
|
|
|
|
handleRabbitMovement();
|
2024-02-20 13:00:13 +00:00
|
|
|
calculateTargetAngle();
|
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-16 02:18:15 +00:00
|
|
|
renderRabbit();
|
2024-02-20 11:48:12 +00:00
|
|
|
renderMouse();
|
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
|
|
|
|
2024-02-15 01:15:55 +00:00
|
|
|
// 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
|
|
|
|
// *
|
2024-02-15 13:34:50 +00:00
|
|
|
//
|
2024-02-16 02:18:15 +00:00
|
|
|
|
|
|
|
freeBMP(&spritesheetImage);
|
|
|
|
|
|
|
|
setVideoMode(VIDEO_MODE_80x25_TEXT);
|
|
|
|
uninstallKeyboardHandler();
|
|
|
|
|
|
|
|
fprintf(stderr, "meow\n");
|
2024-02-15 13:34:50 +00:00
|
|
|
|
|
|
|
return 0;
|
2024-02-15 01:15:55 +00:00
|
|
|
}
|