Browse Source

thing

master
Nicholas Hayashi 4 years ago
parent
commit
6b6e0d958a
  1. 30
      src/entity.lua
  2. 7
      src/grid.lua
  3. 0
      src/log.txt
  4. 66
      src/main.lua
  5. 18
      src/mob.lua
  6. 23
      src/projectile.lua
  7. 5
      src/scratch
  8. 5
      src/sound.lua
  9. 4
      src/tower.lua

30
src/entity.lua

@ -1,9 +1,10 @@
ENTITY_TYPE = { ENTITY_TYPE = {
ENTITY = 0,
MOB = 1,
TOWER = 2,
PROJECTILE = 3
ENTITY = 0,
MOB = 1,
TOWER = 2,
PROJECTILE = 3
} }
ENTITIES = {} ENTITIES = {}
@ -21,6 +22,8 @@ ENTITIES = {}
-- { -- {
-- path - 2d table - map of hexes to other hexes, forms a path -- 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 -- 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: -- tower(entity) structure:
@ -33,6 +36,10 @@ ENTITIES = {}
-- --
-- bullet/projectile structure -- 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) 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 entity.node = am.translate(entity.position) ^ node
table.insert(ENTITIES, entity) table.insert(ENTITIES, entity)
WIN.scene"world":append(entity.node)
WORLD:append(entity.node)
return entity return entity
end end
function delete_all_entities()
for index,entity in pairs(ENTITIES) do
delete_entity(index)
end
ENTITIES = {}
end
function delete_entity(index) 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 end
function do_entity_updates() function do_entity_updates()
@ -61,4 +76,3 @@ function do_entity_updates()
end end
end end

7
src/grid.lua

@ -29,8 +29,10 @@ local function grid_pixel_dimensions()
end end
GRID_PIXEL_DIMENSIONS = grid_pixel_dimensions() 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) function is_interactable(tile, evenq)
return point_in_rect(evenq, { return point_in_rect(evenq, {
x1 = HEX_GRID_INTERACTABLE_REGION_PADDING, 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) local map = rectangular_map(HEX_GRID_DIMENSIONS.x, HEX_GRID_DIMENSIONS.y, seed)
math.randomseed(map.seed) math.randomseed(map.seed)
local world = am.group():tag"world"
local world = am.group()
for i,_ in pairs(map) do for i,_ in pairs(map) do
for j,noise in pairs(map[i]) do for j,noise in pairs(map[i]) do
local evenq = hex_to_evenq(vec2(i, j)) 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)) 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) return map, am.translate(WORLDSPACE_COORDINATE_OFFSET)
^ world:tag"world" ^ world:tag"world"
end end

0
src/log.txt

66
src/main.lua

