diff --git a/CMakeLists.txt b/CMakeLists.txt index 4826895..d3347ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,11 @@ set(ASSETS) if(AZUR_PLATFORM STREQUAL gint) list(APPEND SOURCES + src/backend/gint/shader_vfx.cc src/backend/gint/shader.cc) list(APPEND ASSETS assets/font.png + assets/cursor0.png assets/cursor.png assets/title.png assets/1_1.txt diff --git a/assets/1_1.txt b/assets/1_1.txt index 8e82638..d2f245a 100644 --- a/assets/1_1.txt +++ b/assets/1_1.txt @@ -1,21 +1,20 @@ name: 1-1 -finish: 67 -1-3: text "Welcome to the drop!\n" -4-8: text "I know you have\nmany questions.\n\nDon't ask them. We're busy." -9-13: text "Use the arrow keys to move." +1/ 3 text "Welcome to the drop!\n" +1/ 5 text "I know you have\nmany questions.\n\nDon't ask them. We're busy." +1/ 4 text "Use the arrow keys to move." -20-24: text "Red bad.\nDon't touch the red stuff." -26: plane DAMAGE VLINES_1_5 -30: plane DAMAGE BOX -34: plane DAMAGE 0b11100'11100'11100'00000'00000 -38: plane DAMAGE 0b11100'11000'10001'00011'00111 +9/ 5 text "Red bad.\nDon't touch the red stuff." +3/ plane DAMAGE VLINES_1_5 +3/ plane DAMAGE BIGDOT +3/ plane DAMAGE BOX +3/ plane DAMAGE 0b11111'10101'10101'10101'11111 -42-44: text "Be careful!" -46: plane DAMAGE 0b11100'11100'11100'11100'11100 -48: plane DAMAGE 0b00000'00000'11111'11111'11111 -50: plane DAMAGE 0b00111'00111'00111'00111'00111 -52: plane DAMAGE 0b11111'11111'11111'00000'00000 +4/ 2 text "Be careful!" +3/ plane DAMAGE 0b11111'10011'10101'11001'11111 +3/ plane DAMAGE HASH +3/ plane DAMAGE CORNERS +3/ plane DAMAGE BOX_DOT -56-62: text "Nice job.\n\nDon't worry, I'll teach you\nhow to deal with the drop\nfrom the ground up." -63-65: text "Get it? The ground. Haha." +4/ 6 text "Nice job.\n\nDon't worry, I'll teach you\nhow to deal with the drop\nfrom the ground up." +1/ 3 text "Get it? The ground. Haha." diff --git a/assets/1_2.txt b/assets/1_2.txt index 2be9d9a..70a92e1 100644 --- a/assets/1_2.txt +++ b/assets/1_2.txt @@ -1,26 +1,21 @@ name: 1-2 -finish: 53 -1-5: text "Press F1 or F2 to roll." +1/ 5 text "Press F1 or F2 to roll." +3/ plane DAMAGE 0b01110'11111'11111'10001'01010 +3/ plane DAMAGE BOX +3/ plane DAMAGE 0b01010'10001'11111'11111'01110 +3/ plane DAMAGE BIGDOT -7: plane DAMAGE 0b01110'11111'11011'10001'00000 -10: plane DAMAGE 0b01110'00111'00011'00111'01110 -13: plane DAMAGE 0b00000'10001'11011'11111'01110 -16: plane DAMAGE 0b01110'11100'11000'11100'01110 +5/ 4 text "If you roll while close\nto an edge, you will\nmove along the wall." +3/ plane DAMAGE 0b10001'11111'11111'11111'11111 +3/ plane DAMAGE 0b11111'01111'01111'01111'11111 +3/ plane DAMAGE 0b11111'11110'11110'11110'11111 -18-21: text "If you roll while close\nto an edge, you will\nmove along the wall." +5/ 4 text "Green good.\nRoll to make the arrow point down." +3/ plane ARROW ARROW_+X +3/ plane ARROW ARROW_-X +3/ plane DAMAGE BOX +2/ plane ARROW ARROW_+Z +2/ plane ARROW ARROW_-Z -24: plane DAMAGE 0b10001'11111'11111'11111'11111 -26: plane DAMAGE 0b11111'01111'01111'01111'11111 -28: plane DAMAGE 0b11111'11111'11111'11111'10001 -30: plane DAMAGE 0b11111'11110'11110'11110'11111 - -34-38: text "Green good.\nRoll to make the arrow point down." - -40: plane ARROW ARROW_+X -42: plane ARROW ARROW_-X -44: plane DAMAGE BOX -45: plane ARROW ARROW_+Z -46: plane ARROW ARROW_-Z - -48-51: text "Impressive! You're taking off!" +4/ 3 text "Impressive! You're taking off!" diff --git a/assets/1_3.txt b/assets/1_3.txt index 0c613aa..3edd4d3 100644 --- a/assets/1_3.txt +++ b/assets/1_3.txt @@ -1,20 +1,20 @@ name: 1-3 -finish: 39 -1-6: text "Oh, we have mirrors too.\nAbsolutely not for safety reasons." -3-33: mirror +@ 3/ 42 mirror -8: plane DAMAGE BOX -10: plane DAMAGE BIGDOT -12: plane DAMAGE BOX_DOT +1/ 6 text "Oh, we have mirrors too.\nAbsolutely not for safety reasons." -15-18: text "Ok, I lied.\n\nThere MIGHT be invisible red stuff." +3/ plane DAMAGE BOX +3/ plane DAMAGE BIGDOT +3/ plane DAMAGE BOX_DOT -21: plane INVIS BOX -23: plane INVIS BIGDOT -25: plane ARROW ARROW_+X -27: plane ARROW ARROW_-X -29: plane INVIS VLINES_2_4 +4/ 4 text "Ok, I lied.\n\nThere MIGHT be invisible red stuff." -31-33: text "Wow, you're good.\nYou're gonna run the lab\ninto the ground." -35-37: text "The DROP. *" +3/ plane INVIS BOX +3/ plane INVIS BIGDOT +3/ plane ARROW ARROW_+X +3/ plane ARROW ARROW_-X +3/ plane INVIS VLINES_2_4 + +4/ 5 text "Wow, you're good.\nYou're gonna run the lab\ninto the ground." +1/ 2 text "The DROP. *" diff --git a/assets/2_1.txt b/assets/2_1.txt index 7aa39d5..11e2d52 100644 --- a/assets/2_1.txt +++ b/assets/2_1.txt @@ -1,20 +1,19 @@ name: 2-1 -finish: 32 -1-4: text "Falling in 3, 2...\nOh, wait, you're already falling." +1/ 4 text "Falling in 3, 2...\nOh, wait, you're already falling." -6: plane DAMAGE DIAGONAL+ -8: plane DAMAGE DIAGONAL- -10: plane ARROW ARROW_+Z -12: plane DAMAGE BOX -13: plane ARROW ARROW_-X -14: plane ARROW ARROW_+X +3/ plane DAMAGE DIAGONAL+ +3/ plane DAMAGE DIAGONAL- +3/ plane ARROW ARROW_+Z +2/ plane DAMAGE BOX +2/ plane ARROW ARROW_-X +3/ plane ARROW ARROW_+X -16-30: mirror -18: plane DAMAGE RING -20: plane ARROW ARROW_-Z -21: plane DAMAGE BOX -22: plane ARROW ARROW_-X -23: plane DAMAGE DOT -24: plane ARROW ARROW_+X -27: plane DAMAGE VLINES_2_4 +@ 2/ 20 mirror +4/ plane DAMAGE RING +2/ plane ARROW ARROW_-Z +3/ plane DAMAGE BOX +2/ plane ARROW ARROW_-X +2/ plane DAMAGE DOT +2/ plane ARROW ARROW_+X +3/ plane DAMAGE VLINES_2_4 diff --git a/assets/2_2.txt b/assets/2_2.txt index 61401a7..a6eb887 100644 --- a/assets/2_2.txt +++ b/assets/2_2.txt @@ -1,19 +1,18 @@ name: 2-2 -finish: 34 -1-30: mirror -2-5: text "You don't have a reflection\nin the mirror.\n\nWhat does that tell us\nabout you?" +@ 3/ 40 mirror +1/ 5 text "You don't have a reflection\nin the mirror.\n\nWhat does that tell us\nabout you?" -7: plane ARROW ARROW_+X -9: plane DAMAGE HLINES_1_5 -11: plane DAMAGE VLINES_2_4 -13: plane ARROW ARROW_-Z -15: plane DAMAGE BIGDOT -16: plane DAMAGE BOX -18: plane DAMAGE BIGDOT -20: plane ARROW ARROW_-X -22: plane DAMAGE VLINES_2_4 -24: plane ARROW ARROW_+Z -26: plane DAMAGE HLINES_2_4 +3/ plane ARROW ARROW_+X +3/ plane DAMAGE HLINES_1_5 +3/ plane DAMAGE VLINES_1_3_5 +3/ plane ARROW ARROW_+Z +2/ plane DAMAGE BIGDOT +2/ plane DAMAGE BOX +2/ plane DAMAGE BIGDOT +3/ plane ARROW ARROW_-X +3/ plane DAMAGE VLINES_2_4 +3/ plane ARROW ARROW_+Z +3/ plane DAMAGE HLINES_2_4 -30-33: text "Look at you, all dizzy\njust from rolling a bit.\n\nGet ready, we need results!" +5/ 5 text "Don't get dizzy\njust from rolling a bit.\n\nBuckle up, we're going for results!" diff --git a/assets/2_3.txt b/assets/2_3.txt index e698f2c..f69692e 100644 --- a/assets/2_3.txt +++ b/assets/2_3.txt @@ -1,30 +1,28 @@ name: 2-3 -finish: 57 -1-3: text "Let's see if you can\nthread the needle here." +1/ 3 text "Let's see if you can\nthread the needle." -5: plane DAMAGE 0b11111'11101'11111'11111'11111 -7: plane DAMAGE 0b11111'11111'11111'10111'11111 -9: plane DAMAGE 0b11111'10111'11111'11111'11111 -11: plane DAMAGE 0b11111'11111'11111'11101'11111 +3/ plane DAMAGE 0b11111'11101'11101'11101'11111 +3/ plane DAMAGE 0b11111'11111'11111'11111'11001 +3/ plane DAMAGE 0b10111'10111'11111'11111'11111 +3/ plane ARROW ARROW_-X +3/ plane DAMAGE BOX_DOT -14-17: text "Trick question!\nYou just had to roll." -18-20: text "No longer though." +@ 6/ 36 mirror +4/ 5 text "Great!\n\nNow for peripheral vision..." -22: plane DAMAGE 0b01111'11111'11111'11111'11111 -24: plane DAMAGE 0b11111'10111'11111'11111'11111 -26: plane DAMAGE 0b11111'11111'11011'11111'11111 -28: plane DAMAGE 0b11111'11111'11111'11101'11111 -30: plane DAMAGE 0b11111'11111'11011'11111'11111 +2/ plane DAMAGE BOX +2/ plane INVIS HLINES_1_3_5 +2/ plane DAMAGE BIGDOT +2/ plane INVIS BOX -34: plane DAMAGE 0b11111'11101'11111'11111'11111 -36: plane ARROW ARROW_+Z -38: plane DAMAGE 0b11111'10111'11111'11111'11111 -40: plane ARROW ARROW_+X -42: plane DAMAGE 0b01111'11111'11111'11111'11111 -44: plane ARROW ARROW_-X -46: plane DAMAGE 0b11111'11111'11111'11101'11111 -48: plane ARROW ARROW_+Z -50: plane DAMAGE 0b11111'11111'11111'11101'11111 +3/ 1 text "Roll, boy, roll!" -52-55: text "Not bad...\nFinally someone promising." +2/ plane ARROW ARROW_-Z +2/ plane DAMAGE VLINES_1_3_5 +2/ plane ARROW ARROW_+X +2/ plane INVIS HASH +3/ plane ARROW ARROW_-X +2/ plane ARROW ARROW_+Z + +5/ 5 text "Not bad...!\nYou're promising,\nI'll give you that." diff --git a/assets/cursor.png b/assets/cursor.png index e0699a2..5f1dc8f 100644 Binary files a/assets/cursor.png and b/assets/cursor.png differ diff --git a/assets/cursor0.png b/assets/cursor0.png new file mode 100644 index 0000000..4c09199 Binary files /dev/null and b/assets/cursor0.png differ diff --git a/assets/title.png b/assets/title.png index 2fb6ade..faeba81 100644 Binary files a/assets/title.png and b/assets/title.png differ diff --git a/assets/title.xcf b/assets/title.xcf index 5e701e2..2834fa8 100644 Binary files a/assets/title.xcf and b/assets/title.xcf differ diff --git a/converters.py b/converters.py index 8708149..3d08da8 100644 --- a/converters.py +++ b/converters.py @@ -17,57 +17,80 @@ def convert(input, output, params, target): def num(value): return fxconv.u32(value * 65536) +DISTANCE_FACTOR = 24 + +def advance(position, coordinate): + silent = False + + if coordinate.startswith("@"): + silent = True + coordinate = coordinate[1:] + + if coordinate.startswith("="): + value = int(coordinate) + else: + value = position + int(coordinate[1:]) + + if silent: + return position, value + else: + return value, value + def convert_level(input, params): RE_VALUES = { "name": re.compile(r'.*'), - "finish": re.compile(r'\d+') } RE_ELEMENTS = { "mirror": (True, re.compile(r'')), "plane": (False, re.compile(r'(\S+)\s+(\S+)')), "text": (True, re.compile(r'\"([^"]+)\"')), } - RE_POSITION = re.compile(r'(\d+)(?:-(\d+))?') + RE_POSITION = re.compile(r'^\s*(@)?\s*(?:(\d+)/)?\s*(\d+)?') header = dict() elements = [] + pos = 0 with open(input, "r") as fp: lines = [l for l in fp.read().splitlines() if l and not l.startswith("#")] for i, l in enumerate(lines): - if ":" not in l: - raise fxconv.FxconvError(f"invalid line '{l}': no ':'") - key, value = [x.strip() for x in l.split(":", 1)] - - m_pos = RE_POSITION.fullmatch(key) - if m_pos: - start = int(m_pos[1]) - end = int(m_pos[2]) if m_pos[2] else None - things = [x.strip() for x in value.strip().split(" ", 1)] - if len(things) == 1: - key, value = things[0], "" - else: - key, value = things - - if key not in RE_ELEMENTS: - raise fxconv.FxconvError(f"unknown element '{key}'") - if RE_ELEMENTS[key][0] and end is None: - raise fxconv.FxconvError(f"'{key}' needs an end position") - if not RE_ELEMENTS[key][0] and end is not None: - raise fxconv.FxconvError(f"'{key}' needs no end position") - m = RE_ELEMENTS[key][1].fullmatch(value) - if not m: - raise fxconv.FxconvError( - f"invalid value for '{key}': '{value}") - elements.append((key, start, end, m)) - else: + # Key/value metadata + if ":" in l: + key, value = [x.strip() for x in l.split(":", 1)] if key not in RE_VALUES: raise fxconv.FxconvError(f"unknown key '{key}'") if not RE_VALUES[key].fullmatch(value): raise fxconv.FxconvError( f"invalid value for '{key}': '{value}'") header[key] = value + continue + + # Elements + m_pos = RE_POSITION.match(l) + if not m_pos: + raise fxconv.FxconvError(f"invalid position: '{l}'") + + start = pos + int(m_pos[2]) if m_pos[2] else pos + end = start + int(m_pos[3]) if m_pos[3] else start + if not m_pos[1]: + pos = end + + l = l[len(m_pos[0]):] + things = [x.strip() for x in l.strip().split(" ", 1)] + if len(things) == 1: + elname, data = things[0], "" + else: + elname, data = things + + if RE_ELEMENTS[elname][0] and end == start: + raise fxconv.FxconvError(f"'{elname}' needs a size") + if not RE_ELEMENTS[elname][0] and end != start: + 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}") + elements.append((elname, start, end, m)) mirrors = fxconv.ObjectData() planes = fxconv.ObjectData() @@ -78,8 +101,8 @@ def convert_level(input, params): for (key, start, end, m) in elements: if key == "mirror": - mirrors += num(start * 32) - mirrors += num(end * 32) + mirrors += num(start * DISTANCE_FACTOR) + mirrors += num(end * DISTANCE_FACTOR) mirror_count += 1 elif key == "plane": @@ -88,14 +111,18 @@ def convert_level(input, params): predef_shapes = { "VLINES_1_5": 0b1000110001100011000110001, + "VLINES_1_3_5": 0b1010110101101011010110101, "VLINES_2_4": 0b0101001010010100101001010, "HLINES_1_5": 0b1111100000000000000011111, + "HLINES_1_3_5": 0b1111100000111110000011111, "HLINES_2_4": 0b0000011111000001111100000, + "HASH": 0b0101011111010101111101010, "BOX": 0b1111110001100011000111111, "BOX_DOT": 0b1111110001101011000111111, "BIGDOT": 0b0000001110011100111000000, "DOT": 0b0000000000001000000000000, "RING": 0b0000001110010100111000000, + "CORNERS": 0b1101111011000001101111011, "DIAGONAL+": 0b0001100111011101110011000, "DIAGONAL-": 0b1100011100011100011100011, "ARROW_+X": 0b0010000010111110001000100, @@ -124,7 +151,7 @@ def convert_level(input, params): assert shape_str in directions data = directions.index(shape_str) - planes += num(start * 32) + planes += num(start * DISTANCE_FACTOR) planes += fxconv.u32(shape) planes += fxconv.u16(kinds[kind]) planes += fxconv.u16(data) @@ -132,14 +159,14 @@ def convert_level(input, params): elif key == "text": string = m[1].replace("\\n", "\n").replace("\\\\", "\\") - texts += num(start * 32) - texts += num(end * 32) + texts += num(start * DISTANCE_FACTOR) + texts += num(end * DISTANCE_FACTOR) texts += fxconv.string(string) text_count += 1 o = fxconv.ObjectData() o += fxconv.string(header.get("name", "")) - o += num(int(header["finish"]) * 32) + o += num(int(header.get("finish", pos+2)) * DISTANCE_FACTOR) o += fxconv.u32(mirror_count) o += fxconv.ptr(mirrors) o += fxconv.u32(plane_count) diff --git a/src/backend/gint/shader_vfx.cc b/src/backend/gint/shader_vfx.cc new file mode 100644 index 0000000..89fa271 --- /dev/null +++ b/src/backend/gint/shader_vfx.cc @@ -0,0 +1,57 @@ +#include "../../chaos-drop.h" +#include + +uint8_t CD_VFX_SHADER_ID = -1; + +struct cd_vfx_cmd +{ + /* Shader ID for Azur */ + uint8_t shader_id; + uint8_t _; + + uint16_t effect; +}; + +void cd_vfx_shader(void *uniforms, void *cmd0, void *fragment0) +{ + int N = (int)uniforms; + struct cd_vfx_cmd *cmd = (struct cd_vfx_cmd *)cmd0; + uint32_t *fragment = (uint32_t *)fragment0; + + if(cmd->effect == CD_VFX_DARKEN) { + for(int i = 0; i < N; i++) + fragment[i] = (fragment[i] & 0xf7def7de) >> 1; + } + else if(cmd->effect == CD_VFX_WHITEN) { + for(int i = 0; i < N; i++) + fragment[i] = ~((~fragment[i] & 0xf7def7de) >> 1); + } + else if(cmd->effect == CD_VFX_INVERT) { + for(int i = 0; i < N; i++) + fragment[i] = ~fragment[i]; + } +} + +GCONSTRUCTOR +static void register_shader(void) +{ + CD_VFX_SHADER_ID = azrp_register_shader(cd_vfx_shader); +} + +void cd_vfx(int effect) +{ + prof_enter(azrp_perf_cmdgen); + + struct cd_vfx_cmd cmd; + cmd.shader_id = CD_VFX_SHADER_ID; + cmd.effect = effect; + + azrp_queue_command(&cmd, sizeof cmd, 0, azrp_frag_count); + prof_leave(azrp_perf_cmdgen); +} + +void cd_vfx_configure(void) +{ + uint32_t value = (azrp_frag_height * azrp_width) / 2; + azrp_set_uniforms(CD_VFX_SHADER_ID, (void *)value); +} diff --git a/src/chaos-drop.h b/src/chaos-drop.h index cf633f7..33eb5d9 100644 --- a/src/chaos-drop.h +++ b/src/chaos-drop.h @@ -202,6 +202,22 @@ void cd_raytrace(struct game const *game); any scale change. */ void cd_raytrace_configure(void); +//--- +// Other shaders +//--- + +/* Basic full-screen visual effects */ +enum { + CD_VFX_DARKEN = 0, + CD_VFX_WHITEN = 1, + CD_VFX_INVERT = 2, +}; + +/* Apply a visual effect to the entire screen */ +void cd_vfx(int effect); +/* Shader configuration function for cd_vfx() */ +void cd_vfx_configure(void); + //=== Input management ===// struct input { diff --git a/src/main.cc b/src/main.cc index 871cc47..375528c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -168,6 +168,7 @@ static void init(void) prof_init(); azrp_config_scale(2); cd_raytrace_configure(); + cd_vfx_configure(); azrp_shader_clear_configure(); azrp_shader_image_p8_configure(); } @@ -287,7 +288,7 @@ void game_render(struct game *g) struct level const *level = g->level; #ifdef AZUR_TOOLKIT_GINT - extern image_t img_title, img_cursor; + extern image_t img_title, img_cursor, img_cursor0; azrp_perf_clear(); if(g->blank_frames > 0) { @@ -311,7 +312,9 @@ void game_render(struct game *g) int width = text_size(name, l); if(g->menu_cursor == i) - azrp_image(x - width/2 - 6, y-2, &img_cursor); + azrp_image(x - width/2 - 8, y-5, &img_cursor); + else + azrp_image(x - width/2 - 6, y-3, &img_cursor0); draw_text(x - width/2, y, name, l); } diff --git a/src/raytracing.cc b/src/raytracing.cc index e686297..3df2431 100644 --- a/src/raytracing.cc +++ b/src/raytracing.cc @@ -6,11 +6,11 @@ #define RGB(R, G, B) ((R << 11) | (G << 6) | (B)) /* Color palette for world objects */ static uint16_t const object_colors[] = { - RGB(3, 4, 8), /* Void/background */ - RGB(3, 4, 8), /* Left wall (-X) */ - RGB(5, 6, 9), /* Top wall (+Z) */ - RGB(7, 8, 11), /* Right wall (+X) */ - RGB(5, 6, 9), /* Bottom wall (-Z) */ + 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(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 */