From 12db355f64b6363867bcfabf2e1a287b294c7452 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 30 Apr 2023 03:00:50 +0200 Subject: [PATCH] final level --- CMakeLists.txt | 7 +++++-- assets/3_1.txt | 28 ++++++++++++++++++++++++++++ assets/3_2.txt | 23 +++++++++++++++++++++++ assets/3_3.txt | 44 ++++++++++++++++++++++++++++++++++++++++++++ converters.py | 24 ++++++++++++++++++++++-- src/chaos-drop.h | 11 +++++++++++ src/game.cc | 14 ++++++++++++++ src/main.cc | 18 +++++++++++++++--- src/raytracing.cc | 3 ++- 9 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 assets/3_1.txt create mode 100644 assets/3_2.txt create mode 100644 assets/3_3.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index d3347ae..0ab5617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/assets/3_1.txt b/assets/3_1.txt new file mode 100644 index 0000000..1dd139f --- /dev/null +++ b/assets/3_1.txt @@ -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 "" diff --git a/assets/3_2.txt b/assets/3_2.txt new file mode 100644 index 0000000..49158f2 --- /dev/null +++ b/assets/3_2.txt @@ -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 diff --git a/assets/3_3.txt b/assets/3_3.txt new file mode 100644 index 0000000..3c882f7 --- /dev/null +++ b/assets/3_3.txt @@ -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 diff --git a/converters.py b/converters.py index 3d08da8..d9341d3 100644 --- a/converters.py +++ b/converters.py @@ -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", "")) 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 diff --git a/src/chaos-drop.h b/src/chaos-drop.h index 33eb5d9..3615f4c 100644 --- a/src/chaos-drop.h +++ b/src/chaos-drop.h @@ -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]; diff --git a/src/game.cc b/src/game.cc index 4cc6211..8845a9e 100644 --- a/src/game.cc +++ b/src/game.cc @@ -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++]; + } } diff --git a/src/main.cc b/src/main.cc index 375528c..b8affa7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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); } diff --git a/src/raytracing.cc b/src/raytracing.cc index 3df2431..3ecd39b 100644 --- a/src/raytracing.cc +++ b/src/raytracing.cc @@ -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 {