RDP version
This commit is contained in:
parent
c192ae6e1f
commit
cc3c155b64
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
238
src/game.c
238
src/game.c
|
@ -2,6 +2,7 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/timer.h>
|
||||
#include <gint/std/stdio.h>
|
||||
#include <gint/std/stdlib.h>
|
||||
|
||||
/* State definition, as used throughout the main game.
|
||||
|
@ -17,6 +18,8 @@
|
|||
* of the path where is at, `substep` is the substep from 0 to 7, looping
|
||||
* when 8 (augmenting step, except when at the castle).
|
||||
* - nfwait: number of frames to be waited.
|
||||
* - lfbase, lf: life base (e.g. lfbase = 10 and lf = 5 for 5/10 as life).
|
||||
* - bonus: bonus when killed by a turret.
|
||||
* - pdr: the enemy that spawned previously or is the next further on the
|
||||
* path. Simple chain list that could evolve later if some enemies are
|
||||
* slowed down or have various speeds, allowing some enemies to overtake
|
||||
|
@ -28,6 +31,8 @@ struct enemy {
|
|||
int alive;
|
||||
|
||||
int nstepf;
|
||||
int lfbase, lf;
|
||||
int bonus;
|
||||
|
||||
int x, y;
|
||||
int step, substep;
|
||||
|
@ -38,14 +43,24 @@ struct enemy {
|
|||
|
||||
/* For each turret, the data is:
|
||||
*
|
||||
* - x, y: the coordinates of the turret. */
|
||||
* - type, amongst:
|
||||
* 0x01: basic turret.
|
||||
* 0x02: boom turret.
|
||||
* - x, y: the coordinates of the turret.
|
||||
* - rlbase, rl: reload base and current.
|
||||
* - radius: radius of action, in blocks.
|
||||
* - dmg: damage done to enemies either targetted or nearby. */
|
||||
|
||||
#define NTURRETS 256
|
||||
|
||||
struct turret {
|
||||
int exists;
|
||||
|
||||
int type;
|
||||
int x, y;
|
||||
int rlbase, rl;
|
||||
int radius;
|
||||
int dmg;
|
||||
};
|
||||
|
||||
/* And the main state definition. */
|
||||
|
@ -68,11 +83,12 @@ struct state {
|
|||
* - tbsp: time between enemy spawns.
|
||||
* - tnsp: time to next spawn (as a number of ticks).
|
||||
* - nae: number of currently alive enemies.
|
||||
* - nvc: number of victims.
|
||||
* - first_enemy: pointer to the last enemy to have spawned,
|
||||
* to draw first */
|
||||
|
||||
int tbsp, tnsp;
|
||||
int nae;
|
||||
int nae, nvc;
|
||||
struct enemy *first_enemy;
|
||||
struct enemy *enemies;
|
||||
|
||||
|
@ -84,6 +100,14 @@ struct state {
|
|||
int net;
|
||||
struct turret *turrets;
|
||||
|
||||
/* Player information.
|
||||
*
|
||||
* - lf: number of lifes left.
|
||||
* - money: the money left. */
|
||||
|
||||
int lf;
|
||||
int money;
|
||||
|
||||
/* Camera, cursor and display information:
|
||||
*
|
||||
* - cur_x, cur_y: map coordinate for the cursor.
|
||||
|
@ -131,6 +155,7 @@ static void init(uint8_t const *raw)
|
|||
state.tbsp = 99;
|
||||
state.tnsp = state.tbsp;
|
||||
state.nae = 0;
|
||||
state.nvc = 0;
|
||||
state.first_enemy = NULL;
|
||||
|
||||
state.enemies = malloc(NENEMIES * sizeof (struct enemy));
|
||||
|
@ -147,6 +172,11 @@ static void init(uint8_t const *raw)
|
|||
for (i = 0; i < NTURRETS; i++)
|
||||
state.turrets[i].exists = 0;
|
||||
|
||||
/* Initialize player information */
|
||||
|
||||
state.lf = 10;
|
||||
state.money = 100;
|
||||
|
||||
/* Initialize display information */
|
||||
|
||||
state.cur_x = raw[4];
|
||||
|
@ -161,7 +191,7 @@ static void deinit()
|
|||
|
||||
/* place_turret(): place a turret at the cursor position. */
|
||||
|
||||
static void place_turret()
|
||||
static void place_turret(int type)
|
||||
{
|
||||
int i;
|
||||
struct turret *tp, *ntp = NULL;
|
||||
|
@ -186,13 +216,56 @@ static void place_turret()
|
|||
return ;
|
||||
}
|
||||
|
||||
/* The slot is free, let's go */
|
||||
|
||||
if (!ntp)
|
||||
return ;
|
||||
|
||||
/* The slot is free, check that we have the money, deduce
|
||||
* it and let's go */
|
||||
|
||||
{
|
||||
int price;
|
||||
|
||||
if (type == 1)
|
||||
price = 100;
|
||||
else
|
||||
price = 200;
|
||||
if (state.money < price)
|
||||
return ;
|
||||
state.money -= price;
|
||||
}
|
||||
|
||||
ntp->exists = 1;
|
||||
ntp->type = type;
|
||||
ntp->x = state.cur_x;
|
||||
ntp->y = state.cur_y;
|
||||
ntp->rlbase = type == 1 ? 50 : 90;
|
||||
ntp->rl = ntp->rlbase;
|
||||
ntp->radius = 2;
|
||||
ntp->dmg = type == 1 ? 5 : 3;
|
||||
}
|
||||
|
||||
/* kill(enemy): kill an enemy. */
|
||||
|
||||
static void kill(struct enemy *ep, int bonus)
|
||||
{
|
||||
ep->alive = 0;
|
||||
if (ep->ndrp)
|
||||
(*ep->ndrp) = ep->pdr;
|
||||
|
||||
state.nae--;
|
||||
state.nvc++;
|
||||
|
||||
if (bonus)
|
||||
state.money += ep->bonus;
|
||||
}
|
||||
|
||||
/* damage_on(enemy, amount): make damage on enemies. */
|
||||
|
||||
static void damage_on(struct enemy *ep, int amount)
|
||||
{
|
||||
ep->lf -= amount;
|
||||
if (ep->lf <= 0)
|
||||
kill(ep, 1);
|
||||
}
|
||||
|
||||
/* tick(): tick the game engine. */
|
||||
|
@ -227,13 +300,9 @@ static void tick()
|
|||
ep->substep = 0;
|
||||
|
||||
if (ep->step == state.nep) {
|
||||
ep->alive = 0;
|
||||
if (ep->ndrp)
|
||||
(*ep->ndrp) = ep->pdr;
|
||||
|
||||
state.nae--;
|
||||
|
||||
/* TODO: remove one life to the castle */
|
||||
kill(ep, 0);
|
||||
if (state.lf >= 0)
|
||||
state.lf--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,9 +333,86 @@ static void tick()
|
|||
ep->nstepf = 5;
|
||||
ep->nfwait = ep->nstepf;
|
||||
|
||||
ep->lfbase = 10;
|
||||
ep->lf = ep->lfbase;
|
||||
ep->bonus = 5;
|
||||
|
||||
state.nae++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the turrets. */
|
||||
|
||||
for (i = 0; i < NTURRETS; i++) {
|
||||
struct turret *tp = &state.turrets[i];
|
||||
|
||||
if (!tp->exists)
|
||||
continue ;
|
||||
if (tp->rl > 0) {
|
||||
tp->rl--;
|
||||
continue ;
|
||||
}
|
||||
|
||||
/* Now: we check if there's an enemy in the radius,
|
||||
* starting from the earliest spawned.
|
||||
* If that's the case:
|
||||
* - if turret type is 1, we damage the targetted enemy.
|
||||
* - if turret type is 2, we damage every enemy within the
|
||||
* radius.
|
||||
*
|
||||
* The distance is calculated using the centers. */
|
||||
|
||||
if (tp->type == 1) {
|
||||
struct enemy *target = NULL;
|
||||
int tx = (tp->x << 3) + 4, ty = (tp->y << 3) + 4;
|
||||
int trs = (tp->radius << 3) * (tp->radius << 3);
|
||||
|
||||
for (struct enemy *ep = state.first_enemy; ep; ep = ep->pdr) {
|
||||
int cx = ep->x + 4, cy = ep->y + 4;
|
||||
int dxs = cx - tx, dys = cy - ty;
|
||||
|
||||
dxs *= dxs;
|
||||
dys *= dys;
|
||||
|
||||
if (dxs + dys <= trs)
|
||||
target = ep;
|
||||
}
|
||||
|
||||
if (target) {
|
||||
damage_on(target, tp->dmg);
|
||||
tp->rl = tp->rlbase;
|
||||
}
|
||||
} else if (tp->type == 2) {
|
||||
int tx = (tp->x << 3) + 4, ty = (tp->y << 3) + 4;
|
||||
int trs = (tp->radius << 3) * (tp->radius << 3);
|
||||
|
||||
for (struct enemy *ep = state.first_enemy; ep; ep = ep->pdr) {
|
||||
int cx = ep->x + 4, cy = ep->y + 4;
|
||||
int dxs = cx - tx, dys = cy - ty;
|
||||
|
||||
dxs *= dxs;
|
||||
dys *= dys;
|
||||
|
||||
if (dxs + dys <= trs) {
|
||||
damage_on(ep, tp->dmg);
|
||||
tp->rl = tp->rlbase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* dnumber(): draw a number on three digits at given position. */
|
||||
|
||||
static void dnumber(int x, int y, int number)
|
||||
{
|
||||
extern bopti_image_t img_numbers;
|
||||
char buf[4];
|
||||
|
||||
snprintf(buf, 4, "%03d", number < 0 ? 0 : number > 999 ? 999 : number);
|
||||
drect(x, y, x + 11, y + 3, C_WHITE);
|
||||
for (int i = 0; i < 3; i++)
|
||||
dsubimage(x + i * 4, y, &img_numbers, (buf[i] - '0') * 4, 0, 3, 4, 0);
|
||||
}
|
||||
|
||||
/* draw(): basically the drawing function for everything. */
|
||||
|
@ -291,7 +437,7 @@ static void draw()
|
|||
|
||||
/* Draw the grid. */
|
||||
|
||||
for (y = 0; y < 8; y++) {
|
||||
for (y = 0; y < 6; y++) {
|
||||
for (x = 0; x < 16; x++) {
|
||||
int ox = x << 3, oy = y << 3;
|
||||
int tile = tile_cam(x, y);
|
||||
|
@ -327,28 +473,47 @@ static void draw()
|
|||
}
|
||||
}
|
||||
|
||||
/* Draw the turrets. */
|
||||
|
||||
{
|
||||
struct turret *tp;
|
||||
extern bopti_image_t img_basic_turret;
|
||||
extern bopti_image_t img_zone_turret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NTURRETS; i++) {
|
||||
bopti_image_t *tip;
|
||||
|
||||
tp = &state.turrets[i];
|
||||
if (tp->type == 1)
|
||||
tip = &img_basic_turret;
|
||||
else
|
||||
tip = &img_zone_turret;
|
||||
|
||||
if (tp->exists)
|
||||
dimage(x_cam(tp->x << 3), y_cam(tp->y << 3), tip);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw the enemies. */
|
||||
|
||||
{
|
||||
struct enemy *ep;
|
||||
extern bopti_image_t img_enemy;
|
||||
|
||||
for (ep = state.first_enemy; ep; ep = ep->pdr)
|
||||
dimage(x_cam(ep->x), y_cam(ep->y), &img_enemy);
|
||||
}
|
||||
for (ep = state.first_enemy; ep; ep = ep->pdr) {
|
||||
int ox = x_cam(ep->x), oy = y_cam(ep->y);
|
||||
|
||||
/* Draw the turrets. */
|
||||
dimage(ox, oy, &img_enemy);
|
||||
if (ep->lf < ep->lfbase) {
|
||||
int lfwidth, spacing = 7;
|
||||
|
||||
{
|
||||
struct turret *tp;
|
||||
extern bopti_image_t img_basic_turret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NTURRETS; i++) {
|
||||
tp = &state.turrets[i];
|
||||
|
||||
if (tp->exists)
|
||||
dimage(x_cam(tp->x << 3), y_cam(tp->y << 3), &img_basic_turret);
|
||||
drect_border(ox, oy + spacing, ox + 8, oy + spacing + 2,
|
||||
C_WHITE, 1, C_BLACK);
|
||||
lfwidth = ep->lf * 6 / ep->lfbase;
|
||||
drect(ox + 1, oy + spacing + 1, ox + 1 + lfwidth,
|
||||
oy + spacing + 1, C_BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,6 +534,19 @@ static void draw()
|
|||
dline(ox + 7, oy + d + 4, ox + 7, oy + d + 5, C_BLACK);
|
||||
}
|
||||
|
||||
/* Draw the menu */
|
||||
|
||||
{
|
||||
extern bopti_image_t img_menu_bar;
|
||||
|
||||
dimage(0, 48, &img_menu_bar);
|
||||
dnumber(94, 50, state.lf);
|
||||
dnumber(94, 55, state.money);
|
||||
dnumber(94, 60, 1); /* TODO: round number */
|
||||
dnumber(113, 50, state.net);
|
||||
dnumber(113, 55, state.nvc);
|
||||
}
|
||||
|
||||
/* okay we can update now */
|
||||
|
||||
dupdate();
|
||||
|
@ -456,9 +634,11 @@ menu_t *game(menu_t *last_menu)
|
|||
if (state.cur_x < state.w - 1)
|
||||
state.cur_x++;
|
||||
break;
|
||||
case KEY_XOT:
|
||||
place_turret();
|
||||
case KEY_F1:
|
||||
place_turret(1);
|
||||
break;
|
||||
case KEY_F2:
|
||||
place_turret(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Reference in New Issue