Nicholas Hayashi 4 years ago
parent
commit
f5305e2363
  1. 11
      main.lua
  2. BIN
      res/satelite.png
  3. 6
      sound.lua
  4. 56
      src/grid.lua
  5. 59
      src/mob.lua
  6. 3
      src/projectile.lua
  7. 5
      src/tower.lua
  8. 1
      texture.lua

11
main.lua

@ -72,7 +72,7 @@ local function can_do_build(hex, tile, tower_type)
end end
local function game_action(scene) local function game_action(scene)
if SCORE < 0 then game_end() end
--if SCORE < 0 then game_end() end
TIME = TIME + am.delta_time TIME = TIME + am.delta_time
SCORE = SCORE + am.delta_time SCORE = SCORE + am.delta_time
@ -111,7 +111,12 @@ local function game_action(scene)
TRDT = (TRDT + 1) % #table.keys(TRDTS) TRDT = (TRDT + 1) % #table.keys(TRDTS)
elseif WIN:key_pressed"tab" then elseif WIN:key_pressed"tab" then
select_tower_type((SELECTED_TOWER_TYPE) % #table.keys(TOWER_TYPE) + 1)
local num_of_types = #table.keys(TOWER_TYPE)
if WIN:key_down"lshift" then
select_tower_type((SELECTED_TOWER_TYPE + num_of_types - 2) % num_of_types + 1)
else
select_tower_type((SELECTED_TOWER_TYPE) % num_of_types + 1)
end
elseif WIN:key_pressed"1" then select_tower_type(TOWER_TYPE.REDEYE) elseif WIN:key_pressed"1" then select_tower_type(TOWER_TYPE.REDEYE)
elseif WIN:key_pressed"2" then select_tower_type(2) elseif WIN:key_pressed"2" then select_tower_type(2)
@ -214,7 +219,7 @@ local function toolbelt()
toolbelt:append(tower_select_square) toolbelt:append(tower_select_square)
local tower_type_values = table.values(TOWER_TYPE) local tower_type_values = table.values(TOWER_TYPE)
local keys = { '1', '2', '3', '4', '5', '6', '7', '9', '0', '-', '=' }
local keys = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=' }
for i = 1, #keys do for i = 1, #keys do
if tower_type_values[i] then if tower_type_values[i] then
toolbelt:append( toolbelt:append(

BIN
res/satelite.png

After

Width: 300  |  Height: 300  |  Size: 30 KiB

6
sound.lua

@ -6,7 +6,7 @@ SOUNDS = {
EXPLOSION3 = 69338002, EXPLOSION3 = 69338002,
EXPLOSION4 = 92224102, EXPLOSION4 = 92224102,
COIN1 = 10262800, COIN1 = 10262800,
HIT2 = 25811004,
HIT1 = 39920504,
LASER1 = 79859301, LASER1 = 79859301,
LASER2 = 86914201, LASER2 = 86914201,
PUSH1 = 30455908, PUSH1 = 30455908,
@ -24,8 +24,8 @@ SOUNDS = {
} }
-- play a sound with variable pitch -- play a sound with variable pitch
function vplay_sound(seed)
return am.play(am.sfxr_synth(seed), false, (math.random() + 0.5)/2)
function vplay_sound(seed, range)
return am.play(am.sfxr_synth(seed), false, (math.random() + 0.5)/(range and 1/range or 2))
end end
function play_sound(seed) function play_sound(seed)

56
src/grid.lua

@ -78,8 +78,48 @@ end
function grid_cost(map, from, to) function grid_cost(map, from, to)
local t1, t2 = map.get(from.x, from.y), map.get(to.x, to.y) local t1, t2 = map.get(from.x, from.y), map.get(to.x, to.y)
--local base_cost = math.abs(t1.elevation) * 10
return math.abs(10 * math.abs(t1.elevation)^0.5 - 10 * math.abs(t2.elevation)^0.5)
return 1 + 10 * math.abs(math.abs(t1.elevation)^0.5
- math.abs(t2.elevation)^0.5)
end
function generate_and_apply_flow_field(map, start, world)
local flow_field = dijkstra(map, start, nil, grid_cost)
local overlay_group = am.group():tag"flow_field"
for i,_ in pairs(flow_field) do
for j,f in pairs(flow_field[i]) do
if f then
map[i][j].priority = f.priority
overlay_group:append(am.translate(hex_to_pixel(vec2(i, j)))
^ am.text(string.format("%.1f", f.priority * 10)))
else
-- should fire exactly once per goal hex
log('no priority')
end
end
end
-- dijkstra doesn't set the priority of the center, do it ourselves
map[HEX_GRID_CENTER.x][HEX_GRID_CENTER.y].priority = -1
overlay_group:append(am.translate(hex_to_pixel(vec2(HEX_GRID_CENTER.x, HEX_GRID_CENTER.y)))
^ am.text(string.format("%.1f", -10)))
if world then world:append(overlay_group) end
end
function redraw_flow_field_overlay(flow_field)
local overlay_group = am.group():tag"flow_field"
for i,_ in pairs(flow_field) do
for j,f in pairs(flow_field[i]) do
if f then
overlay_group:append(am.translate(hex_to_pixel(vec2(i, j)))
^ am.text(string.format("%.1f", f.priority * 10)))
else
-- should fire exactly once per goal hex
--log('no priority')
end
end
end
end end
function random_map(seed) function random_map(seed)
@ -127,6 +167,10 @@ function random_map(seed)
node = node node = node
}) })
world:append(node)
end
end
getmetatable(map).__index.neighbours = function(hex) getmetatable(map).__index.neighbours = function(hex)
return table.filter(hex_neighbours(hex), function(_hex) return table.filter(hex_neighbours(hex), function(_hex)
local tile = map.get(_hex.x, _hex.y) local tile = map.get(_hex.x, _hex.y)
@ -134,12 +178,10 @@ function random_map(seed)
end) end)
end end
world:append(node)
end
end
generate_and_apply_flow_field(map, HEX_GRID_CENTER)
world:append(am.translate(hex_to_pixel(HEX_GRID_CENTER))
^ pack_texture_into_sprite(TEX_RADAR1, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y))
--world:append(am.translate(hex_to_pixel(HEX_GRID_CENTER))
-- ^ pack_texture_into_sprite(TEX_SATELLITE, HEX_PIXEL_SIZE.x*2, HEX_PIXEL_SIZE.y*2))
return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world
end end

