final level

This commit is contained in:
Lephenixnoir 2023-04-30 03:00:50 +02:00
parent 5d6fca1607
commit 12db355f64
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
9 changed files with 164 additions and 8 deletions

View File

@ -27,7 +27,10 @@ if(AZUR_PLATFORM STREQUAL gint)
assets/1_3.txt
assets/2_1.txt
assets/2_2.txt
assets/2_3.txt)
assets/2_3.txt
assets/3_1.txt
assets/3_2.txt
assets/3_3.txt)
endif()
if(AZUR_PLATFORM STREQUAL linux)
@ -60,7 +63,7 @@ if(AZUR_PLATFORM STREQUAL gint)
include(GenerateG3A)
generate_g3a(TARGET chaos-drop
NAME "Chaos Drop"
NAME "Chaos Drop!"
OUTPUT "ChaosDrop.g3a"
ICONS assets/icon-uns.png assets/icon-sel.png)
endif()

28
assets/3_1.txt Normal file
View File

@ -0,0 +1,28 @@
name: 3-1
1/ 3 text "Time to invoke some\nCHAOS!"
3/ plane DAMAGE 0b11100'11100'11111'11111'11111
3/ plane ARROW ARROW_+Z
3/ plane DAMAGE HLINES_2_4
3/ plane DAMAGE 0b11111'11111'11111'00111'00111
@ 1/ 30 mirror
2/ plane ARROW ARROW_-X
2/ plane DAMAGE BOX_DOT
2/ plane ARROW ARROW_+X
2/ plane INVIS BIGDOT
2/ plane ARROW ARROW_-Z
2/ plane DAMAGE 0b10001'11111'11111'11111'11111
2/ plane DAMAGE 0b11111'01111'01111'01111'11111
4/ 3 text "Good, shall we raise\nthe intensity?"
@ 1/ 9 vfx invert
2/ plane ARROW ARROW_+X
2/ plane DAMAGE HASH
2/ plane DAMAGE BOX_DOT
2/ plane ARROW ARROW_-Z
3/ 1 text ""

23
assets/3_2.txt Normal file
View File

@ -0,0 +1,23 @@
name: 3-2
@ 1/ 30 mirror
1/ 3 text "Ahaha, more! More!\nSummon the DIVINE!"
2/ plane DAMAGE HASH
2/ plane INVIS HLINES_2_4
2/ plane ARROW ARROW_+X
2/ plane DAMAGE HLINES_1_3_5
2/ plane INVIS BOX
2/ plane INVIS HASH
2/ plane ARROW ARROW_-X
1/ plane ARROW ARROW_-Z
4/ 3 text "Fall, fall! Into disarray!"
2/ plane DAMAGE BOX
1/ plane DAMAGE BIGDOT
1/ plane DAMAGE BOX
1/ plane DAMAGE BIGDOT
2/ plane ARROW ARROW_+Z
2/ plane INVIS BOX

44
assets/3_3.txt Normal file
View File

@ -0,0 +1,44 @@
name: 3-3
@ 1/ 99 mirror
1/ 3 text "Damn boy, why keep it up?!"
2/ plane DAMAGE 0b10001'11111'11111'11111'11111
2/ plane ARROW ARROW_+X
2/ plane DAMAGE 0b00111'11111'11111'11111'11111
2/ plane ARROW ARROW_-Z
2/ plane ARROW ARROW_-X
2/ plane DAMAGE BOX_DOT
2/ plane ARROW ARROW_+X
2/ plane ARROW ARROW_-Z
2/ plane DAMAGE BIGDOT
4/ 3 text "Come on! Do it!\nLose to the ANARCHY!"
2/ plane INVIS HASH
2/ plane INVIS VLINES_1_5
2/ plane ARROW ARROW_-X
2/ plane INVIS VLINES_2_4
2/ plane ARROW ARROW_+Z
2/ plane INVIS BIGDOT
1/ plane INVIS BOX
1/ plane INVIS BIGDOT
5/ 3 text "Grrr, then I'll just\nkill you like the others!"
@ 99 vfx invert
2/ plane DAMAGE VLINES_1_3_5
2/ plane ARROW ARROW_+X
2/ plane DAMAGE HLINES_2_4
2/ plane DAMAGE VLINES_2_4
2/ plane ARROW ARROW_-Z
2/ plane DAMAGE VLINES_1_3_5
4/ 3 text "CURSE YOU!"
2/ plane DAMAGE BOX
1/ plane DAMAGE BOX
1/ plane DAMAGE BOX
1/ plane DAMAGE BOX
1/ plane DEATH FULL

