|
@ -11,7 +11,7 @@ mob(entity) structure: |
|
|
--]] |
|
|
--]] |
|
|
|
|
|
|
|
|
MAX_MOB_SIZE = hex_height(HEX_SIZE, ORIENTATION.FLAT) / 2 |
|
|
MAX_MOB_SIZE = hex_height(HEX_SIZE, ORIENTATION.FLAT) / 2 |
|
|
MOB_SIZE = MAX_MOB_SIZE/2 |
|
|
|
|
|
|
|
|
MOB_SIZE = MAX_MOB_SIZE |
|
|
|
|
|
|
|
|
function mobs_on_hex(hex) |
|
|
function mobs_on_hex(hex) |
|
|
local t = {} |
|
|
local t = {} |
|
@ -37,7 +37,7 @@ function mob_can_pass_through(mob, hex) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
function mob_die(mob, mob_index) |
|
|
function mob_die(mob, mob_index) |
|
|
WORLD:action(vplay_sound(SOUNDS.EXPLOSION1)) |
|
|
|
|
|
|
|
|
vplay_sfx(SOUNDS.EXPLOSION1) |
|
|
delete_entity(MOBS, mob_index) |
|
|
delete_entity(MOBS, mob_index) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
@ -45,6 +45,7 @@ function do_hit_mob(mob, damage, mob_index) |
|
|
mob.health = mob.health - damage |
|
|
mob.health = mob.health - damage |
|
|
if mob.health <= 0 then |
|
|
if mob.health <= 0 then |
|
|
update_score(mob.bounty) |
|
|
update_score(mob.bounty) |
|
|
|
|
|
update_money(mob.bounty) |
|
|
mob_die(mob, mob_index) |
|
|
mob_die(mob, mob_index) |
|
|
end |
|
|
end |
|
|
end |
|
|
end |
|
@ -79,90 +80,97 @@ local function get_spawn_hex() |
|
|
return evenq_to_hex(vec2(x, -y)) |
|
|
return evenq_to_hex(vec2(x, -y)) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
local function mob_update(mob, mob_index) |
|
|
|
|
|
|
|
|
local function update_mob(mob, mob_index) |
|
|
local last_frame_hex = mob.hex |
|
|
local last_frame_hex = mob.hex |
|
|
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 |
|
|
|
|
|
|
|
|
-- figure out movement |
|
|
-- 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 |
|
|
|
|
|
|
|
|
if last_frame_hex ~= mob.hex or not mob.frame_target then |
|
|
|
|
|
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] |
|
|
|
|
|
mob.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) |
|
|
|
|
|
mob.frame_target = nil |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
frame_target = lowest_cost_hex |
|
|
|
|
|
else |
|
|
else |
|
|
log('no neighbours') |
|
|
|
|
|
log(table.tostring(neighbours) .. mob.hex .. mob.position) |
|
|
|
|
|
|
|
|
-- 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 |
|
|
|
|
|
|
|
|
|
|
|
mob.frame_target = lowest_cost_hex |
|
|
|
|
|
else |
|
|
|
|
|
log('no neighbours') |
|
|
|
|
|
end |
|
|
end |
|
|
end |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
if mob.frame_target and mob.frame_target == last_frame_hex then |
|
|
|
|
|
log('backpedaling') |
|
|
|
|
|
log(mob.frame_target) |
|
|
|
|
|
log(mob.hex) |
|
|
|
|
|
log(last_frame_hex) |
|
|
|
|
|
--WIN.scene.paused = true |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
-- do movement |
|
|
-- do movement |
|
|
if frame_target then |
|
|
|
|
|
|
|
|
if mob.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 / PERF_STATS.avg_fps |
|
|
|
|
|
|
|
|
-- the constant multiplier at the beginning is how many pixels we want a mob with speed 1 to move in one frame |
|
|
|
|
|
local rate = 4 * mob.speed / PERF_STATS.avg_fps |
|
|
|
|
|
|
|
|
mob.position = mob.position + math.normalize(hex_to_pixel(frame_target) - mob.position) * rate |
|
|
|
|
|
|
|
|
mob.position = mob.position + math.normalize(hex_to_pixel(mob.frame_target) - mob.position) * rate |
|
|
mob.node.position2d = mob.position |
|
|
mob.node.position2d = mob.position |
|
|
else |
|
|
else |
|
|
log('no target') |
|
|
log('no target') |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
--[[ passive animation |
|
|
|
|
|
|
|
|
-- passive animation |
|
|
if math.random() < 0.01 then |
|
|
if math.random() < 0.01 then |
|
|
mob.node"rotate":action(am.tween(0.3, { angle = mob.node"rotate".angle + math.pi*3 })) |
|
|
mob.node"rotate":action(am.tween(0.3, { angle = mob.node"rotate".angle + math.pi*3 })) |
|
|
else |
|
|
else |
|
|
mob.node"rotate".angle = math.wrapf(mob.node"rotate".angle + am.delta_time, math.pi*2) |
|
|
mob.node"rotate".angle = math.wrapf(mob.node"rotate".angle + am.delta_time, math.pi*2) |
|
|
end |
|
|
end |
|
|
--]] |
|
|
|
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
local function make_and_register_mob() |
|
|
|
|
|
|
|
|
local function make_and_register_mob(mob_type) |
|
|
local mob = make_basic_entity( |
|
|
local mob = make_basic_entity( |
|
|
get_spawn_hex(), |
|
|
get_spawn_hex(), |
|
|
am.circle(vec2(0), MOB_SIZE, COLORS.SUNRAY), |
|
|
|
|
|
mob_update |
|
|
|
|
|
|
|
|
am.rotate(TIME) ^ pack_texture_into_sprite(TEX_MOB_BEEPER, MOB_SIZE, MOB_SIZE), |
|
|
|
|
|
update_mob |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
--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 = 10 |
|
|
mob.bounty = 5 |
|
|
mob.bounty = 5 |
|
|
mob.hurtbox_radius = MOB_SIZE |
|
|
mob.hurtbox_radius = MOB_SIZE |
|
|
|
|
|
|
|
|