@ -13,13 +13,20 @@ require "projectile"
require "tower" require "tower"
-- Globals -- 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 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 = { local COORDINATE_DISPLAY_TYPES = {
CENTERED_EVENQ = 0, CENTERED_EVENQ = 0,
@ -29,20 +36,23 @@ local COORDINATE_DISPLAY_TYPES = {
local COORDINATE_DISPLAY_TYPE = COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ local COORDINATE_DISPLAY_TYPE = COORDINATE_DISPLAY_TYPES.CENTERED_EVENQ
local function game_action(scene) 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)) , math.floor(HEX_GRID_HEIGHT/2))
local tile = HEX_MAP.get(hex.x, hex.y) local tile = HEX_MAP.get(hex.x, hex.y)
local hot = is_interactable(tile, evenq{ y = -evenq.y }) local hot = is_interactable(tile, evenq{ y = -evenq.y })
do_mob_spawning()
do_entity_updates() do_entity_updates()
do_mob_spawning()
if WIN:mouse_pressed"left" then if WIN:mouse_pressed"left" then
if hot and is_buildable(hex, tile, nil) then if hot and is_buildable(hex, tile, nil) then
@ -51,6 +61,9 @@ local function game_action(scene)
end end
if WIN:key_pressed"escape" then if WIN:key_pressed"escape" then
pause()
elseif WIN:key_pressed"f2" then
WIN.scene = game_scene() WIN.scene = game_scene()
elseif WIN:key_pressed"f3" then elseif WIN:key_pressed"f3" then
@ -84,6 +97,24 @@ local function game_action(scene)
end end
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 function toolbelt()
local toolbelt_height = hex_height(HEX_SIZE) * 2 local toolbelt_height = hex_height(HEX_SIZE) * 2
local toolbelt = am.group{ local toolbelt = am.group{
@ -116,11 +147,10 @@ function game_scene()
WIN.scene:remove(curtain) WIN.scene:remove(curtain)
end)) end))
local world
HEX_MAP, world = random_map()
HEX_MAP, WORLD = random_map()
local scene = am.group{ local scene = am.group{
world,
WORLD,
curtain, curtain,
hex_cursor, hex_cursor,
toolbelt(), toolbelt(),
@ -133,6 +163,10 @@ function game_scene()
return scene return scene
end 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" require "texture"
load_textures() load_textures()
WIN.scene = am.scale(1) ^ game_scene() WIN.scene = am.scale(1) ^ game_scene()

18
src/mob.lua

@ -4,9 +4,7 @@ require "extra"
require "sound" require "sound"
function mob_die(mob, entity_index) 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) delete_entity(entity_index)
end end
@ -21,6 +19,7 @@ function do_hit_mob(mob, damage, index)
mob.health = mob.health - damage mob.health = mob.health - damage
if mob.health < 1 then if mob.health < 1 then
update_score(mob.bounty)
mob_die(mob, index) mob_die(mob, index)
end end
end end
@ -116,14 +115,15 @@ local function make_and_register_mob()
else else
if _mob.hex == HEX_GRID_CENTER then if _mob.hex == HEX_GRID_CENTER then
mob_die(_mob, index)
update_score(-_mob.health)
mob_die(_mob, _mob_index)
else else
log("stuck") log("stuck")
end end
end end
-- passive animation -- 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 })) _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)
@ -131,9 +131,11 @@ local function make_and_register_mob()
end 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 end
local SPAWN_CHANCE = 50 local SPAWN_CHANCE = 50

23
src/projectile.lua

@ -1,6 +1,5 @@
function make_and_register_projectile(hex, vector, velocity) function make_and_register_projectile(hex, vector, velocity)
local projectile = make_and_register_entity( local projectile = make_and_register_entity(
-- type -- type
@ -9,25 +8,35 @@ function make_and_register_projectile(hex, vector, velocity)
hex, hex,
-- node -- node
am.line(vector, vector * 4, 2, COLORS.CLARET),
am.circle(vec2(0), 2, COLORS.CLARET),
-- update function
function(_projectile, _projectile_index) function(_projectile, _projectile_index)
_projectile.position = _projectile.position + vector * velocity _projectile.position = _projectile.position + vector * velocity
_projectile.node.position2d = _projectile.position _projectile.node.position2d = _projectile.position
_projectile.hex = pixel_to_hex(_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) 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) do_hit_mob(mob, _projectile.damage, mob_index)
delete_entity(_projectile_index) delete_entity(_projectile_index)
WIN.scene"world":action(am.play(am.sfxr_synth(SOUNDS.HIT1)))
WORLD:action(vplay_sound(SOUNDS.HIT1))
end end
end end
) )
projectile.vector = vector
projectile.velocity = velocity
projectile.damage = 5
projectile.vector = vector
projectile.velocity = velocity
projectile.damage = 5
projectile.hitbox_radius = 10 projectile.hitbox_radius = 10
end end

5
src/scratch

@ -1,5 +0,0 @@
x = y - floor(z/2)
j + floor(z/2) = j2

5
src/sound.lua

@ -14,3 +14,8 @@ SOUNDS = {
RANDOM5 = 36680709 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

4
src/tower.lua

@ -38,11 +38,11 @@ function make_and_register_tower(hex)
make_and_register_projectile( make_and_register_projectile(
_tower.hex, _tower.hex,
math.normalize(hex_to_pixel(entity.hex) - _tower.position), math.normalize(hex_to_pixel(entity.hex) - _tower.position),
5
15
) )
_tower.last_shot_time = TIME _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 end
end end

Loading…
Cancel
Save