Browse Source

fix buggies

master
Nicholas Hayashi 4 years ago
parent
commit
6620215d43
  1. BIN
      .DS_Store
  2. 12
      NOTES.md
  3. 39
      main.lua
  4. BIN
      res/arrow.png
  5. 0
      res/cells.jpg
  6. BIN
      res/marquis.png
  7. 0
      res/mob_beeper.png
  8. BIN
      res/radar.aseprite
  9. BIN
      res/tab_icon.zip
  10. BIN
      res/tab_icon/Tab-02.eps
  11. BIN
      res/tab_icon/Tab-02.jpg
  12. BIN
      res/tab_icon/Tab-02.png
  13. 11
      res/tab_icon/Tab-02.svg
  14. BIN
      res/tower1.png
  15. BIN
      res/tower2.png
  16. BIN
      res/tower_lighthouse.png
  17. 0
      res/tower_moat.png
  18. BIN
      res/tower_redeye.png
  19. BIN
      res/tower_wall.aseprite
  20. BIN
      res/tower_wall.png
  21. BIN
      res/wall_closed.png
  22. BIN
      res/wall_open.png
  23. 11
      sound.lua
  24. 30
      src/extra.lua
  25. 1
      src/game.lua
  26. 28
      src/grid.lua
  27. 108
      src/mob.lua
  28. 6
      src/projectile.lua
  29. 49
      src/tower.lua
  30. 12
      src/tower_spec.luaa
  31. 18
      texture.lua

BIN
.DS_Store

12
NOTES.md

@ -10,14 +10,16 @@ MAP RESOURCES
towers:
1 - redeye
- redeye
long-range laser tower
only buildable on mountains and upgraded walls
upgrades:
???
- lighthouse
light-emitting static tower
only buildable on tiles adjacent to water
mobs strongly prefer to path around lighthouses
-1 - wall
- wall
some fraction of the height of the tallest mountain
makes mob pathing more difficult
@ -25,7 +27,7 @@ towers:
- fortifications - lets you build some qualifying towers on top of this tower
- spikes - mobs take damage when climbing
-2 - moat
- moat
some fraction of the depth of the deepest lake
makes mob pathing more difficult

39
main.lua

@ -36,10 +36,11 @@ PERF_STATS = false -- result of am.perf_stats() -- should be calle
WORLD = false -- root scene node of everything considered to be in the game world
-- aka non gui stuff
TIME = 0 -- runtime of the current game in seconds (not whole program runtime)
SCORE = 0 -- score of the player
MONEY = 0 -- available resources
MOUSE = false -- position of the mouse at the start of every frame, if an action is tracking it
TIME = 0 -- runtime of the current game in seconds (not whole program runtime)
SCORE = 0 -- score of the player
STARTING_MONEY = 50
MONEY = STARTING_MONEY -- available resources
MOUSE = false -- position of the mouse at the start of every frame, if an action is tracking it
-- global audio settings
MUSIC_VOLUME = 0.1
@ -68,7 +69,7 @@ local function select_hex(hex)
end
local function can_do_build(hex, tile, tower_type)
return tower_is_buildable_on(hex, tile, SELECTED_TOWER_TYPE)
return can_afford_tower(MONEY, tower_type) and tower_is_buildable_on(hex, tile, tower_type)
end
local function game_action(scene)
@ -105,7 +106,14 @@ local function game_action(scene)
end
if WIN:key_pressed"escape" then
game_end()
WIN.scene"game".paused = true
WIN.scene:action(function()
if WIN:key_pressed"escape" then
WIN.scene"game".paused = false
return true
end
end)
--game_end()
elseif WIN:key_pressed"f1" then
TRDT = (TRDT + 1) % #table.keys(TRDTS)
@ -171,26 +179,30 @@ local function game_action(scene)
end
function do_day_night_cycle()
local tstep = (math.sin(TIME) / PERF_STATS.avg_fps + 1)/8
WORLD"negative_mask".color = vec4(tstep)
local slow = 100
local tstep = (math.sin(TIME / 100) + 1) / PERF_STATS.avg_fps
WORLD"negative_mask".color = vec4(tstep){a=1}
end
function game_end()
-- de-initialize stuff
delete_all_entities()
TIME = 0
SCORE = 0
MONEY = 0
MONEY = STARTING_MONEY
WORLD = false
WIN.scene = am.scale(1) ^ game_scene()
WIN.scene = am.group(am.scale(1) ^ game_scene())
end
function update_score(diff)
SCORE = SCORE + diff
end
function update_money(diff)
MONEY = MONEY + diff
end
local function toolbelt()
local toolbelt_height = hex_height(HEX_SIZE) * 2
local tower_tooltip = am.translate(WIN.left + 10, WIN.bottom + toolbelt_height + 20)
@ -283,6 +295,7 @@ function game_scene()
WIN.scene:remove(curtain)
end))
-- 2227
HEX_MAP, WORLD = random_map()
local scene = am.group{
@ -293,7 +306,7 @@ function game_scene()
score,
money,
coords,
}
}:tag"game"
scene:action(game_action)
--scene:action(am.play(SOUNDS.TRACK1))
@ -302,6 +315,6 @@ function game_scene()
end
load_textures()
WIN.scene = am.scale(vec2(1)) ^ game_scene()
WIN.scene = am.group(am.scale(vec2(1)) ^ game_scene())
noglobals()