View File

@ -43,7 +43,8 @@ def convert_level(input, params):
RE_ELEMENTS = {
"mirror": (True, re.compile(r'')),
"plane": (False, re.compile(r'(\S+)\s+(\S+)')),
"text": (True, re.compile(r'\"([^"]+)\"')),
"text": (True, re.compile(r'\"([^"]*)\"')),
"vfx": (True, re.compile(r'([a-z]+)')),
}
RE_POSITION = re.compile(r'^\s*(@)?\s*(?:(\d+)/)?\s*(\d+)?')
@ -89,15 +90,17 @@ def convert_level(input, params):
raise fxconv.FxconvError(f"'{elname}' needs no size")
m = RE_ELEMENTS[elname][1].fullmatch(data)
if not m:
raise fxconv.FxconvError(f"bad data for '{elname}': '{data}")
raise fxconv.FxconvError(f"bad data for '{elname}': '{data}'")
elements.append((elname, start, end, m))
mirrors = fxconv.ObjectData()
planes = fxconv.ObjectData()
texts = fxconv.ObjectData()
vfxs = fxconv.ObjectData()
mirror_count = 0
plane_count = 0
text_count = 0
vfx_count = 0
for (key, start, end, m) in elements:
if key == "mirror":
@ -129,6 +132,7 @@ def convert_level(input, params):
"ARROW_-X": 0b0010001000111110100000100,
"ARROW_+Z": 0b0010001110101010010000100,
"ARROW_-Z": 0b0010000100101010111000100,
"FULL": 0b1111111111111111111111111,
}
if shape_str in predef_shapes:
shape = predef_shapes[shape_str]
@ -142,6 +146,7 @@ def convert_level(input, params):
"DAMAGE": 0,
"ARROW": 1,
"INVIS": 2,
"DEATH": 3,
}
assert kind in kinds
@ -164,6 +169,19 @@ def convert_level(input, params):
texts += fxconv.string(string)
text_count += 1
elif key == "vfx":
effects = {
"darken": 0,
"whiten": 1,
"invert": 2,
}
if m[1] not in effects:
raise fxconv.FxconvError(f"invalid vfx '{m[1]}'")
vfxs += num(start * DISTANCE_FACTOR)
vfxs += num(end * DISTANCE_FACTOR)
vfxs += fxconv.u32(effects[m[1]])
vfx_count += 1
o = fxconv.ObjectData()
o += fxconv.string(header.get("name", "<Untitled>"))
o += num(int(header.get("finish", pos+2)) * DISTANCE_FACTOR)
@ -173,4 +191,6 @@ def convert_level(input, params):
o += fxconv.ptr(planes)
o += fxconv.u32(text_count)
o += fxconv.ptr(texts)
o += fxconv.u32(vfx_count)
o += fxconv.ptr(vfxs)
return o

View File

