From 66c525a0d4d168df97b77f64ef21b3606e2f92fb Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Fri, 21 Feb 2025 01:12:41 +0300 Subject: [PATCH] /apps/demos/crawl: visuals and stuff --- apps/demos/crawl/data/assets/brick.png | 3 + apps/demos/crawl/data/assets/pebbles.png | 3 + apps/demos/crawl/data/levels/00.lvl | 15 ++- apps/demos/crawl/data/scripts/game.lua | 138 +++++++++-------------- apps/demos/crawl/data/scripts/level.lua | 87 ++++++++++++++ apps/demos/crawl/data/scripts/render.lua | 59 ++++++++++ 6 files changed, 214 insertions(+), 91 deletions(-) create mode 100644 apps/demos/crawl/data/assets/brick.png create mode 100644 apps/demos/crawl/data/assets/pebbles.png create mode 100644 apps/demos/crawl/data/scripts/level.lua create mode 100644 apps/demos/crawl/data/scripts/render.lua diff --git a/apps/demos/crawl/data/assets/brick.png b/apps/demos/crawl/data/assets/brick.png new file mode 100644 index 0000000..cdbbdeb --- /dev/null +++ b/apps/demos/crawl/data/assets/brick.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ae17cf7bf707adac858d8bcbf5beb17621e49418d9f1fa9b4a4da56dc06ad49 +size 26378 diff --git a/apps/demos/crawl/data/assets/pebbles.png b/apps/demos/crawl/data/assets/pebbles.png new file mode 100644 index 0000000..4632701 --- /dev/null +++ b/apps/demos/crawl/data/assets/pebbles.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe48cc6da3a1e2e3871301377fe453c2a4eb09e8e93565cb0d29d970d9e4490f +size 36539 diff --git a/apps/demos/crawl/data/levels/00.lvl b/apps/demos/crawl/data/levels/00.lvl index c97c65b..798b326 100644 --- a/apps/demos/crawl/data/levels/00.lvl +++ b/apps/demos/crawl/data/levels/00.lvl @@ -11,16 +11,21 @@ @classes -- Defines classes under symbols, which could have properties attached. -# wall -. floor +# stone_wall + wall_texture : /assets/brick.png +. stone_floor + tile_texture : /assets/pebbles.png @ player_spawn unique : face : south hold : torch + tile_texture : /assets/pebbles.png X door - open_on : sg_torch0 -/ torch - emit : sg_torch0 + open_on_signal : sg_torch0 + tile_texture : /assets/pebbles.png +/ lever + on_interact_emit : sg_torch0 + tile_texture : /assets/pebbles.png @meta -- Arbitrary sections could be defined with value pairs. diff --git a/apps/demos/crawl/data/scripts/game.lua b/apps/demos/crawl/data/scripts/game.lua index 6beaf88..71e4a42 100644 --- a/apps/demos/crawl/data/scripts/game.lua +++ b/apps/demos/crawl/data/scripts/game.lua @@ -1,98 +1,64 @@ require("string") +require("level") +require("render") -function load_level(file) - local f = file_read { file = file } - - local result = { - classes = { - void = { }, - }, - glossary = { - [" "] = "void", - }, - grid = {}, - map = {}, - size = { x = 0, y = 0 }, - } - - -- iterate over lines - local section, subsection = "none", "none" - local from = 1 - local start, limit = string.find(f, "\n", from) - while start do - local line = string.sub(f, from, start - 1) - -- skip over - if #line == 0 or line:find("^%-%-%s*") then - goto skip - -- start new section - elseif line:find("^@%g+") then - section = line:sub(2); subsection = "none" - -- decode map one line at a time - elseif section == "map" then - local l = #result.map + 1 - if result.size.x < #line then - result.size.x = #line - end - result.map[l] = {} - for i = 1, #line do - result.map[l][i] = line:sub(i,i) - end - -- templates to expand - elseif section == "classes" then - -- properties - if line:find("^ %g+") then - local _, _, property, value = line:find("^ (%g+)%s?:%s?(.*)") - result.classes[subsection][property] = value - goto skip - end - local symbol, classname = line:sub(1,1), line:sub(3) - result.classes[classname] = { - symbol = symbol, - } - result.glossary[symbol] = classname - subsection = classname - elseif section ~= "none" then - local _, _, property, value = line:find("^(%g+)%s?:%s?(.*)") - if result[section] == nil then - result[section] = {} - end - result[section][property] = value - end - ::skip:: - from = limit + 1 - start, limit = string.find(f, "\n", from) - end - -- post process - for y = 1, #result.map do - result.grid[y] = {} - for x = 1, result.size.x do - -- past defined for line - local symbol - if x > #result.map[y] then symbol = " " - else symbol = result.map[y][x] - end - local class = result.classes[result.glossary[symbol]] - if class["unique"] ~= nil then - class.position = { x = x, y = y } - end - result.grid[y][x] = class - ::continue:: - end - end - - result.size.y = #result.map - - print(result.meta.description) - - return result +function lerp(a, b, x) + return a + ((b - a) * x) end +function qlerp(a, b, x) + return lerp(a, b, x * x) +end function game_tick() if ctx.udata == nil then ctx.udata = { level = load_level("levels/00.lvl") } - log_vec2 { value = ctx.udata.level.classes.player_spawn.position } + ctx.udata.player = { + position = ctx.udata.level.classes.player_spawn.position, + position_lerp = ctx.udata.level.classes.player_spawn.position, + direction = { x = 1, y = 0, z = 0 }, + direction_lerp = { x = 1, y = 0, z = 0 }, + } end + + input_action { control = "A", name = "turn_left" } + input_action { control = "D", name = "turn_right" } + input_action { control = "W", name = "walk_forward" } + input_action { control = "S", name = "walk_backward" } + + if input_action_just_released { name = "turn_left" } then + ctx.udata.player.direction = { x = ctx.udata.player.direction.z, y = ctx.udata.player.direction.y, z = -ctx.udata.player.direction.x } + end + + if input_action_just_released { name = "turn_right" } then + ctx.udata.player.direction = { x = -ctx.udata.player.direction.z, y = ctx.udata.player.direction.y, z = ctx.udata.player.direction.x } + end + + local direction = { x = 0, z = 0 } + if input_action_just_released { name = "walk_forward" } then + direction = { x = direction.x + ctx.udata.player.direction.z, z = direction.z + ctx.udata.player.direction.x } + end + if input_action_just_released { name = "walk_backward" } then + direction = { x = direction.x - ctx.udata.player.direction.z, z = direction.z - ctx.udata.player.direction.x } + end + + ctx.udata.player.position = { x = ctx.udata.player.position.x + direction.x, y = ctx.udata.player.position.y + direction.z } + + ctx.udata.player.position_lerp.x = qlerp(ctx.udata.player.position_lerp.x, ctx.udata.player.position.x, ctx.frame_duration * 30) + ctx.udata.player.position_lerp.y = qlerp(ctx.udata.player.position_lerp.y, ctx.udata.player.position.y, ctx.frame_duration * 30) + ctx.udata.player.direction_lerp.x = qlerp(ctx.udata.player.direction_lerp.x, ctx.udata.player.direction.x, ctx.frame_duration * 40) + ctx.udata.player.direction_lerp.z = qlerp(ctx.udata.player.direction_lerp.z, ctx.udata.player.direction.z, ctx.frame_duration * 40) + + draw_camera { + position = { + x = ctx.udata.player.position_lerp.y * 2 + 1, + y = 1, + z = ctx.udata.player.position_lerp.x * 2 + 1, + }, + direction = ctx.udata.player.direction_lerp, + } + + render_dungeon(ctx.udata.level) end diff --git a/apps/demos/crawl/data/scripts/level.lua b/apps/demos/crawl/data/scripts/level.lua new file mode 100644 index 0000000..e05046d --- /dev/null +++ b/apps/demos/crawl/data/scripts/level.lua @@ -0,0 +1,87 @@ + +function load_level(file) + local f = file_read { file = file } + + local result = { + classes = { + void = { }, + }, + glossary = { + [" "] = "void", + }, + grid = {}, + map = {}, + size = { x = 0, y = 0 }, + } + + -- iterate over lines + local section, subsection = "none", "none" + local from = 1 + local start, limit = string.find(f, "\n", from) + while start do + local line = string.sub(f, from, start - 1) + -- skip over + if #line == 0 or line:find("^%-%-%s*") then + goto skip + -- start new section + elseif line:find("^@%g+") then + section = line:sub(2); subsection = "none" + -- decode map one line at a time + elseif section == "map" then + local l = #result.map + 1 + if result.size.x < #line then + result.size.x = #line + end + result.map[l] = {} + for i = 1, #line do + result.map[l][i] = line:sub(i,i) + end + -- templates to expand + elseif section == "classes" then + -- properties + if line:find("^ %g+") then + local _, _, property, value = line:find("^ (%g+)%s?:%s?(.*)") + result.classes[subsection][property] = value + goto skip + end + local symbol, classname = line:sub(1,1), line:sub(3) + result.classes[classname] = { + symbol = symbol, + } + result.glossary[symbol] = classname + subsection = classname + elseif section ~= "none" then + local _, _, property, value = line:find("^(%g+)%s?:%s?(.*)") + if result[section] == nil then + result[section] = {} + end + result[section][property] = value + end + ::skip:: + from = limit + 1 + start, limit = string.find(f, "\n", from) + end + -- post process + for y = 1, #result.map do + result.grid[y] = {} + for x = 1, result.size.x do + -- past defined for line + local symbol + if x > #result.map[y] then symbol = " " + else symbol = result.map[y][x] + end + local class = result.classes[result.glossary[symbol]] + if class["unique"] ~= nil then + class.position = { x = x, y = y } + end + result.grid[y][x] = class + ::continue:: + end + end + + result.size.y = #result.map + + print(result.meta.description) + + return result +end diff --git a/apps/demos/crawl/data/scripts/render.lua b/apps/demos/crawl/data/scripts/render.lua new file mode 100644 index 0000000..f0819e1 --- /dev/null +++ b/apps/demos/crawl/data/scripts/render.lua @@ -0,0 +1,59 @@ + +function render_dungeon(dungeon) + for y = 1, dungeon.size.y do + for x = 1, dungeon.size.x do + if dungeon.grid[y][x].wall_texture ~= nil then + draw_quad { + texture = dungeon.grid[y][x].wall_texture, + v3 = { x = y * 2, y = 2, z = x * 2 }, + v2 = { x = y * 2, y = 0, z = x * 2 }, + v1 = { x = y * 2 + 2, y = 0, z = x * 2 }, + v0 = { x = y * 2 + 2, y = 2, z = x * 2 }, + texture_region = { w = 128, h = 128 }, + } + draw_quad { + texture = dungeon.grid[y][x].wall_texture, + v3 = { x = y * 2 + 2, y = 2, z = x * 2 }, + v2 = { x = y * 2 + 2, y = 0, z = x * 2 }, + v1 = { x = y * 2 + 2, y = 0, z = x * 2 + 2 }, + v0 = { x = y * 2 + 2, y = 2, z = x * 2 + 2 }, + texture_region = { w = 128, h = 128 }, + } + draw_quad { + texture = dungeon.grid[y][x].wall_texture, + v3 = { x = y * 2 + 2, y = 2, z = x * 2 + 2 }, + v2 = { x = y * 2 + 2, y = 0, z = x * 2 + 2 }, + v1 = { x = y * 2, y = 0, z = x * 2 + 2 }, + v0 = { x = y * 2, y = 2, z = x * 2 + 2 }, + texture_region = { w = 128, h = 128 }, + } + draw_quad { + texture = dungeon.grid[y][x].wall_texture, + v3 = { x = y * 2, y = 2, z = x * 2 + 2 }, + v2 = { x = y * 2, y = 0, z = x * 2 + 2 }, + v1 = { x = y * 2, y = 0, z = x * 2 }, + v0 = { x = y * 2, y = 2, z = x * 2 }, + texture_region = { w = 128, h = 128 }, + } + + elseif dungeon.grid[y][x].tile_texture ~= nil then + draw_quad { + texture = dungeon.grid[y][x].tile_texture, + v0 = { x = y * 2 + 2, y = 0, z = x * 2 }, + v1 = { x = y * 2, y = 0, z = x * 2 }, + v2 = { x = y * 2, y = 0, z = x * 2 + 2 }, + v3 = { x = y * 2 + 2, y = 0, z = x * 2 + 2}, + texture_region = { w = 128, h = 128 }, + } + draw_quad { + texture = dungeon.grid[y][x].tile_texture, + v3 = { x = y * 2 + 2, y = 2, z = x * 2 }, + v2 = { x = y * 2, y = 2, z = x * 2 }, + v1 = { x = y * 2, y = 2, z = x * 2 + 2 }, + v0 = { x = y * 2 + 2, y = 2, z = x * 2 + 2}, + texture_region = { w = 128, h = 128 }, + } + end + end + end +end