BIN
res/arrow.png

Before

Width: 46  |  Height: 58  |  Size: 518 B

0
res/077-8332_001.jpg → res/cells.jpg

Before

Width: 2000  |  Height: 2000  |  Size: 716 KiB

After

Width: 2000  |  Height: 2000  |  Size: 716 KiB

BIN
res/marquis.png

Before

Width: 306  |  Height: 40  |  Size: 452 B

0
res/mob1_1.png → res/mob_beeper.png

Before

Width: 638  |  Height: 639  |  Size: 6.1 KiB

After

Width: 638  |  Height: 639  |  Size: 6.1 KiB

BIN
res/radar.aseprite

BIN
res/tab_icon.zip

BIN
res/tab_icon/Tab-02.eps

BIN
res/tab_icon/Tab-02.jpg

Before

Width: 512  |  Height: 512  |  Size: 32 KiB

BIN
res/tab_icon/Tab-02.png

Before

Width: 512  |  Height: 512  |  Size: 3.8 KiB

11
res/tab_icon/Tab-02.svg

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g id="XMLID_1_">
<rect id="XMLID_3_" x="480.3" width="31.7" height="256"/>
<rect id="XMLID_4_" y="256" width="31.7" height="256"/>
<polygon id="XMLID_5_" points="160.1,351.9 512,351.9 512,416.1 160.1,416.1 160.1,496.2 48.4,384.5 160.1,271.8 "/>
<polygon id="XMLID_6_" points="351.9,160.1 0,160.1 0,95.9 351.9,95.9 351.9,15.8 463.6,128.5 351.9,240.2 "/>
</g>
</svg>

BIN
res/tower1.png

Before

Width: 137  |  Height: 137  |  Size: 2.5 KiB

BIN
res/tower2.png

Before

Width: 32  |  Height: 32  |  Size: 487 B

BIN
res/tower_lighthouse.png

After

Width: 64  |  Height: 64  |  Size: 934 B

0
res/moat1.png → res/tower_moat.png

Before

Width: 137  |  Height: 137  |  Size: 1.8 KiB

After

Width: 137  |  Height: 137  |  Size: 1.8 KiB

BIN
res/tower_redeye.png

After

Width: 64  |  Height: 64  |  Size: 640 B

BIN
res/tower_wall.aseprite

BIN
res/tower_wall.png

After

Width: 100  |  Height: 88  |  Size: 2.0 KiB

BIN
res/wall_closed.png

Before

Width: 100  |  Height: 88  |  Size: 1.9 KiB

BIN
res/wall_open.png

Before

Width: 137  |  Height: 137  |  Size: 1.8 KiB

11
sound.lua

