Browse Source

fix some stuff

master
Nicholas Hayashi 4 years ago
parent
commit
ad0ac0e643
  1. BIN
      res/Sprite-0001.aseprite
  2. BIN
      res/gem1.png
  3. BIN
      res/logo.png
  4. 47
      src/game.lua
  5. 5
      src/grid.lua
  6. 5
      src/hexyz.lua
  7. 6
      src/mob.lua
  8. 68
      src/projectile.lua
  9. 5
      src/tower.lua
  10. 1
      texture.lua

BIN
res/Sprite-0001.aseprite

BIN
res/gem1.png

After

Width: 419  |  Height: 483  |  Size: 99 KiB

BIN
res/logo.png

Before

Width: 938  |  Height: 500  |  Size: 30 KiB

After

Width: 905  |  Height: 483  |  Size: 138 KiB

47
src/game.lua

@ -24,17 +24,21 @@ local TRDTS = {
local function get_initial_game_state(seed) local function get_initial_game_state(seed)
local STARTING_MONEY = 10000 local STARTING_MONEY = 10000
local map, world = random_map(seed)
-- 2014
local map, world = random_map(2014)
return { return {
map = map, -- map of hex coords map[x][y] to some stuff at that location map = map, -- map of hex coords map[x][y] to some stuff at that location
world = world, -- the root scene graph node for the game 'world' world = world, -- the root scene graph node for the game 'world'
ui = nil, -- unused, root scene graph node for the 'ui' stuff
perf = {}, -- result of call to am.perf_stats, called every frame perf = {}, -- result of call to am.perf_stats, called every frame
time = 0, -- time since game started in seconds
time = 0, -- real time since game started in seconds
score = 0, -- current game score score = 0, -- current game score
money = STARTING_MONEY, -- current money money = STARTING_MONEY, -- current money
current_wave = 0,
selected_tower_type = false, selected_tower_type = false,
selected_toolbelt_button = 9, selected_toolbelt_button = 9,
selected_top_right_display_type = TRDTS.SEED, selected_top_right_display_type = TRDTS.SEED,
@ -67,10 +71,6 @@ local function get_top_right_display_text(hex, evenq, centered_evenq, display_ty
return str return str
end end
local function handle_left_click(hex, tile, tower_type, toolbelt_button)
end
-- initialized later, as part of the init of the toolbelt -- initialized later, as part of the init of the toolbelt
function select_tower_type(tower_type) end function select_tower_type(tower_type) end
@ -84,27 +84,29 @@ function select_toolbelt_button(i)
end end
function do_day_night_cycle() function do_day_night_cycle()
local tstep = (math.sin(state.time / 100) + 1) * am.delta_time
local tstep = (math.sin(state.time * am.delta_time) + 1) / 100
state.world"negative_mask".color = vec4(tstep){a=1} state.world"negative_mask".color = vec4(tstep){a=1}
end end
local function game_pause() local function game_pause()
WIN.scene"game".paused = true
WIN.scene"game":append(am.group{
WIN.scene("game").paused = true
WIN.scene("game"):append(am.group{
am.rect(WIN.left, WIN.bottom, WIN.right, WIN.top, COLORS.TRANSPARENT), am.rect(WIN.left, WIN.bottom, WIN.right, WIN.top, COLORS.TRANSPARENT),
am.scale(3) am.scale(3)
^ am.text(string.format( ^ am.text(string.format(
"Paused.\nSeed: %d\nEscape to Resume\nf4 to start a new game", state.map.seed "Paused.\nSeed: %d\nEscape to Resume\nf4 to start a new game", state.map.seed
), COLORS.BLACK)
), COLORS.BLACK),
} }
:tag"pause_menu") :tag"pause_menu")
WIN.scene:action(function() WIN.scene:action(function()
if WIN:key_pressed"escape" then
WIN.scene:remove"pause_menu"
WIN.scene"game".paused = false
if WIN:key_pressed("escape") then
WIN.scene:remove("pause_menu")
WIN.scene("game").paused = false
return true return true
elseif WIN:key_pressed"f4" then
elseif WIN:key_pressed("f4") then
game_end() game_end()
return true return true
end end
@ -160,11 +162,19 @@ local function game_action(scene)
end end
end end
if WIN:mouse_pressed"middle" then
state.world"scale".scale2d = vec2(1)
else
local mwd = WIN:mouse_wheel_delta()
state.world"scale".scale = state.world"scale".scale + vec3(mwd, 0) / 100
end
if WIN:key_pressed"escape" then if WIN:key_pressed"escape" then
game_pause() game_pause()
elseif WIN:key_pressed"f1" then elseif WIN:key_pressed"f1" then
state.top_right_display_type = (state.top_right_display_type + 1) % #table.keys(TRDTS)
state.selected_top_right_display_type = (state.selected_top_right_display_type + 1) % #table.keys(TRDTS)
elseif WIN:key_pressed"f2" then elseif WIN:key_pressed"f2" then
state.world"flow_field".hidden = not state.world"flow_field".hidden state.world"flow_field".hidden = not state.world"flow_field".hidden
@ -219,7 +229,7 @@ local function make_game_toolbelt()
register_button_widget("toolbelt_tower_button" .. i register_button_widget("toolbelt_tower_button" .. i
, am.rect(x1, y1, x2, y2) , am.rect(x1, y1, x2, y2)
, function() select_tower_type(i) end)
, function() select_toolbelt_button(i) end)
return am.translate(vec2(size + padding, 0) * i + offset) return am.translate(vec2(size + padding, 0) * i + offset)
^ am.group{ ^ am.group{
@ -332,6 +342,7 @@ local function make_game_toolbelt()
WIN.scene:action(am.play(am.sfxr_synth(SOUNDS.SELECT1), false, 1, SFX_VOLUME)) WIN.scene:action(am.play(am.sfxr_synth(SOUNDS.SELECT1), false, 1, SFX_VOLUME))
else else
-- de-selecting currently selected tower if any
toolbelt("tower_select_square").hidden = true toolbelt("tower_select_square").hidden = true
WIN.scene:replace("cursor", make_hex_cursor(0, COLORS.TRANSPARENT)) WIN.scene:replace("cursor", make_hex_cursor(0, COLORS.TRANSPARENT))
@ -394,9 +405,9 @@ end
function game_init() function game_init()
state = get_initial_game_state() state = get_initial_game_state()
build_tower(HEX_GRID_CENTER, TOWER_TYPE.RADAR)
-- hack to make the center tile passable even though there's a tower on it
build_tower(HEX_GRID_CENTER, TOWER_TYPE.RADAR)
-- @HACK to make the center tile passable even though there's a tower on it
state.map.get(HEX_GRID_CENTER.x, HEX_GRID_CENTER.y).elevation = 0 state.map.get(HEX_GRID_CENTER.x, HEX_GRID_CENTER.y).elevation = 0
WIN.scene:remove("game") WIN.scene:remove("game")

5
src/grid.lua

@ -144,10 +144,10 @@ function random_map(seed)
-- the world's appearance relies largely on a backdrop which can be scaled in -- the world's appearance relies largely on a backdrop which can be scaled in
-- tone to give the appearance of light or darkness -- tone to give the appearance of light or darkness
-- @NOTE replace this with a shader program -- @NOTE replace this with a shader program
-- interestingly, if it's colored white, it almost gives the impression of a winter biome
local neg_mask = am.rect(0, 0, HEX_GRID_PIXEL_WIDTH, HEX_GRID_PIXEL_HEIGHT, COLORS.TRUE_BLACK):tag"negative_mask" local neg_mask = am.rect(0, 0, HEX_GRID_PIXEL_WIDTH, HEX_GRID_PIXEL_HEIGHT, COLORS.TRUE_BLACK):tag"negative_mask"
local world = am.group(neg_mask):tag"world" local world = am.group(neg_mask):tag"world"
local edge_nodes = {}
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))
@ -157,9 +157,6 @@ function random_map(seed)
-- if we're on an edge -- terraform edges to be passable -- if we're on an edge -- terraform edges to be passable
noise = 0 noise = 0
-- it's nice to also store the coords for edge nodes in a separate table for later
table.insert(edge_nodes, vec2(i, j))
elseif j == HEX_GRID_CENTER.y and i == HEX_GRID_CENTER.x then elseif j == HEX_GRID_CENTER.y and i == HEX_GRID_CENTER.x then
-- also terraform the center of the grid to be passable -- also terraform the center of the grid to be passable
-- very infrequently, but still sometimes it is not medium elevation -- very infrequently, but still sometimes it is not medium elevation

5
src/hexyz.lua

@ -292,9 +292,9 @@ function parallelogram_map(width, height, seed)
local seed = seed or math.random(width * height) local seed = seed or math.random(width * height)
local map = {} local map = {}
for i = 0, width do
for i = 0, width - 1 do
map[i] = {} map[i] = {}
for j = 0, height do
for j = 0, height - 1 do
-- Calculate Noise -- Calculate Noise
local idelta = i / width local idelta = i / width
@ -408,6 +408,7 @@ function hexagonal_map(radius, seed)
end end
-- Returns Unordered Rectangular Map of |width| and |height| with Simplex Noise -- Returns Unordered Rectangular Map of |width| and |height| with Simplex Noise
-- @TODO - this doesn't work for pointy orientations
function rectangular_map(width, height, seed) function rectangular_map(width, height, seed)
local seed = seed or math.random(width * height) local seed = seed or math.random(width * height)

6
src/mob.lua

@ -86,7 +86,9 @@ local function get_spawn_hex()
end end
-- @NOTE negate 'y' because hexyz algorithms assume south is positive, in amulet north is positive -- @NOTE negate 'y' because hexyz algorithms assume south is positive, in amulet north is positive
return evenq_to_hex(vec2(x, -y))
local hex = evenq_to_hex(vec2(x, -y))
return hex
end end
local function update_mob(mob, mob_index) local function update_mob(mob, mob_index)
@ -198,7 +200,7 @@ local function make_and_register_mob(mob_type)
return mob return mob
end end
local SPAWN_CHANCE = 25
local SPAWN_CHANCE = 50
function do_mob_spawning() function do_mob_spawning()
--if WIN:key_pressed"space" then --if WIN:key_pressed"space" then
if math.random(SPAWN_CHANCE) == 1 then if math.random(SPAWN_CHANCE) == 1 then

68
src/projectile.lua

@ -7,11 +7,11 @@ PROJECTILE_TYPE = {
LASER = 2, LASER = 2,
} }
PROJECTILE_SPECS = {
local PROJECTILE_SPECS = {
[PROJECTILE_TYPE.SHELL] = { [PROJECTILE_TYPE.SHELL] = {
velocity = 13, velocity = 13,
damage = 20, damage = 20,
hitbox_radius = 3
hitbox_radius = 20
}, },
[PROJECTILE_TYPE.LASER] = { [PROJECTILE_TYPE.LASER] = {
velocity = 25, velocity = 25,
@ -20,7 +20,6 @@ PROJECTILE_SPECS = {
}, },
} }
function get_projectile_velocity(projectile_type) function get_projectile_velocity(projectile_type)
return PROJECTILE_SPECS[projectile_type].velocity return PROJECTILE_SPECS[projectile_type].velocity
end end
@ -34,17 +33,41 @@ function get_projectile_spec(projectile_type)
return PROJECTILE_SPECS[projectile_type] return PROJECTILE_SPECS[projectile_type]
end end
local function make_shell_explosion_node(source_position)
return am.particles2d{
source_pos = source_position,
source_pos_var = vec2(4),
start_size = 2,
start_size_var = 1,
end_size = 0,
end_size_var = 0,
angle = 0,
angle_var = math.pi,
speed = 25,
speed_var = 15,
life = 10,
life_var = 1,
start_color = COLORS.VERY_DARK_GRAY,
start_color_var = vec4(0.2),
end_color = vec4(0),
end_color_var = vec4(0.1),
emission_rate = 100,
start_particles = 150,
max_particles = 150,
gravity = vec2(0, -10),
warmup_time = 1
}
:action(coroutine.create(function(self)
am.wait(am.delay(3))
end))
end
local function update_projectile_shell(projectile, projectile_index) local function update_projectile_shell(projectile, projectile_index)
projectile.position = projectile.position + projectile.vector * projectile.velocity projectile.position = projectile.position + projectile.vector * projectile.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)
projectile.props.z = projectile.props.z - 0.6 * am.delta_time
if projectile.props.z <= 0 then
log('exploded cuz we hit da grund')
delete_entity(PROJECTILES, projectile_index)
return true
end
projectile.props.z = projectile.props.z - 0.6 * am.delta_time
-- check if we hit something -- check if we hit something
-- get a list of hexes that could have something we could hit on them -- get a list of hexes that could have something we could hit on them
@ -52,21 +75,40 @@ local function update_projectile_shell(projectile, projectile_index)
-- this is done to avoid having to check every mob on screen, though maybe it's not necessary. -- this is done to avoid having to check every mob on screen, though maybe it's not necessary.
local do_explode = false local do_explode = false
local search_hexes = spiral_map(projectile.hex, 1) local search_hexes = spiral_map(projectile.hex, 1)
local mobs = {}
for _,hex in pairs(search_hexes) do for _,hex in pairs(search_hexes) do
for mob_index,mob in pairs(mobs_on_hex(hex)) do for mob_index,mob in pairs(mobs_on_hex(hex)) do
if mob and circles_intersect(mob.position
if mob then
table.insert(mobs, mob_index, mob)
if circles_intersect(mob.position
, projectile.position , projectile.position
, mob.hurtbox_radius , mob.hurtbox_radius
, projectile.hitbox_radius) then , projectile.hitbox_radius) then
log('exploded cuz we hit a boi')
do_explode = true do_explode = true
break
-- we don't break here because if we hit a mob we have to collect all the mobs on the hexes in the search space anyway
end
end end
end end
end end
local tile = state.map.get(projectile.hex.x, projectile.hex.y)
if tile and tile.elevation >= projectile.props.z then
log('we exploded cuz we hit something toll')
do_explode = true
elseif projectile.props.z <= 0 then
log('exploded cuz we hit da grund')
do_explode = true
end
if do_explode then if do_explode then
log('exploded cuz we hit a boi')
log(#mobs)
for index,mob in pairs(mobs) do
do_hit_mob(mob, 1 / math.distance(mob.position, projectile.position) * projectile.damage, index)
end
WIN.scene:append(make_shell_explosion_node(projectile.position))
delete_entity(PROJECTILES, projectile_index) delete_entity(PROJECTILES, projectile_index)
return true return true
end end

5
src/tower.lua

@ -321,7 +321,10 @@ function update_tower_howitzer(tower, tower_index)
math.normalize(mob.position - tower.position) math.normalize(mob.position - tower.position)
) )
projectile.props.z = tower.props.z
-- @HACK, the projectile will explode if it encounters something taller than it,
-- but the tower it spawns on quickly becomes taller than it, so we just pad it
-- if it's not enough the shell explodes before it leaves its spawning hex
projectile.props.z = tower.props.z + 0.1
tower.last_shot_time = state.time tower.last_shot_time = state.time
play_sfx(SOUNDS.EXPLOSION2) play_sfx(SOUNDS.EXPLOSION2)

1
texture.lua

@ -11,6 +11,7 @@ end
TEXTURES = { TEXTURES = {
LOGO = load_texture("res/logo.png"), LOGO = load_texture("res/logo.png"),
GEM1 = load_texture("res/gem1.png"),
BUTTON1 = load_texture("res/button1.png"), BUTTON1 = load_texture("res/button1.png"),
WIDER_BUTTON1 = load_texture("res/wider_button1.png"), WIDER_BUTTON1 = load_texture("res/wider_button1.png"),

Loading…
Cancel
Save