From 75f74b324a76e29c2c014c6d87bf8c917a3d88d7 Mon Sep 17 00:00:00 2001 From: Nicholas Hayashi Date: Mon, 4 Jan 2021 21:15:52 -0500 Subject: [PATCH] reorganize --- res/mob1_1.png | Bin 0 -> 6260 bytes src/color.lua | 26 ++++++++++++++ src/colors.lua | 17 --------- src/grid.lua | 4 +-- src/hexyz.lua | 58 ++++++++++++++++++++++-------- src/main.lua | 37 ++++++------------- src/math.lua | 9 +++++ src/mob.lua | 92 ++++++++++++++++++++++++++++++++---------------- src/sound.lua | 14 ++++++++ src/table.lua | 14 ++++++++ src/texture.lua | 5 +++ src/util.lua | 10 ++++-- 12 files changed, 191 insertions(+), 95 deletions(-) create mode 100644 res/mob1_1.png create mode 100644 src/color.lua delete mode 100644 src/colors.lua create mode 100644 src/math.lua create mode 100644 src/sound.lua create mode 100644 src/table.lua create mode 100644 src/texture.lua diff --git a/res/mob1_1.png b/res/mob1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3c8a9eb554d621d148ac9b61b8678c6776ab4c GIT binary patch literal 6260 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 literal 0 HcmV?d00001 diff --git a/src/color.lua b/src/color.lua new file mode 100644 index 0000000..74ae63f --- /dev/null +++ b/src/color.lua @@ -0,0 +1,26 @@ + + +COLORS = { + TRANSPARENT = vec4(0.4), + + -- tones + WHITE = vec4(0.8, 0.8, 0.7, 1), + BLACK = vec4(0, 0, 0, 1), + TRUEBLACK = vec4(0, 0, 0, 1), + + -- hues + BLUE_STONE = vec4(0.12, 0.3, 0.3, 1), + MYRTLE = vec4(0.10, 0.25, 0.10, 1), + BROWN_POD = vec4(0.25, 0.20, 0.10, 1), + BOTTLE_GREEN = vec4(0.15, 0.30, 0.20, 1), + MAGENTA = vec4(1, 0, 1, 1), + TEAL = vec4(16/255, 126/255, 124/244, 1), + YALE_BLUE = vec4(4/255, 75/255, 127/255, 1), + OLIVE = vec4(111/255, 124/254, 18/255, 1), + LIGHT_CYAN = vec4(224/255, 251/255, 252/255, 1), + PALE_SILVER = vec4(193/255, 178/255, 171/255, 1), + CLARET = vec4(139/255, 30/255, 63/255, 1), + BISTRO = vec4(73/255, 44/255, 29/255, 1), + DEEP_SPACE_SPARKLE = vec4(61/255, 90/255, 108/255, 1) +} + diff --git a/src/colors.lua b/src/colors.lua deleted file mode 100644 index 5b22f72..0000000 --- a/src/colors.lua +++ /dev/null @@ -1,17 +0,0 @@ - -COLORS = { - TRANSPARENT = vec4(0.4), - - -- tones - WHITE = vec4(0.8, 0.8, 0.7, 1), - BLACK = vec4(0, 0, 0, 1), - TRUEBLACK = vec4(0, 0, 0, 1), - - -- hues - BLUE_STONE = vec4(0.12, 0.3, 0.3, 1), - MYRTLE = vec4(0.10, 0.25, 0.10, 1), - BROWN_POD = vec4(0.25, 0.20, 0.10, 1), - BOTTLE_GREEN = vec4(0.15, 0.30, 0.20, 1), - MAGENTA = vec4(1, 0, 1, 1) -} - diff --git a/src/grid.lua b/src/grid.lua index 41cfde6..23d2d09 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -1,6 +1,5 @@ -require "colors" -require "gui" +require "hexyz" HEX_SIZE = 20 HEX_GRID_WIDTH = 65 -- 65 @@ -79,6 +78,7 @@ function random_map(seed, do_seed_rng) -- the center of the map in some radius is always considered 'passable' terrain and is home base -- terraform this area to ensure it's passable -- @NOTE no idea why the y-coord doesn't need to be transformed + -- @TODO @FIXME also terraform the edges of the map to be passable - it is theoretically possible to get maps where mobs can be stuck from the very beginning local home = spiral_map(HEX_GRID_CENTER, 3) for _,hex in pairs(home) do map[hex.x][hex.y].elevation = 0 diff --git a/src/hexyz.lua b/src/hexyz.lua index be46bc2..d98f6f9 100644 --- a/src/hexyz.lua +++ b/src/hexyz.lua @@ -170,12 +170,44 @@ function hex_corners(hex, size, orientation) return corners end +-- @TODO test +function hex_to_oddr(hex) + local z = -hex.x - hex.y + return vec2(hex.x + (z - (z % 2)) / 2) +end + +-- @TODO test +function oddr_to_hex(oddr) + return vec2(hex.x - (hex.y - (hex.y % 2)) / 2, -hex.x - hex.y) +end + +-- @TODO test +function hex_to_evenr(hex) + local z = -hex.x - hex.y + return vec2(hex.x + (z + (z % 2)) / 2, z) +end + +-- @TODO test +function evenr_to_hex(evenr) + return vec2(hex.x - (hex.y + (hex.y % 2)) / 2, -hex.x - hex.y) +end + +-- @TODO test +function hex_to_oddq(hex) + return vec2(hex.x, -hex.x - hex.y + (hex.x - (hex.x % 2)) / 2) +end + +-- @TODO test +function oddq_to_hex(oddq) + return vec2(hex.x, -hex.x - (hex.y - (hex.x - (hex.y % 2)) / 2)) +end + function hex_to_evenq(hex) return vec2(hex.x, (-hex.x - hex.y) + (hex.x + (hex.x % 2)) / 2) end -function evenq_to_hex(off) - return vec2(off.x, -off.x - (off.y - (off.x + (off.x % 2)) / 2)) +function evenq_to_hex(evenq) + return vec2(evenq.x, -evenq.x - (evenq.y - (evenq.x + (evenq.x % 2)) / 2)) end --============================================================================ @@ -404,19 +436,15 @@ function Astar(map, start, goal, neighbour_f, heuristic_f, cost_f) end for _,next_ in pairs(neighbour_f(current.hex)) do - local entry = map.get(next_.x, next_.y) - - if entry then - local new_cost = map_get(cost_so_far, current.hex.x, current.hex.y) - + cost_f(entry) - - local next_cost = map_get(cost_so_far, next_.x, next_.y) - if not next_cost or new_cost < next_cost then - map_set(cost_so_far, next_.x, next_.y, new_cost) - local priority = new_cost + heuristic_f(goal, next_) - table.insert(frontier, { hex = next_, priority = priority }) - map_set(came_from, next_.x, next_.y, current) - end + local new_cost = map_get(cost_so_far, current.hex.x, current.hex.y) + + cost_f(next_) + local next_cost = map_get(cost_so_far, next_.x, next_.y) + + if not next_cost or new_cost < next_cost then + map_set(cost_so_far, next_.x, next_.y, new_cost) + local priority = new_cost + heuristic_f(goal, next_) + table.insert(frontier, { hex = next_, priority = priority }) + map_set(came_from, next_.x, next_.y, current) end end end diff --git a/src/main.lua b/src/main.lua index 8468b63..3ed8f77 100644 --- a/src/main.lua +++ b/src/main.lua @@ -3,34 +3,21 @@ math.randomseed(os.time()); math.random(); math.random(); math.random() --============================================================================ -- Imports -require "hexyz" +require "color" require "grid" require "mob" -require "util" +require "math" +require "table" + --============================================================================ -- Globals +TIME = 0 win = am.window{ width = 1920, height = 1080 } -function mask() - return am.rect(win.left, win.bottom, win.right, win.top, COLORS.TRANSPARENT):tag"mask" -end - -function get_menu_for_tile(x, y, tile) - local pos = hex_to_pixel(vec2(x, y)) + WORLDSPACE_COORDINATE_OFFSET - return am.translate(pos) ^ am.group{ - am.rect(-50, -50, 50, 50, COLORS.TRANSPARENT), - make_button_widget(x .. y, pos, vec2(100, 37), "close") - } -end - -function invoke_tile_menu(x, y, tile) - win.scene:append(get_menu_for_tile(x, y, tile)) -end - function game_action(scene) - local time = am.current_time() + TIME = am.current_time() local mouse = win:mouse_position() local hex = pixel_to_hex(mouse - WORLDSPACE_COORDINATE_OFFSET) @@ -44,18 +31,12 @@ function game_action(scene) if win:key_pressed"f1" then end - for wid,widget in pairs(get_widgets()) do - if widget.poll() then - log('we clicked button with id %s!', wid) - end - end - do_mob_updates() do_mob_spawning() -- draw stuff win.scene"hex_cursor".center = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET - win.scene"score".text = string.format("SCORE: %.2f", time) + win.scene"score".text = string.format("SCORE: %.2f", TIME) win.scene"coords".text = string.format("%d,%d", hex.x, hex.y) end @@ -79,7 +60,7 @@ function game_scene() curtain, hex_cursor, score, - coords, + coords } scene:action(game_action) @@ -88,6 +69,8 @@ function game_scene() end function init() + require "texture" + load_textures() win.scene = am.scale(1) ^ game_scene() end diff --git a/src/math.lua b/src/math.lua new file mode 100644 index 0000000..aac0697 --- /dev/null +++ b/src/math.lua @@ -0,0 +1,9 @@ + +function math.wrapf(float, range) + return float - range * math.floor(float / range) +end + +function math.lerpv2(v1, v2, t) + return v1 * t + v2 * (1 - t) +end + diff --git a/src/mob.lua b/src/mob.lua index 4eab791..10ef5e0 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -1,5 +1,47 @@ + MOBS = {} +--[[ + mob structure: + { + position - vec2 -- true pixel coordinates + TOB - float -- time stamp in seconds of when the mob when spawned + node - node -- the root graph node for this mob + hex - vec2 -- hexagon the mob is on top of + update - function -- the function that gets called every frame + } +]] + +require "sound" +require "util" + +MOB_UPDATES = { + BEEPER = function(mob, index) + mob.hex = pixel_to_hex(mob.position - WORLDSPACE_COORDINATE_OFFSET) + + local frame_target = map_get(mob.path, mob.hex.x, mob.hex.y) + + if frame_target then + mob.position = math.lerpv2(mob.position, hex_to_pixel(frame_target.hex) + WORLDSPACE_COORDINATE_OFFSET, 0.91) + mob.node.position2d = mob.position + + -- can't find path, or dead + else + win.scene:action(am.play(am.sfxr_synth(SOUNDS.EXPLOSION1), false, math.random() + 0.5)) + + local i,v = table.find(MOBS, function(_mob) return _mob == mob end) + table.remove(MOBS, index) + win.scene:remove(mob.node) + end + + -- passive animation + if math.random() < 0.01 then + mob.node"rotate":action(am.tween(0.3, { angle = mob.node"rotate".angle + math.pi*3 })) + else + mob.node"rotate".angle = math.wrapf(mob.node"rotate".angle + am.delta_time, math.pi*2) + end + end +} -- check if a the tile at |hex| is passable by |mob| function can_pass_through(mob, hex) @@ -7,10 +49,7 @@ function can_pass_through(mob, hex) return tile and tile.elevation < 0.5 and tile.elevation > -0.5 end -function get_movement_cost(mob, start_hex, goal_hex) - return 1 -end - +-- @FIXME there's a bug here where the position of the spawn hex is sometimes 1 closer to the center than we want function get_spawn_hex(mob) local spawn_hex repeat @@ -40,16 +79,15 @@ function get_spawn_hex(mob) return spawn_hex end --- @NOTE spawn hex +-- function make_mob() local mob = {} - local spawn_hex = get_spawn_hex(mob) - local spawn_position = hex_to_pixel(spawn_hex) + WORLDSPACE_COORDINATE_OFFSET - - mob.position = spawn_position - mob.hex = spawn_hex - mob.path = Astar(HEX_MAP, HEX_GRID_CENTER, spawn_hex, + mob.TOB = TIME + mob.update = MOB_UPDATES.BEEPER + mob.hex = get_spawn_hex(mob) + mob.position = hex_to_pixel(mob.hex) + WORLDSPACE_COORDINATE_OFFSET + mob.path = Astar(HEX_MAP, HEX_GRID_CENTER, mob.hex, -- neighbour function function(hex) @@ -64,39 +102,31 @@ function make_mob() end, -- cost function - function(map_entry) - return math.abs(map_entry.elevation) + function(hex) + return math.abs(HEX_MAP.get(hex.x, hex.y).elevation) end ) - mob.sprite = am.circle(spawn_position, 18, COLORS.WHITE, 4) - win.scene:append(mob.sprite) + mob.node = am.translate(mob.position) + ^ am.scale(2) + ^ am.rotate(mob.TOB) + ^ pack_texture_into_sprite(TEX_MOB1_1, 20, 20) + + win.scene:append(mob.node) return mob end -local SPAWN_CHANCE = 25 +local SPAWN_CHANCE = 50 function do_mob_spawning() - if win:key_pressed"space" then - --if math.random(SPAWN_CHANCE) == 1 then + if math.random(SPAWN_CHANCE) == 1 then table.insert(MOBS, make_mob()) end end function do_mob_updates() - --if win:key_pressed"a" then - for _,mob in pairs(MOBS) do - mob.hex = pixel_to_hex(mob.position - WORLDSPACE_COORDINATE_OFFSET) - - local frame_target = map_get(mob.path, mob.hex.x, mob.hex.y) - - if frame_target then - mob.position = lerp(mob.position, hex_to_pixel(frame_target.hex) + WORLDSPACE_COORDINATE_OFFSET, 0.9) - mob.sprite.center = mob.position - else - - end + for i,mob in pairs(MOBS) do + mob.update(mob, i) end - --end end diff --git a/src/sound.lua b/src/sound.lua new file mode 100644 index 0000000..29ae28c --- /dev/null +++ b/src/sound.lua @@ -0,0 +1,14 @@ + +SOUNDS = { + EXPLOSION1 = 49179102, -- this slowed sounds metal as fuck + EXPLOSION2 = 19725402, + LASER1 = 79859301, + PUSH1 = 30455908, + BIRD1 = 50838307, + RANDOM1 = 85363309, + RANDOM2 = 15482409, + RANDOM3 = 58658009, + RANDOM4 = 89884209, + RANDOM5 = 36680709 +} + diff --git a/src/table.lua b/src/table.lua new file mode 100644 index 0000000..81c7e0b --- /dev/null +++ b/src/table.lua @@ -0,0 +1,14 @@ + +function table.rchoice(t) + return t[math.floor(math.random() * #t) + 1] +end + +function table.find(t, predicate) + for i,v in pairs(t) do + if predicate(v) then + return i,v + end + end + return nil +end + diff --git a/src/texture.lua b/src/texture.lua new file mode 100644 index 0000000..db0de40 --- /dev/null +++ b/src/texture.lua @@ -0,0 +1,5 @@ + +function load_textures() + TEX_MOB1_1 = am.texture2d("../res/mob1_1.png") +end + diff --git a/src/util.lua b/src/util.lua index 972a16a..fd7e481 100644 --- a/src/util.lua +++ b/src/util.lua @@ -1,6 +1,10 @@ -function lerp(v1, v2, t) - return v1 * t + v2 * (1 - t) +function pack_texture_into_sprite(texture, width, height) + return am.sprite{ + texture = texture, + s1 = 0, s2 = 1, t1 = 0, t2 = 1, + x1 = 0, x2 = width, width = width, + y1 = 0, y2 = height, height = height + } end -