@ -90,6 +90,7 @@ enum element_plane_type {
ELEMENT_PLANE_DAMAGE,
ELEMENT_PLANE_ARROW,
ELEMENT_PLANE_INVIS,
ELEMENT_PLANE_DEATH,
};
struct element_plane {
num y;
@ -103,6 +104,11 @@ struct element_text {
num begin, end;
char const *str;
};
/* Additional full-screen visual effect. */
struct element_vfx {
num begin, end;
int effect;
};
struct level {
/* Level name (usually just two digits) */
@ -122,6 +128,9 @@ struct level {
int text_count;
struct element_text *texts;
int vfx_count;
struct element_vfx *vfxs;
};
/* Total number of levels. */
@ -151,10 +160,12 @@ struct game {
int mirror_index;
int plane_index;
int text_index;
int vfx_index;
/* Corresponding elements (these are the only active elements) */
struct element_mirror *mirror;
struct element_plane *plane;
struct element_text *text;
struct element_vfx *vfx;
/* A dynamic plane y value; mostly redundant from plane->y, used to optimize
away some checks during collisions with the plane */
num plane_collision[2];

View File

@ -6,9 +6,11 @@
extern struct level level_1_1, level_1_2, level_1_3;
extern struct level level_2_1, level_2_2, level_2_3;
extern struct level level_3_1, level_3_2, level_3_3;
static struct level const *ALL_LEVELS[] = {
&level_1_1, &level_1_2, &level_1_3,
&level_2_1, &level_2_2, &level_2_3,
&level_3_1, &level_3_2, &level_3_3,
};
#else
/* TODO: PC/SDL build: Embed levels as in the add-in */
@ -178,10 +180,14 @@ static void game_reset_level_data(struct game *g)
g->mirror_index = 0;
g->plane_index = 0;
g->text_index = 0;
g->vfx_index = 0;
g->mirror = NULL;
g->plane = NULL;
g->text = NULL;
g->vfx = NULL;
g->depth = 0;
g->plane_collision[0] = num(0x7ff);
g->plane_collision[1] = num(0x7ff);
}
void game_load_menu(struct game *g)
@ -242,6 +248,8 @@ void game_advance_in_level(struct game *g)
g->plane = NULL;
if(g->text && g->depth > g->text->end)
g->text = NULL;
if(g->vfx && g->depth > g->vfx->end)
g->vfx = NULL;
/* Load incoming elements */
@ -253,8 +261,14 @@ void game_advance_in_level(struct game *g)
&& level->planes[g->plane_index].y < g->depth + num(64)) {
g->plane = &level->planes[g->plane_index++];
}
// FIXME: Should've loaded just in time, not 64 in advance...
// (but now all levels are calibrated for that)
if(!g->text && g->text_index < level->text_count
&& level->texts[g->text_index].begin < g->depth + num(64)) {
g->text = &level->texts[g->text_index++];
}
if(!g->vfx && g->vfx_index < level->vfx_count
&& level->vfxs[g->vfx_index].begin < g->depth) {
g->vfx = &level->vfxs[g->vfx_index++];
}
}

View File

@ -299,7 +299,7 @@ void game_render(struct game *g)
cd_raytrace(g);
azrp_image((azrp_width - img_title.width) / 2, 4, &img_title);
for(int row = 0; row < 2; row++)
for(int row = 0; row < 3; row++)
for(int col = 0; col < 3; col++) {
int i = 3 * row + col;
if(i >= level_count())
@ -324,6 +324,9 @@ void game_render(struct game *g)
if(g->text)
render_centered_text(g->text->str);
draw_text(1, 1, level->name, strlen(level->name));
if(g->vfx)
cd_vfx(g->vfx->effect);
}
#else
if(g->blank_frames > 0) {
@ -434,6 +437,7 @@ int game_update(struct game *g, bool *debug)
camera_update_angles(camera);
}
camera->pos.y = 0;
g->depth += fall_speed;
g->neon_position += g->neon_period - num16(fall_speed);
g->neon_position %= g->neon_period;
@ -451,14 +455,22 @@ int game_update(struct game *g, bool *debug)
game_restart_level(g, 2);
}
else if(p->type == ELEMENT_PLANE_ARROW && camera->roll_quadrant != p->data)
{
game_restart_level(g, 2);
}
else if(p->type == ELEMENT_PLANE_DEATH)
{
game_next_level_or_menu(g);
g->blank_frames = 2;
return 0;
}
// Load incoming level elements
game_advance_in_level(g);
if(!g->mirror && !g->plane && !g->text && g->depth >= g->level->finish
&& !g->blank_frames) {
if(!g->mirror && !g->plane && !g->text && !g->vfx
&& g->depth >= g->level->finish && !g->blank_frames) {
game_next_level_or_menu(g);
}

View File

@ -9,11 +9,12 @@ static uint16_t const object_colors[] = {
RGB(3, 4, 5), /* Void/background */
RGB(3, 4, 5), /* Left wall (-X) */
RGB(5, 6, 7), /* Top wall (+Z) */
RGB(7, 8, 9), /* Right wall (+X) */
RGB(7, 8, 9), /* Right wall (+X) */
RGB(5, 6, 7), /* Bottom wall (-Z) */
RGB(31, 0, 0), /* ELEMENT_PLANE_DAMAGE */
RGB(0, 31, 0), /* ELEMENT_PLANE_ARROW */
RGB(15, 0, 0), /* ELEMENT_PLANE_INVIS */
RGB(31, 31, 31), /* ELEMENT_PLANE_DEATH */
};
/* Objects hit by a ray */
enum {