-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathglitches.lua
More file actions
125 lines (110 loc) · 4.01 KB
/
glitches.lua
File metadata and controls
125 lines (110 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
--[[ Glitches
Instances hold a perpetual set of glitch coordinates, generated from
existing tiles in a map layer.
Glitches are generated from whatever map layer is currently loaded, but
glitch coordinates are forever.
Can also apply glitches to a map layer -- will attempt to apply all
accumulated glitch coordinates, deleting any matching tiles in the layer.
]]--
Glitches = function(param)
local glitch_coords = {}
local map_layer, tile_list, layer_w, layer_h = nil, nil, nil, nil
--hacky RNG seeding/init
local rng = love.math.newRandomGenerator(os.time())
rng:random()
rng:random()
-- if `param` passed is not a callback function, then have a backup function
-- which sets the coords to `param` (which will default to nil). Clever!
local callback_func = nil
if (type(param) == "function") then
callback_func = param
else
callback_func = function(layer, x, y)
layer:set(x, y, param)
end
end
-- loads a map layer and populates a tile list for creating glitches
local load_layer = function (layer_in)
map_layer = layer_in
tile_list = {}
map_w = map_layer.map.width
map_h = map_layer.map.height
for x, y, tile in map_layer:iterate() do
table.insert(tile_list, {x, y, tile.properties})
end
end
-- everybody loves a getter
local get_glitch_coords = function()
return glitch_coords
end
-- iterator over glitch coords, stolen from AdvTiledLoader.Grid
local glitch_coords_iterate = function()
local x, y, row, val = nil, nil, nil, nil
return function()
repeat
if not y then
x, row = next(glitch_coords, x)
if not row then return end
end
y, val = next(row, y)
until y
return x, y, val
end
end
-- safely write coords to 2d table
local glitch_coords_add = function(x, y, p)
-- do some basic bounds-checking for new coords
if (x >= map_w or y >= map_h) then return false end
if (glitch_coords[x] == nil) then
glitch_coords[x] = {}
end
glitch_coords[x][y] = {p}
end
-- add a cross-shaped glitch
local add_cross_glitch = function(x, y, p)
glitch_coords_add(x, y, p)
glitch_coords_add(x + 1, y, p)
glitch_coords_add(x - 1, y, p)
glitch_coords_add(x, y + 1, p)
glitch_coords_add(x, y - 1, p)
end
-- Generate cross-shaped glitches on tiles in loaded layer.
-- Doesn't try to avoid duplicates, nor to keep whole glitch on-screen.
local generate_glitches = function(num_glitches, shape, whole_map)
for i = 1, num_glitches, 1 do
local x, y, p = nil, nil, nil
if(whole_map) then
repeat -- be less naive about picking existing tiles
x = rng:random(1, map_w)
y = rng:random(1, map_h)
p = map_layer(x, y)
until p == nil
else
x, y, p = unpack(tile_list[rng:random(1, #tile_list)])
end
-- shape defaults to a cross, but "single" is an option
if (shape == "single") then
glitch_coords_add(x, y, p)
else
add_cross_glitch(x, y, p)
end
end
end
-- Modify glitched tiles from a map layer.
-- Shouldn't choke if impossible/nonexistent tiles are in the list.
local modify_layer = function (safe_col)
local x, y = nil, nil
for x, y in glitch_coords_iterate() do
if (not safe_col or (x > safe_col + 1 or x < safe_col -1)) then
callback_func(map_layer, x, y, p)
end
end
end
-- Public Interface
return {
load_layer = load_layer,
get_glitch_coords = get_glitch_coords,
generate_glitches = generate_glitches,
modify_layer = modify_layer
}
end