@ -23,12 +23,13 @@ SOUNDS = {
TRACK1 = am.track(am.load_audio("res/track1.ogg"), true, 1, 0.1)
}
-- play a sound with variable pitch
function vplay_sound(seed, range)
return am.play(am.sfxr_synth(seed), false, (math.random() + 0.5)/(range and 1/range or 2))
-- play sound effect with variable pitch
function vplay_sfx(sound, pitch_range)
local pitch = (math.random() + 0.5)/(pitch_range and 1/pitch_range or 2)
WIN.scene:action(am.play(sound, false, pitch, SFX_VOLUME))
end
function play_sound(seed)
return am.play(am.sfxr_synth(seed), false)
function play_sfx(sound)
WIN.scene:action(am.play(sound, false, 1, SFX_VOLUME))
end

30
src/extra.lua

@ -24,3 +24,33 @@ function table.find(t, predicate)
return nil
end
function quicksort(t, low_index, high_index, comparator)
local function partition(t, low_index, high_index)
local i = low_index - 1
local pivot = t[high_index]
for j = low_index, high_index - 1 do
if comparator(t[j], t[pivot]) <= 0 then
i = i + 1
t[i], t[j] = t[j], t[i]
end
end
t[i + 1], t[high_index] = t[high_index], t[i + 1]
return i + 1
end
if #t == 1 then
return t
end
if comparator(t[low_index], t[high_index]) < 0 then
local partition_index = partition(t, low_index, high_index)
quicksort(t, low_index, partition_index - 1, comparator)
quicksort(t, partition_index + 1, high_index, comparator)
end
return t
end

1
src/tower_spec.lua → src/game.lua

@ -1 +1,2 @@

28
src/grid.lua

@ -2,8 +2,10 @@
-- distance from hex centerpoint to any vertex
HEX_SIZE = 20
HEX_PIXEL_SIZE = vec2(hex_width(HEX_SIZE, ORIENTATION.FLAT)
, hex_height(HEX_SIZE, ORIENTATION.FLAT))
HEX_PIXEL_WIDTH = hex_width(HEX_SIZE, ORIENTATION.FLAT)
HEX_PIXEL_HEIGHT = hex_height(HEX_SIZE, ORIENTATION.FLAT)
HEX_PIXEL_DIMENSIONS = vec2(HEX_PIXEL_WIDTH, HEX_PIXEL_HEIGHT)
-- with 1920x1080, this is the minimal dimensions to cover the screen (65x33)
-- @NOTE added 2 cell padding, because we terraform the very outer edge and it looks ugly
@ -17,6 +19,9 @@ HEX_GRID_CENTER = vec2(math.floor(HEX_GRID_WIDTH/2)
, 0)
-- math.floor(HEX_GRID_HEIGHT/2))
HEX_GRID_MINIMUM_ELEVATION = -1
HEX_GRID_MAXIMUM_ELEVATION = 1
-- index is hex coordinates [x][y]
-- { { elevation, node, etc. } }
HEX_MAP = {}
@ -78,8 +83,9 @@ end
function grid_cost(map, from, to)
local t1, t2 = map.get(from.x, from.y), map.get(to.x, to.y)
return 1 + 10 * math.abs(math.abs(t1.elevation)^0.5
- math.abs(t2.elevation)^0.5)
local epsilon = HEX_GRID_MAXIMUM_ELEVATION - HEX_GRID_MINIMUM_ELEVATION
return epsilon + 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)
@ -94,7 +100,7 @@ function generate_and_apply_flow_field(map, start, world)
^ am.text(string.format("%.1f", f.priority * 10)))
else
-- should fire exactly once per goal hex
log('no priority')
--log('no priority')
end
end
end
@ -135,14 +141,14 @@ function random_map(seed)
for j,noise in pairs(map[i]) do
local evenq = hex_to_evenq(vec2(i, j))
-- check if we're on an edge -- terraform edges to be passable
if evenq.x == 0 or evenq.x == (HEX_GRID_WIDTH - 1)
or -evenq.y == 0 or -evenq.y == (HEX_GRID_HEIGHT - 1) then
-- if we're on an edge -- terraform edges to be passable
noise = 0
-- also terraform the center of the grid to be passable
-- very infrequently, but still sometimes it is not medium elevation
elseif i == HEX_GRID_CENTER.x and j == HEX_GRID_CENTER.y then
-- also terraform the center of the grid to be passable
-- very infrequently, but still sometimes it is not medium elevation
noise = 0
else
@ -178,10 +184,10 @@ function random_map(seed)
end)
end
generate_and_apply_flow_field(map, HEX_GRID_CENTER)
generate_and_apply_flow_field(map, HEX_GRID_CENTER, world)
--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))
world:append(am.translate(hex_to_pixel(HEX_GRID_CENTER))
^ pack_texture_into_sprite(TEX_SATELLITE, HEX_PIXEL_WIDTH, HEX_PIXEL_HEIGHT))
return map, am.translate(WORLDSPACE_COORDINATE_OFFSET) ^ world
end

