diff --git a/src/entity.lua b/src/entity.lua index d1c490d..7dfca12 100644 --- a/src/entity.lua +++ b/src/entity.lua @@ -1,9 +1,10 @@ + ENTITY_TYPE = { - ENTITY = 0, - MOB = 1, - TOWER = 2, - PROJECTILE = 3 + ENTITY = 0, + MOB = 1, + TOWER = 2, + PROJECTILE = 3 } ENTITIES = {} @@ -21,6 +22,8 @@ ENTITIES = {} -- { -- path - 2d table - map of hexes to other hexes, forms a path -- speed - number - multiplier on distance travelled per frame, up to the update function to use correctly +-- bounty - number - score bonus you get when this mob is killed +-- hurtbox_radius - number - -- } -- -- tower(entity) structure: @@ -33,6 +36,10 @@ ENTITIES = {} -- -- bullet/projectile structure -- { +-- vector - vec2 - normalized vector of the current direction of this projectile +-- velocity - number - multplier on distance travelled per frame +-- damage - number - guess +-- hitbox_radius - number - hitboxes are circles -- } -- function make_and_register_entity(type_, hex, node, update) @@ -46,13 +53,21 @@ function make_and_register_entity(type_, hex, node, update) entity.node = am.translate(entity.position) ^ node table.insert(ENTITIES, entity) - WIN.scene"world":append(entity.node) + WORLD:append(entity.node) return entity end +function delete_all_entities() + for index,entity in pairs(ENTITIES) do + delete_entity(index) + end + + ENTITIES = {} +end + function delete_entity(index) - WIN.scene"world":remove(ENTITIES[index].node) - ENTITIES[index] = nil + WORLD:remove(ENTITIES[index].node) + ENTITIES[index] = nil -- leave empty indexes so other entities can learn that this entity was deleted end function do_entity_updates() @@ -61,4 +76,3 @@ function do_entity_updates() end end - diff --git a/src/grid.lua b/src/grid.lua index 309d5c2..a0b19fb 100644 --- a/src/grid.lua +++ b/src/grid.lua @@ -29,8 +29,10 @@ local function grid_pixel_dimensions() end GRID_PIXEL_DIMENSIONS = grid_pixel_dimensions() +WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2 + +HEX_GRID_INTERACTABLE_REGION_PADDING = 3 -HEX_GRID_INTERACTABLE_REGION_PADDING = 2 function is_interactable(tile, evenq) return point_in_rect(evenq, { x1 = HEX_GRID_INTERACTABLE_REGION_PADDING, @@ -75,7 +77,7 @@ function random_map(seed) local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y, seed) math.randomseed(map.seed) - local world = am.group():tag"world" + local world = am.group() for i,_ in pairs(map) do for j,noise in pairs(map[i]) do local evenq = hex_to_evenq(vec2(i, j)) @@ -111,7 +113,6 @@ function random_map(seed) world:append(am.circle(hex_to_pixel(HEX_GRID_CENTER), HEX_SIZE/2, COLORS.MAGENTA, 4)) - WORLDSPACE_COORDINATE_OFFSET = -GRID_PIXEL_DIMENSIONS/2 return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world:tag"world" end diff --git a/src/log.txt b/src/log.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.lua b/src/main.lua index 09dcf6f..1c415e0 100644 --- a/src/main.lua +++ b/src/main.lua @@ -13,13 +13,20 @@ require "projectile" require "tower" -- Globals -WIN = am.window{ width = 1920, height = 1080, title = "hexyz" } +WIN = am.window{ + width = 1920, + height = 1080, + title = "hexyz", + resizable = false +} OFF_SCREEN = vec2(WIN.width * 2) -- arbitrary pixel position that is garunteed to be off screen -TIME = 0 -SCORE = 0 -MOUSE = vec2(0) +WORLD = false -- root scene node of everything considered to be in the game world +TIME = 0 -- runtime of the current game in seconds +SCORE = 0 -- score of the player +MOUSE = false -- position of the mouse at the start of every frame, if an action is tracking it +RAND = 0 -- result of first call to math.random() this frame local COORDINATE_DISPLAY_TYPES = { CENTERED_EVENQ = 0, @@ -29,20 +36,23 @@ local COORDINATE_DISPLAY_TYPES = { local COORDINATE_DISPLAY_TYPE = COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ local function game_action(scene) - TIME = am.current_time() - SCORE = TIME - MOUSE = WIN:mouse_position() - - local hex = pixel_to_hex(MOUSE - WORLDSPACE_COORDINATE_OFFSET) - local rounded_mouse = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET - local evenq = hex_to_evenq(hex) - local centered_evenq = evenq{ y = -evenq.y } - vec2(math.floor(HEX_GRID_WIDTH/2) + if SCORE < 0 then game_end() end + + TIME = am.current_time() + SCORE = SCORE + am.delta_time + RAND = math.random() + MOUSE = WIN:mouse_position() + + local hex = pixel_to_hex(MOUSE - WORLDSPACE_COORDINATE_OFFSET) + local rounded_mouse = hex_to_pixel(hex) + WORLDSPACE_COORDINATE_OFFSET + local evenq = hex_to_evenq(hex) + local centered_evenq = evenq{ y = -evenq.y } - vec2(math.floor(HEX_GRID_WIDTH/2) , math.floor(HEX_GRID_HEIGHT/2)) local tile = HEX_MAP.get(hex.x, hex.y) local hot = is_interactable(tile, evenq{ y = -evenq.y }) - do_mob_spawning() do_entity_updates() + do_mob_spawning() if WIN:mouse_pressed"left" then if hot and is_buildable(hex, tile, nil) then @@ -51,6 +61,9 @@ local function game_action(scene) end if WIN:key_pressed"escape" then + pause() + + elseif WIN:key_pressed"f2" then WIN.scene = game_scene() elseif WIN:key_pressed"f3" then @@ -84,6 +97,24 @@ local function game_action(scene) end end +function pause() + WORLD"group".paused = true +end + +function game_end() + WIN.scene.paused = true + + -- de-initialize stuff + delete_all_entities() + SCORE = 0 + + WIN.scene = game_scene() +end + +function update_score(diff) + SCORE = SCORE + diff +end + local function toolbelt() local toolbelt_height = hex_height(HEX_SIZE) * 2 local toolbelt = am.group{ @@ -116,11 +147,10 @@ function game_scene() WIN.scene:remove(curtain) end)) - local world - HEX_MAP, world = random_map() + HEX_MAP, WORLD = random_map() local scene = am.group{ - world, + WORLD, curtain, hex_cursor, toolbelt(), @@ -133,6 +163,10 @@ function game_scene() return scene end +function get_debug_string() + return string.format("%s, %s lang %s\n%s", am.platform, am.version, am.language(), am.perf_stats()) +end + require "texture" load_textures() WIN.scene = am.scale(1) ^ game_scene() diff --git a/src/mob.lua b/src/mob.lua index 57a2280..559a9d2 100644 --- a/src/mob.lua +++ b/src/mob.lua @@ -4,9 +4,7 @@ require "extra" require "sound" function mob_die(mob, entity_index) - WIN.scene"world":action( - am.play(am.sfxr_synth(SOUNDS.EXPLOSION1), false, math.random() + 0.5) - ) + WORLD:action(vplay_sound(SOUNDS.EXPLOSION1)) delete_entity(entity_index) end @@ -21,6 +19,7 @@ function do_hit_mob(mob, damage, index) mob.health = mob.health - damage if mob.health < 1 then + update_score(mob.bounty) mob_die(mob, index) end end @@ -116,14 +115,15 @@ local function make_and_register_mob() else if _mob.hex == HEX_GRID_CENTER then - mob_die(_mob, index) + update_score(-_mob.health) + mob_die(_mob, _mob_index) else log("stuck") end end -- passive animation - if math.random() < 0.01 then + if RAND < 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) @@ -131,9 +131,11 @@ local function make_and_register_mob() end ) - mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER) - mob.health = 10 - mob.speed = 1 + mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER) + mob.health = 10 + mob.speed = 5 + mob.bounty = 5 + mob.hurtbox_radius = 15 end local SPAWN_CHANCE = 50 diff --git a/src/projectile.lua b/src/projectile.lua index b3fd279..957247d 100644 --- a/src/projectile.lua +++ b/src/projectile.lua @@ -1,6 +1,5 @@ - function make_and_register_projectile(hex, vector, velocity) local projectile = make_and_register_entity( -- type @@ -9,25 +8,35 @@ function make_and_register_projectile(hex, vector, velocity) hex, -- node - am.line(vector, vector * 4, 2, COLORS.CLARET), + am.circle(vec2(0), 2, COLORS.CLARET), + -- update function function(_projectile, _projectile_index) _projectile.position = _projectile.position + vector * velocity _projectile.node.position2d = _projectile.position _projectile.hex = pixel_to_hex(_projectile.position) + if not point_in_rect(_projectile.position + WORLDSPACE_COORDINATE_OFFSET, { + x1 = WIN.left, + y1 = WIN.bottom, + x2 = WIN.right, + y2 = WIN.top + }) then + delete_entity(_projectile_index) + end + local mob_index,mob = mob_on_hex(_projectile.hex) - if mob and (math.distance(mob.position, _projectile.position) > _projectile.hitbox_radius) then + if mob and math.distance(mob.position, _projectile.position) > math.abs(_projectile.hitbox_radius - mob.hurtbox_radius) then do_hit_mob(mob, _projectile.damage, mob_index) delete_entity(_projectile_index) - WIN.scene"world":action(am.play(am.sfxr_synth(SOUNDS.HIT1))) + WORLD:action(vplay_sound(SOUNDS.HIT1)) end end ) - projectile.vector = vector - projectile.velocity = velocity - projectile.damage = 5 + projectile.vector = vector + projectile.velocity = velocity + projectile.damage = 5 projectile.hitbox_radius = 10 end diff --git a/src/scratch b/src/scratch deleted file mode 100644 index fbd86f7..0000000 --- a/src/scratch +++ /dev/null @@ -1,5 +0,0 @@ - - -x = y - floor(z/2) - -j + floor(z/2) = j2 diff --git a/src/sound.lua b/src/sound.lua index ee99515..0b55550 100644 --- a/src/sound.lua +++ b/src/sound.lua @@ -14,3 +14,8 @@ SOUNDS = { RANDOM5 = 36680709 } +-- play a sound with variable pitch +function vplay_sound(seed) + return am.play(am.sfxr_synth(seed), false, (math.random() + 0.5)/2) +end + diff --git a/src/tower.lua b/src/tower.lua index fe396df..cde8582 100644 --- a/src/tower.lua +++ b/src/tower.lua @@ -38,11 +38,11 @@ function make_and_register_tower(hex) make_and_register_projectile( _tower.hex, math.normalize(hex_to_pixel(entity.hex) - _tower.position), - 5 + 15 ) _tower.last_shot_time = TIME - _tower.node:action(am.play(am.sfxr_synth(SOUNDS.EXPLOSION3))) + _tower.node:action(vplay_sound(SOUNDS.EXPLOSION3)) end end end