/apps/demos/crawl: visuals and stuff

This commit is contained in:
veclavtalica 2025-02-21 01:12:41 +03:00
parent 70fab28158
commit 66c525a0d4
6 changed files with 214 additions and 91 deletions

BIN
apps/demos/crawl/data/assets/brick.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
apps/demos/crawl/data/assets/pebbles.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -11,16 +11,21 @@
@classes @classes
-- Defines classes under symbols, which could have properties attached. -- Defines classes under symbols, which could have properties attached.
# wall # stone_wall
. floor wall_texture : /assets/brick.png
. stone_floor
tile_texture : /assets/pebbles.png
@ player_spawn @ player_spawn
unique : unique :
face : south face : south
hold : torch hold : torch
tile_texture : /assets/pebbles.png
X door X door
open_on : sg_torch0 open_on_signal : sg_torch0
/ torch tile_texture : /assets/pebbles.png
emit : sg_torch0 / lever
on_interact_emit : sg_torch0
tile_texture : /assets/pebbles.png
@meta @meta
-- Arbitrary sections could be defined with value pairs. -- Arbitrary sections could be defined with value pairs.

View File

@ -1,98 +1,64 @@
require("string") require("string")
require("level")
require("render")
function load_level(file) function lerp(a, b, x)
local f = file_read { file = file } return a + ((b - a) * x)
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 end
function qlerp(a, b, x)
return lerp(a, b, x * x)
end
function game_tick() function game_tick()
if ctx.udata == nil then if ctx.udata == nil then
ctx.udata = { ctx.udata = {
level = load_level("levels/00.lvl") 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 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 end

View File

@ -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

View File

@ -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