108
src/mob.lua

@ -11,7 +11,7 @@ mob(entity) structure:
--]]
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)
local t = {}
@ -37,7 +37,7 @@ function mob_can_pass_through(mob, hex)
end
function mob_die(mob, mob_index)
WORLD:action(vplay_sound(SOUNDS.EXPLOSION1))
vplay_sfx(SOUNDS.EXPLOSION1)
delete_entity(MOBS, mob_index)
end
@ -45,6 +45,7 @@ function do_hit_mob(mob, damage, mob_index)
mob.health = mob.health - damage
if mob.health <= 0 then
update_score(mob.bounty)
update_money(mob.bounty)
mob_die(mob, mob_index)
end
end
@ -79,90 +80,97 @@ local function get_spawn_hex()
return evenq_to_hex(vec2(x, -y))
end
local function mob_update(mob, mob_index)
local function update_mob(mob, mob_index)
local last_frame_hex = mob.hex
mob.hex = pixel_to_hex(mob.position)
if mob.hex == HEX_GRID_CENTER then
log('die')
update_score(-mob.health)
mob_die(mob, mob_index)
return true
end
-- 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
frame_target = lowest_cost_hex
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
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
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
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
else
log('no target')
end
--[[ passive animation
-- passive animation
if math.random() < 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)
end
--]]
end
local function make_and_register_mob()
local function make_and_register_mob(mob_type)
local mob = make_basic_entity(
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.health = 10
mob.speed = 100
mob.speed = 10
mob.bounty = 5
mob.hurtbox_radius = MOB_SIZE

6
src/projectile.lua

@ -10,7 +10,7 @@ bullet/projectile(entity) structure
}
--]]
function projectile_update(projectile, projectile_index)
function update_projectile(projectile, projectile_index)
projectile.position = projectile.position + projectile.vector * projectile.velocity
projectile.node.position2d = projectile.position
projectile.hex = pixel_to_hex(projectile.position)
@ -63,13 +63,13 @@ function projectile_update(projectile, projectile_index)
-- hit the mob, delete ourselves, affect the world
do_hit_mob(closest_mob, projectile.damage, closest_mob_index)
delete_entity(PROJECTILES, projectile_index)
WORLD:action(vplay_sound(SOUNDS.HIT1, 0.5))
vplay_sfx(SOUNDS.HIT1, 0.5)
end
function make_and_register_projectile(hex, vector, velocity, damage, hitbox_radius)
local projectile = make_basic_entity(hex
, am.line(vector, vector*hitbox_radius, 3, COLORS.CLARET)
, projectile_update)
, update_projectile)
projectile.vector = vector
projectile.velocity = velocity
projectile.damage = damage

49
src/tower.lua

