2021-12-16 13:56:02 +01:00
|
|
|
#include "level.h"
|
2021-12-16 15:57:50 +01:00
|
|
|
#include "conf.h"
|
2021-12-17 23:07:06 +01:00
|
|
|
#include "player.h"
|
2021-12-18 11:02:33 +01:00
|
|
|
#include "polarity.h"
|
2021-12-17 00:20:39 +01:00
|
|
|
#include "tile.h"
|
2021-12-17 18:44:13 +01:00
|
|
|
#include "vec.h"
|
2021-12-16 15:57:50 +01:00
|
|
|
#include "visual_data.h"
|
|
|
|
#include <gint/display.h>
|
2021-12-16 13:56:02 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
static struct Level level;
|
2021-12-16 15:57:50 +01:00
|
|
|
extern bopti_image_t bimg_tileset;
|
2021-12-16 13:56:02 +01:00
|
|
|
|
2021-12-18 18:24:17 +01:00
|
|
|
extern struct LevelBin kble_test, kble_burn, kble_bounce, kble_worm, kble_shake,
|
2021-12-19 23:02:51 +01:00
|
|
|
kble_tilt, kble_cave, kble_headtrauma, kble_gimmick;
|
2021-12-18 12:47:35 +01:00
|
|
|
static const struct LevelBinNamed levels[] = {
|
2021-12-18 18:24:17 +01:00
|
|
|
{&kble_test, "gentle introduction"},
|
2021-12-19 18:13:43 +01:00
|
|
|
{&kble_cave, "the light at the end of the tunnel"},
|
2021-12-19 23:02:51 +01:00
|
|
|
{&kble_gimmick, "sell your gimmick"},
|
2021-12-19 18:13:43 +01:00
|
|
|
{&kble_headtrauma, "minefield"},
|
2021-12-18 18:24:17 +01:00
|
|
|
{&kble_burn, "these are rare"},
|
|
|
|
{&kble_bounce, "deceptive road"},
|
|
|
|
{&kble_shake, "breaking into reality"},
|
|
|
|
{&kble_tilt, "tilted"},
|
2021-12-19 17:53:43 +01:00
|
|
|
{&kble_worm, "under your skin"},
|
2021-12-18 18:24:17 +01:00
|
|
|
{NULL, NULL}};
|
2021-12-17 23:07:06 +01:00
|
|
|
|
2021-12-16 13:56:02 +01:00
|
|
|
static void level_free(void);
|
|
|
|
|
|
|
|
void
|
2021-12-17 23:07:06 +01:00
|
|
|
level_init(struct Player *p)
|
2021-12-16 13:56:02 +01:00
|
|
|
{
|
|
|
|
level.data = NULL;
|
2021-12-16 15:57:50 +01:00
|
|
|
level.visual_data = NULL;
|
2021-12-17 23:07:06 +01:00
|
|
|
level.player = p;
|
2021-12-16 13:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
level_deinit(void)
|
|
|
|
{
|
|
|
|
level_free();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-12-17 23:07:06 +01:00
|
|
|
level_load(int id)
|
2021-12-16 13:56:02 +01:00
|
|
|
{
|
2021-12-18 12:47:35 +01:00
|
|
|
const struct LevelBin *const b = levels[id].bin;
|
2021-12-16 13:56:02 +01:00
|
|
|
int i = b->width * b->height;
|
|
|
|
level_free();
|
|
|
|
level.width = b->width;
|
|
|
|
level.height = b->height;
|
|
|
|
level.size = i;
|
2021-12-17 23:07:06 +01:00
|
|
|
level.id = id;
|
2021-12-16 13:56:02 +01:00
|
|
|
level.data = malloc(i);
|
2021-12-16 15:57:50 +01:00
|
|
|
level.visual_data = malloc(i * sizeof(struct VisualData));
|
2021-12-16 13:56:02 +01:00
|
|
|
while (i-- > 0)
|
|
|
|
level.data[i] = b->data[i];
|
2021-12-18 15:50:05 +01:00
|
|
|
polarity_reset();
|
2021-12-19 00:30:09 +01:00
|
|
|
level_regen_visual_data(0);
|
2021-12-17 23:07:06 +01:00
|
|
|
player_spawn(level.player);
|
2021-12-16 13:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
level_reload(void)
|
|
|
|
{
|
2021-12-17 23:07:06 +01:00
|
|
|
level_load(level.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
level_next(void)
|
|
|
|
{
|
2021-12-18 12:47:35 +01:00
|
|
|
if (levels[level.id + 1].bin != NULL)
|
2021-12-17 23:07:06 +01:00
|
|
|
level_load(level.id + 1);
|
|
|
|
else
|
|
|
|
level_reload();
|
2021-12-16 13:56:02 +01:00
|
|
|
}
|
|
|
|
|
2021-12-16 15:57:50 +01:00
|
|
|
void
|
2021-12-19 00:30:09 +01:00
|
|
|
level_regen_visual_data(int editing)
|
2021-12-16 15:57:50 +01:00
|
|
|
{
|
|
|
|
const int tileset_width = bimg_tileset.width / TILE_SIZE;
|
|
|
|
int y = level.height;
|
|
|
|
while (y-- > 0) {
|
|
|
|
int x = level.width;
|
|
|
|
while (x-- > 0) {
|
|
|
|
const int i = x + y * level.width;
|
|
|
|
const int tile = level.data[i];
|
|
|
|
struct VisualData *const vd = &level.visual_data[i];
|
|
|
|
vd->x = x * TILE_SIZE;
|
|
|
|
vd->y = y * TILE_SIZE;
|
|
|
|
vd->img_x = tile % tileset_width * TILE_SIZE;
|
|
|
|
vd->img_y = (int)(tile / tileset_width) * TILE_SIZE;
|
|
|
|
vd->visible = tile != 0;
|
2021-12-19 00:30:09 +01:00
|
|
|
if (editing) continue;
|
2021-12-18 11:02:33 +01:00
|
|
|
switch (tile) {
|
|
|
|
case TILE_RED:
|
2021-12-19 18:13:43 +01:00
|
|
|
case TILE_BURN_RED:
|
2021-12-18 11:02:33 +01:00
|
|
|
vd->img_y += polarity() ? TILE_SIZE : 0;
|
|
|
|
break;
|
|
|
|
case TILE_BLUE:
|
2021-12-19 18:13:43 +01:00
|
|
|
case TILE_BURN_BLUE:
|
2021-12-18 11:02:33 +01:00
|
|
|
vd->img_y += polarity() ? 0 : TILE_SIZE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-12-16 15:57:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
level_draw(void)
|
|
|
|
{
|
|
|
|
int i = level.size;
|
|
|
|
while (i-- > 0) {
|
|
|
|
const struct VisualData *const vd = &level.visual_data[i];
|
|
|
|
if (vd->visible) {
|
2021-12-18 15:55:24 +01:00
|
|
|
dsubimage(vd->x + DRAW_OFF_X, vd->y, &bimg_tileset,
|
|
|
|
vd->img_x, vd->img_y, TILE_SIZE, TILE_SIZE,
|
|
|
|
0);
|
2021-12-16 15:57:50 +01:00
|
|
|
}
|
|
|
|
}
|
2021-12-19 00:30:09 +01:00
|
|
|
}
|
2021-12-18 12:47:35 +01:00
|
|
|
|
2021-12-19 00:30:09 +01:00
|
|
|
void
|
|
|
|
level_draw_name(void)
|
|
|
|
{
|
2021-12-19 15:32:13 +01:00
|
|
|
const int dx = DWIDTH - 4;
|
|
|
|
const int dy = DHEIGHT - 2;
|
|
|
|
int x = 2;
|
|
|
|
while (x-- > -1) {
|
|
|
|
int y = 2;
|
|
|
|
while (y-- > -1) {
|
|
|
|
dprint_opt(dx + x, dy + y, C_WHITE, C_NONE, DTEXT_RIGHT,
|
|
|
|
DTEXT_BOTTOM, "%s", levels[level.id].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dprint_opt(dx, dy, C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_BOTTOM, "%s",
|
|
|
|
levels[level.id].name);
|
2021-12-16 15:57:50 +01:00
|
|
|
}
|
|
|
|
|
2021-12-16 23:27:04 +01:00
|
|
|
int
|
|
|
|
level_get(int x, int y)
|
|
|
|
{
|
|
|
|
if (x < 0 || y < 0 || x >= level.width || y >= level.height)
|
|
|
|
return TILE_OOB;
|
|
|
|
return level.data[x + y * level.width];
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
level_get_px(int x, int y)
|
|
|
|
{
|
|
|
|
return level_get(x / TILE_SIZE, y / TILE_SIZE);
|
|
|
|
}
|
|
|
|
|
2021-12-19 00:30:09 +01:00
|
|
|
void
|
|
|
|
level_set(int x, int y, int v)
|
|
|
|
{
|
|
|
|
if (x < 0 || y < 0 || x >= level.width || y >= level.height) return;
|
|
|
|
level.data[x + y * level.width] = v;
|
|
|
|
}
|
|
|
|
|
2021-12-17 18:44:13 +01:00
|
|
|
struct Vec
|
|
|
|
level_find(enum Tile t)
|
|
|
|
{
|
|
|
|
int i = level.size;
|
|
|
|
while (i-- > 0 && level.data[i] != t)
|
|
|
|
;
|
|
|
|
return (struct Vec){i % level.width, i / level.width};
|
|
|
|
}
|
|
|
|
|
2021-12-19 00:30:09 +01:00
|
|
|
struct Vec
|
|
|
|
level_dim(void)
|
|
|
|
{
|
|
|
|
return (struct Vec){level.width, level.height};
|
|
|
|
}
|
|
|
|
|
2021-12-16 13:56:02 +01:00
|
|
|
static void
|
|
|
|
level_free(void)
|
|
|
|
{
|
|
|
|
if (level.data != NULL) {
|
|
|
|
free(level.data);
|
|
|
|
level.data = NULL;
|
|
|
|
}
|
2021-12-16 15:57:50 +01:00
|
|
|
if (level.visual_data != NULL) {
|
|
|
|
free(level.visual_data);
|
|
|
|
level.visual_data = NULL;
|
|
|
|
}
|
2021-12-16 13:56:02 +01:00
|
|
|
}
|