59
src/mob.lua

@ -84,27 +84,64 @@ local function mob_update(mob, mob_index)
mob.hex = pixel_to_hex(mob.position) mob.hex = pixel_to_hex(mob.position)
if mob.hex == HEX_GRID_CENTER then if mob.hex == HEX_GRID_CENTER then
log('die')
update_score(-mob.health) update_score(-mob.health)
mob_die(mob, mob_index) mob_die(mob, mob_index)
return true return true
end end
local frame_target = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y]
-- frame_target will be false when we are one hex away from the center,
-- or nil if something went wrong
if not frame_target then
frame_target = { hex = HEX_GRID_CENTER, priority = 0 }
-- figure out movement
local frame_target, tile = nil, nil
if mob.path then
log('A*')
-- we have an explicitly stored target
local path_entry = mob.path[mob.hex.x] and mob.path[mob.hex.x][mob.hex.y]
frame_target = path_entry.hex
-- check if our target is valid, and if it's not we aren't going to move this frame.
-- recalculate our path.
if last_frame_hex ~= mob.hex and not mob_can_pass_through(mob, frame_target) then
log('recalc')
mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER)
frame_target = nil
end
else
-- use the map's flow field - gotta find the the best neighbour
local neighbours = HEX_MAP.neighbours(mob.hex)
if #neighbours > 0 then
local first_neighbour = neighbours[1]
tile = HEX_MAP.get(first_neighbour.x, first_neighbour.y)
local lowest_cost_hex = first_neighbour
local lowest_cost = tile.priority or 0
for _,n in pairs(neighbours) do
tile = HEX_MAP.get(n.x, n.y)
local current_cost = tile.priority
if current_cost and current_cost < lowest_cost then
lowest_cost_hex = n
lowest_cost = current_cost
end
end end
if mob_can_pass_through(mob, frame_target.hex) then
frame_target = lowest_cost_hex
else
log('no neighbours')
log(table.tostring(neighbours) .. mob.hex .. mob.position)
end
end
-- do movement
if frame_target then
-- this is supposed to achieve frame rate independence, but i have no idea if it actually does -- this is supposed to achieve frame rate independence, but i have no idea if it actually does
local rate = 1 + mob.speed * (1/frame_target.priority) / PERF_STATS.avg_fps
local rate = 1 + mob.speed / PERF_STATS.avg_fps
mob.position = mob.position + math.normalize(hex_to_pixel(frame_target.hex) - mob.position) * rate
mob.position = mob.position + math.normalize(hex_to_pixel(frame_target) - mob.position) * rate
mob.node.position2d = mob.position mob.node.position2d = mob.position
else else
mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER)
log('no target')
end end
--[[ passive animation --[[ passive animation
@ -123,7 +160,7 @@ local function make_and_register_mob()
mob_update mob_update
) )
mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER)
--mob.path = get_mob_path(mob, HEX_MAP, mob.hex, HEX_GRID_CENTER)
mob.health = 10 mob.health = 10
mob.speed = 100 mob.speed = 100
mob.bounty = 5 mob.bounty = 5

3
src/projectile.lua

@ -63,14 +63,13 @@ function projectile_update(projectile, projectile_index)
-- hit the mob, delete ourselves, affect the world -- hit the mob, delete ourselves, affect the world
do_hit_mob(closest_mob, projectile.damage, closest_mob_index) do_hit_mob(closest_mob, projectile.damage, closest_mob_index)
delete_entity(PROJECTILES, projectile_index) delete_entity(PROJECTILES, projectile_index)
WORLD:action(vplay_sound(SOUNDS.HIT1))
WORLD:action(vplay_sound(SOUNDS.HIT1, 0.5))
end end
function make_and_register_projectile(hex, vector, velocity, damage, hitbox_radius) function make_and_register_projectile(hex, vector, velocity, damage, hitbox_radius)
local projectile = make_basic_entity(hex local projectile = make_basic_entity(hex
, am.line(vector, vector*hitbox_radius, 3, COLORS.CLARET) , am.line(vector, vector*hitbox_radius, 3, COLORS.CLARET)
, projectile_update) , projectile_update)
projectile.vector = vector projectile.vector = vector
projectile.velocity = velocity projectile.velocity = velocity
projectile.damage = damage projectile.damage = damage

5
src/tower.lua

@ -11,8 +11,8 @@ tower(entity) structure:
TOWER_TYPE = { TOWER_TYPE = {
REDEYE = 1, REDEYE = 1,
WALL = 2,
MOAT = 3,
WALL = 11,
MOAT = 12,
} }
function get_tower_texture(tower_type) function get_tower_texture(tower_type)
@ -117,6 +117,7 @@ function make_and_register_tower(hex, tower_type)
-- make this cell impassable -- make this cell impassable
HEX_MAP[hex.x][hex.y].elevation = 2 HEX_MAP[hex.x][hex.y].elevation = 2
generate_and_apply_flow_field(HEX_MAP, HEX_GRID_CENTER)
register_entity(TOWERS, tower) register_entity(TOWERS, tower)
end end

1
texture.lua

@ -10,6 +10,7 @@ function load_textures()
TEX_ARROW = am.texture2d("res/arrow.png") TEX_ARROW = am.texture2d("res/arrow.png")
TEX_RADAR1 = am.texture2d("res/radar.png") TEX_RADAR1 = am.texture2d("res/radar.png")
TEX_SATELLITE = am.texture2d("res/satelite.png")
TEX_WALL_CLOSED = am.texture2d("res/wall_closed.png") TEX_WALL_CLOSED = am.texture2d("res/wall_closed.png")
TEX_MOAT1 = am.texture2d("res/moat1.png") TEX_MOAT1 = am.texture2d("res/moat1.png")
TEX_TOWER1 = am.texture2d("res/tower1.png") TEX_TOWER1 = am.texture2d("res/tower1.png")

Loading…
Cancel
Save