@ -11,14 +11,30 @@ tower(entity) structure:
TOWER_TYPE = {
REDEYE = 1,
WALL = 11,
MOAT = 12,
WALL = 2,
MOAT = 3,
}
function get_tower_build_cost(tower_type)
if tower_type == TOWER_TYPE.REDEYE then return 25
elseif tower_type == TOWER_TYPE.WALL then return 5
elseif tower_type == TOWER_TYPE.MOAT then return 15
end
end
function can_afford_tower(money, tower_type)
local cost = get_tower_build_cost(tower_type)
if tower_type == TOWER_TYPE.REDEYE then return (money - cost) > 0
elseif tower_type == TOWER_TYPE.WALL then return (money - cost) > 0
elseif tower_type == TOWER_TYPE.MOAT then return (money - cost) > 0
end
end
function get_tower_texture(tower_type)
if tower_type == TOWER_TYPE.REDEYE then return TEX_TOWER2
elseif tower_type == TOWER_TYPE.WALL then return TEX_WALL_CLOSED
elseif tower_type == TOWER_TYPE.MOAT then return TEX_MOAT1
if tower_type == TOWER_TYPE.REDEYE then return TEX_TOWER_REDEYE
elseif tower_type == TOWER_TYPE.WALL then return TEX_TOWER_WALL
elseif tower_type == TOWER_TYPE.MOAT then return TEX_TOWER_MOAT
end
end
@ -35,21 +51,17 @@ local function get_tower_update_function(tower_type)
end
end
local function make_tower_sprite(tower_type)
local texture = get_tower_texture(tower_type)
if tower_type == TOWER_TYPE.REDEYE then
return pack_texture_into_sprite(texture, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y)
elseif tower_type == TOWER_TYPE.WALL then
return pack_texture_into_sprite(TEX_WALL_CLOSED, HEX_PIXEL_SIZE.x + 1, HEX_PIXEL_SIZE.y + 1)
--return am.circle(vec2(0), HEX_SIZE, COLORS.VERY_DARK_GRAY, 6)
function update_wall_texture(hex)
for _,n in pairs(hex_neighbours(hex)) do
local tile = HEX_MAP.get(hex.x, hex.y)
elseif tower_type == TOWER_TYPE.MOAT then
--return pack_texture_into_sprite(TEX_MOAT1, HEX_PIXEL_SIZE.x, HEX_PIXEL_SIZE.y)
return am.circle(vec2(0), HEX_SIZE, COLORS.YALE_BLUE, 6)
end
end
local function make_tower_sprite(tower_type)
return pack_texture_into_sprite(get_tower_texture(tower_type), HEX_PIXEL_WIDTH, HEX_PIXEL_HEIGHT)
end
function tower_on_hex(hex)
return table.find(TOWERS, function(tower)
return tower.hex == hex
@ -99,7 +111,7 @@ function update_tower_redeye(tower, tower_index)
)
tower.last_shot_time = TIME
tower.node:action(vplay_sound(SOUNDS.LASER2))
vplay_sfx(SOUNDS.LASER2)
end
end
end
@ -123,7 +135,8 @@ function make_and_register_tower(hex, tower_type)
end
function build_tower(hex, tower_type)
update_money(-get_tower_build_cost(tower_type))
make_and_register_tower(hex, tower_type)
WIN.scene:action(am.play(am.sfxr_synth(SOUNDS.EXPLOSION4)))
vplay_sfx(SOUNDS.EXPLOSION4)
end

12
src/tower_spec.luaa

@ -1,12 +0,0 @@
REDEYE = {
}

18
texture.lua

@ -1,23 +1,17 @@
function load_textures()
TEX_MARQUIS = am.texture2d("res/marquis.png")
TEX_BUTTON1 = am.texture2d("res/button1.png")
TEX_WIDER_BUTTON1 = am.texture2d("res/wider_button1.png")
TEX_TAB_ICON = am.texture2d("res/tab_icon.png")
TEX_ARROW = am.texture2d("res/arrow.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_MOAT1 = am.texture2d("res/moat1.png")
TEX_TOWER1 = am.texture2d("res/tower1.png")
TEX_TOWER2 = am.texture2d("res/tower2.png")
TEX_MOB1_1 = am.texture2d("res/mob1_1.png")
TEX_MOB2_1 = am.texture2d("res/mob2_1.png")
TEX_TOWER_WALL = am.texture2d("res/tower_wall.png")
TEX_TOWER_MOAT = am.texture2d("res/tower_moat.png")
TEX_TOWER_REDEYE = am.texture2d("res/tower_redeye.png")
TEX_TOWER_LIGHTHOUSE = am.texture2d("res/tower_lighthouse.png")
TEX_MOB_BEEPER = am.texture2d("res/mob_beeper.png")
end
function pack_texture_into_sprite(texture, width, height)

Loading…
Cancel
Save