aboutsummaryrefslogtreecommitdiff
path: root/libs/sti/plugins/bump.lua
blob: 1d4b828dc7fbeb236dbf72fc249ab46929ccc491 (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
--- Bump.lua plugin for STI
-- @module bump.lua
-- @author David Serrano (BobbyJones|FrenchFryLord)
-- @copyright 2019
-- @license MIT/X11

local lg = require((...):gsub('plugins.bump', 'graphics'))

return {
	bump_LICENSE        = "MIT/X11",
	bump_URL            = "https://github.com/karai17/Simple-Tiled-Implementation",
	bump_VERSION        = "3.1.7.1",
	bump_DESCRIPTION    = "Bump hooks for STI.",

	--- Adds each collidable tile to the Bump world.
	-- @param world The Bump world to add objects to.
	-- @return collidables table containing the handles to the objects in the Bump world.
	bump_init = function(map, world)
		local collidables = {}

		for _, tileset in ipairs(map.tilesets) do
			for _, tile in ipairs(tileset.tiles) do
				local gid = tileset.firstgid + tile.id

				if map.tileInstances[gid] then
					for _, instance in ipairs(map.tileInstances[gid]) do
						-- Every object in every instance of a tile
						if tile.objectGroup then
							for _, object in ipairs(tile.objectGroup.objects) do
								if object.properties.collidable == true then
									local t = {
										name       = object.name,
										type       = object.type,
										x          = instance.x + map.offsetx + object.x,
										y          = instance.y + map.offsety + object.y,
										width      = object.width,
										height     = object.height,
										layer      = instance.layer,
										properties = object.properties

									}

									world:add(t, t.x, t.y, t.width, t.height)
									table.insert(collidables, t)
								end
							end
						end

						-- Every instance of a tile
						if tile.properties and tile.properties.collidable == true then
							local t = {
								x          = instance.x + map.offsetx,
								y          = instance.y + map.offsety,
								width      = map.tilewidth,
								height     = map.tileheight,
								layer      = instance.layer,
								type       = tile.type,
								properties = tile.properties
							}

							world:add(t, t.x, t.y, t.width, t.height)
							table.insert(collidables, t)
						end
					end
				end
			end
		end

		for _, layer in ipairs(map.layers) do
			-- Entire layer
			if layer.properties.collidable == true then
				if layer.type == "tilelayer" then
					for y, tiles in ipairs(layer.data) do
						for x, tile in pairs(tiles) do

							if tile.objectGroup then
								for _, object in ipairs(tile.objectGroup.objects) do
									if object.properties.collidable == true then
										local t = {
											name       = object.name,
											type       = object.type,
											x          = ((x-1) * map.tilewidth  + tile.offset.x + map.offsetx) + object.x,
											y          = ((y-1) * map.tileheight + tile.offset.y + map.offsety) + object.y,
											width      = object.width,
											height     = object.height,
											layer      = layer,
											properties = object.properties
										}

										world:add(t, t.x, t.y, t.width, t.height)
										table.insert(collidables, t)
									end
								end
							end


							local t = {
								x          = (x-1) * map.tilewidth  + tile.offset.x + map.offsetx,
								y          = (y-1) * map.tileheight + tile.offset.y + map.offsety,
								width      = tile.width,
								height     = tile.height,
								layer      = layer,
								type       = tile.type,
								properties = tile.properties
							}

							world:add(t, t.x, t.y, t.width, t.height)
							table.insert(collidables, t)
						end
					end
				elseif layer.type == "imagelayer" then
					world:add(layer, layer.x, layer.y, layer.width, layer.height)
					table.insert(collidables, layer)
				end
		  end

			-- individual collidable objects in a layer that is not "collidable"
			-- or whole collidable objects layer
		  if layer.type == "objectgroup" then
				for _, obj in ipairs(layer.objects) do
					if layer.properties.collidable == true or obj.properties.collidable == true then
						if obj.shape == "rectangle" then
							local t = {
								name       = obj.name,
								type       = obj.type,
								x          = obj.x + map.offsetx,
								y          = obj.y + map.offsety,
								width      = obj.width,
								height     = obj.height,
								layer      = layer,
								properties = obj.properties
							}

							if obj.gid then
								t.y = t.y - obj.height
							end

							world:add(t, t.x, t.y, t.width, t.height)
							table.insert(collidables, t)
						end -- TODO implement other object shapes?
					end
				end
			end
		end

		map.bump_world       = world
		map.bump_collidables = collidables
	end,

	--- Remove layer
	-- @param index to layer to be removed
	bump_removeLayer = function(map, index)
		local layer = assert(map.layers[index], "Layer not found: " .. index)
		local collidables = map.bump_collidables

		-- Remove collision objects
		for i = #collidables, 1, -1 do
			local obj = collidables[i]

			if obj.layer == layer
			and (
				layer.properties.collidable == true
				or obj.properties.collidable == true
			) then
				map.bump_world:remove(obj)
				table.remove(collidables, i)
			end
		end
	end,

	--- Draw bump collisions world.
	-- @param world bump world holding the tiles geometry
	-- @param tx Translate on X
	-- @param ty Translate on Y
	-- @param sx Scale on X
	-- @param sy Scale on Y
	bump_draw = function(map, tx, ty, sx, sy)
		lg.push()
		lg.scale(sx or 1, sy or sx or 1)
		lg.translate(math.floor(tx or 0), math.floor(ty or 0))

		local items = map.bump_world:getItems()
		for _, item in ipairs(items) do
			lg.rectangle("line", map.bump_world:getRect(item))
		end

		lg.pop()
	end
}

--- Custom Properties in Tiled are used to tell this plugin what to do.
-- @table Properties
-- @field collidable set to true, can be used on any Layer, Tile, or Object