-
Notifications
You must be signed in to change notification settings - Fork 30
/
Object.lua
238 lines (205 loc) · 9.69 KB
/
Object.lua
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
---------------------------------------------------------------------------------------------------
-- -= Object =-
---------------------------------------------------------------------------------------------------
-- Setup
local Object = {class = "Object"}
Object.__index = Object
---------------------------------------------------------------------------------------------------
-- Returns a new Object
function Object:new(layer, name, type, x, y, width, height, gid, prop)
-- Public:
local obj = setmetatable({}, Object)
obj.layer = layer -- The layer that the object belongs to
obj.name = name or "" -- Name of the object
obj.type = type or "" -- Type of the object
obj.x = x or 0 -- X location on the map
obj.y = y or 0 -- Y location on the map
obj.width = width or 0 -- Object width in tiles
obj.height = height or 0 -- Object height in tiles
obj.gid = gid -- The object's associated tile. If false an outline will be drawn.
obj.visible = true -- If false then the object will not be drawn
obj.properties = prop or {} -- Properties set by tiled.
obj.polygon = nil -- Polygon points. Set by the Loader if defined in Tiled.
obj.polyline = nil -- Polyline points. Set by the Loader if defined in Tiled.
-- drawInfo stores values needed to actually draw the object. You can either set these yourself
-- or use updateDrawInfo to do it automatically.
obj.drawInfo = {
-- x and y are the drawing location of the object. This is different than the object's x and
-- y value which is the object's placement on the map.
x = 0, -- The x draw location
y = 0, -- The y draw location
-- These limit the drawing of the object. If the object falls out of the bounds of
-- the map's drawRange then the object will not be drawn.
left = 0, -- The leftmost point on the object
right = 0, -- The rightmost point on the object
top = 0, -- The highest point on the object
bottom = 0, -- The lowest point on the object
-- The order to draw the object in relation to other objects. Usually equal to bottom.
order = 0,
-- In addition to this, other drawing information can be stored in the numerical
-- indicies which is context sensitive to the map's orientation, if the object has a gid, or
-- of the object is a polygon or polyline object.
}
-- Update the draw info
Object.updateDrawInfo(obj)
-- Return our object
return obj
end
---------------------------------------------------------------------------------------------------
-- Updates the draw information. Call this every time the object moves or changes size.
function Object:updateDrawInfo()
local di = self.drawInfo
local map = self.layer.map
if self.polygon or self.polyline then
-- Reset the draw info
self.drawInfo = {}
di = self.drawInfo
-- Set the box to the first vertex
local vertexes = self.polygon or self.polyline
-- Create the draw information for each vertex
for k,v in ipairs(vertexes) do
if k%2 == 1 then
if map.orientation == "isometric" then
di[k], di[k+1] = map:fromIso(self.x+vertexes[k], self.y+vertexes[k+1])
else
di[k], di[k+1] = self.x+vertexes[k], self.y+vertexes[k+1]
end
di[k], di[k+1] = di[k] - map.offsetX, di[k+1] - map.offsetY
end
end
-- Set the start draw location
di.x, di.y = di[1], di[2]
-- Prime the bounds
di.left, di.right, di.top, di.bottom = di.x, di.x, di.y, di.y
-- Go through each vertex and find the highest and lowest values for the bounds.
for k,v in ipairs(di) do
-- if it's odd then it's an x value
if k%2 == 1 then
if v < di.left then di.left = v end
if v > di.right then di.right = v end
-- if it's even it's a y value
else
if v < di.top then di.top = v end
if v > di.bottom then di.bottom = v end
end
end
di.order = di.bottom
-- Isometric map
elseif map.orientation == "isometric" then
-- Is a tile object
if self.gid then
local t = map.tiles[self.gid]
local tw, th = t.width, t.height
di.x, di.y = map:fromIso(self.x, self.y)
di.x, di.y = di.x - map.offsetX, di.y - map.offsetY
di.order = di.y
di.x = di.x - map.tileWidth/2
di.left, di.right, di.top, di.bottom = di.x, di.x+tw, di.y , di.y +th
-- Is not a tile object
else
di[1], di[2] = map:fromIso(self.x, self.y)
di[3], di[4] = map:fromIso(self.x + self.width, self.y)
di[5], di[6] = map:fromIso(self.x + self.width, self.y + self.height)
di[7], di[8] = map:fromIso(self.x, self.y + self.height)
for i =1,7,2 do
di[i] = di[i] - map.offsetX
di[i+1] = di[i+1] - map.offsetY
end
di.left, di.right, di.top, di.bottom = di[7], di[3], di[2], di[6]
di.order = 1
end
-- Orthogonal map
else
-- Is a tile object
if self.gid then
local t = map.tiles[self.gid]
local tw, th = t.width, t.height
di.x, di.y = self.x - map.offsetX, self.y - map.offsetY
di.order = di.y
di.left, di.top, di.right, di.bottom = di.x, di.y, di.x+tw, di.y+th
-- Is not a tile object
else
di.x, di.y = self.x - map.offsetX, self.y - map.offsetY
di[1], di[2] = di.x, di.y
di[3], di[4] = self.width > 20 and self.width or 20, self.height > 20 and self.height or 20
di.left, di.top, di.right, di.bottom = di.x, di.y , di.x+di[3], di.y +di[4]
di.order = 1
end
end
end
---------------------------------------------------------------------------------------------------
-- Draw the object. The passed color is the color of the object layer the object belongs to.
function Object:draw(x, y, r, g, b, a)
if not self.visible then return end
local di = self.drawInfo
love.graphics.setLineWidth(2)
-- The object is a polyline.
if self.polyline then
love.graphics.push()
love.graphics.translate(0,1)
love.graphics.setColor(0, 0, 0, a)
love.graphics.line( unpack(di) )
love.graphics.pop()
love.graphics.setColor(r, g, b, a)
love.graphics.line( unpack(di) )
-- The object is a polygon.
elseif self.polygon then
love.graphics.push()
love.graphics.translate(0,1)
love.graphics.setColor(0, 0, 0, a)
love.graphics.polygon( "line", unpack(di) )
love.graphics.pop()
love.graphics.setColor(r,g,b,a)
love.graphics.polygon( "line", unpack(di) )
-- The object is a tile object. Draw the tile.
elseif self.gid then
local tile = self.layer.map.tiles[self.gid]
tile:draw(di.x, di.y - tile.height)
-- Map is isometric. Draw a parallelogram.
elseif self.layer.map.orientation == "isometric" then
love.graphics.setColor(r, g, b, a/5)
love.graphics.polygon("fill", unpack(di))
love.graphics.push()
love.graphics.translate(0,1)
love.graphics.setColor(0, 0, 0, a)
love.graphics.polygon("line", unpack(di))
love.graphics.pop()
love.graphics.setColor(r,g,b,a)
love.graphics.polygon("line", unpack(di))
-- Map is orthogonal. Draw a rectangle.
else
love.graphics.setColor(r, g, b, a/5)
love.graphics.rectangle("fill", unpack(di))
love.graphics.setColor(0, 0, 0, a)
love.graphics.push()
love.graphics.translate(1,1)
love.graphics.rectangle("line", unpack(di))
love.graphics.print(self.name, di.x, di.y-20)
love.graphics.pop()
love.graphics.setColor(r,g,b,a)
love.graphics.rectangle("line", unpack(di))
love.graphics.print(self.name, di.x, di.y-20)
end
end
---------------------------------------------------------------------------------------------------
-- Returns the Object class
return Object
--[[Copyright (c) 2011-2012 Casey Baxter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.--]]