View difference between Paste ID: 8fVhA2vC and hyfemdX9
SHOW: | | - or go back to the newest paste.
1
--[[
2
3
engine.lua
4
Version: 1.1
5
6
Author: MegaLoler
7
Email: [email protected]
8
9
A game engine for Love that manages game scenes and entities.
10
11
If requires that you use the class.lua file:
12
require("class.lua")
13
14
Make sure you have this in your code:
15
require("engine.lua")
16
17
Create a game by creating a subclass of the Engine class.
18
MyGame = engine.newClass(engine.Engine)
19
20
Define the setup method:
21
function MyGame:setup()
22
	-- Initalize your game here.
23
end
24
25
Make sure to call the setGame function of your game class in your main.lua:
26
MyGame:setGame()  -- This will make the game engine take over.
27
28
Create a scene by subclassing the Entity class:
29
TestScene = newClass(engine.Entity)
30
31
Define the setup, update, draw, and any other methods that you wish:
32
function TestScene:setup() ... end
33
function TestScene:update(dt) ... end
34
function TestScene:draw() ... end
35
36
Call the setScene method somewhere in your game's setup method to set the inital scene on launch:
37
self:setScene(TestScene) -- Pass the class itself, not an instance of it
38
39
--]]
40
41
require("class")
42
43
engine = {} -- Engine package
44
45
-- Love wrappers
46
47
function love.load()
48
	engine.game:load()
49
end
50
51
function love.quit()
52
	engine.game:quit()
53
end
54
55
function love.focus(f)
56
	engine.game:focus(f)
57
end
58
59
function love.keypressed(key, unicode)
60
	engine.game:keypressed(key, unicode)
61
end
62
63
function love.keyreleased(key)
64
	engine.game:keyreleased(key)
65
end
66
67
function love.mousepressed(x, y, button)
68
	engine.game:mousepressed(x, y, button)
69
end
70
71
function love.mousereleased(x, y, button)
72
	engine.game:mousereleased(x, y, button)
73
end
74
75
function love.update(dt)
76
	engine.game:update(dt)
77
end
78
79
function love.draw()
80
	engine.game:draw()
81
end
82
83
-- Engine class
84
85
engine.Engine = newClass()
86
87
function engine.Engine:init()
88
	self:setSize()
89
	self:setTitle()
90
	self.focused = true
91
	self.fading = false
92
	self.fade = 1
93
	self.fadeSpeed = 0.5
94
	self.fadeColor = {255, 255, 255}
95
	self:setScene(engine.Entity)
96
end
97
98
-- Sets the engine subclass to load
99
100
function engine.Engine:setGame()
101
	engine.game = self:new()
102
end
103
104
-- Engine methods
105
106
function engine.Engine:setTitle(title)
107
	self.title = title or "Game Engine"
108
	love.graphics.setCaption(self.title)
109
end
110
111
function engine.Engine:setSize(width, height)
112
	self.width = width or 640
113
	self.height = height or 480
114
	love.graphics.setMode(self.width, self.height)
115
	if self.scene then self:positionScene() end
116
end
117
118
function engine.Engine:fadeToScene(scene, ...)
119
	self.fadeTo = scene
120
	self.fadeArgs = ...
121
	self.fading = true
122
end
123
124
function engine.Engine:setScene(scene, ...)
125
	if self.scene then self.scene:destroy() end
126
	self.scene = scene:new(self)
127
	self:positionScene()
128
	self.scene:setup(...)
129
end
130
131
function engine.Engine:toggleFullscreen()
132
	love.graphics.toggleFullscreen()
133
end
134
135
-- Wrapped Love functions
136
137
function engine.Engine:load()
138
	self:setup()
139
end
140
141
function engine.Engine:quit()
142
end
143
144
function engine.Engine:focus(f)
145
	self.focused = f
146
end
147
148
function engine.Engine:keypressed(key, unicode)
149
	self.scene:onkeypressed(key, unicode)
150
end
151
152
function engine.Engine:keyreleased(key)
153
	self.scene:onkeyreleased(key)
154
end
155
156
function engine.Engine:mousepressed(x, y, button)
157
	self.scene:onmousepressed(x, y, button)
158
end
159
160
function engine.Engine:mousereleased(x, y, button)
161
	self.scene:onmousereleased(x, y, button)
162
end
163
164
function engine.Engine:update(dt)
165
	if self.fading then
166
		if self.fade >= 1 then
167
			self.fade = 1
168
			self.fading = false
169
			self:setScene(self.fadeTo, self.fadeArgs)
170
		else
171
			self.fade = self.fade + self.fadeSpeed * dt
172
			if self.fade > 1 then self.fade = 1 end
173
		end
174
	else
175
		if self.fade <= 0 then
176
			self.fade = 0
177
		else
178
			self.fade = self.fade - self.fadeSpeed * dt
179
			if self.fade < 0 then self.fade = 0 end
180
		end
181
	end
182
	self.scene:masterUpdate(dt)
183
end
184
185
function engine.Engine:draw()
186
	self.scene:render()
187
	love.graphics.setCanvas()
188
	self.scene:postRender()
189
	self:drawFade()
190
end
191
192
-- Private methods
193
194
function engine.Engine:positionScene()
195
	self.scene:setPosition(self.width / 2, self.height / 2)
196
end
197
198
function engine.Engine:drawFade()
199-
	love.graphics.drawq(self.canvas, love.graphics.newQuad(0, 0, self.width, self.height, self.width, self.height), self.x + self.width / 2, self.y + self.height / 2, self.orientation, self.scaleX, self.scaleY, self.width / 2, self.height / 2)
199+
200
	love.graphics.setColor(self.fadeColor[1], self.fadeColor[2], self.fadeColor[3], (math.cos((1 - self.fade) * math.pi) + 1) * 127)
201
	love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
202
end
203
204
-- Virtual methods
205
206
function engine.Engine:setup()
207
end
208
209
-- Entity class
210
211
engine.Entity = newClass()
212
213
function engine.Entity:init(engine)
214
	self.engine = engine
215
	self:setSize()
216
	self:setPosition()
217
	self:setOrientation()
218
	self:setScale()
219
	self:setColor()
220
	self.children = {}
221
	self.selectable = false
222
	self.selected = false
223
end
224
225
function engine.Entity:addChild(child, ...)
226
	table.insert(self.children, child)
227
	child:setup(...)
228
end
229
230
function engine.Entity:removeChild(child)
231
	table.remove(self.children, child)
232
	child:destroy()
233
end
234
235
function engine.Entity:setColor(color)
236
	self.color = color or {255, 255, 255}
237
end
238
239
function engine.Entity:setPosition(x, y)
240
	self.x = x or 0
241
	self.y = y or 0
242
end
243
244
function engine.Entity:setOrientation(r)
245
	self.orientation = r or 0
246
end
247
248
function engine.Entity:setScale(x, y)
249
	self.scaleX = x or 1
250
	self.scaleY = y or 1
251
end
252
253
function engine.Entity:setSize(width, height)
254
	self.width = width or self.engine.width
255
	self.height = height or self.engine.height
256
	self.canvas = love.graphics.newCanvas(self.width, self.height)
257
end
258
259
function engine.Entity:masterUpdate(dt)
260
	for k, v in pairs(self.children) do
261
		v:masterUpdate(dt)
262
	end
263
	self:update(dt)
264
end
265
266
function engine.Entity:render()
267
	love.graphics.setCanvas(self.canvas)
268
	love.graphics.setColor(love.graphics.getBackgroundColor())
269
	love.graphics.setBlendMode("alpha")
270
	love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
271
	
272
	self:preDraw()
273
	
274
	for k, v in pairs(self.children) do
275
		v:render()
276
		love.graphics.setCanvas(self.canvas)
277
		v:postRender()
278
	end
279
	
280
	self:draw()
281
end
282
283
function engine.Entity:postRender()
284
	love.graphics.setBlendMode("alpha")
285
	love.graphics.setColor(self.color[1], self.color[2], self.color[3])
286
	love.graphics.drawq(self.canvas, love.graphics.newQuad(0, 0, self.width, self.height, self.width, self.height), self.x, self.y , self.orientation, self.scaleX, self.scaleY, self.width / 2, self.height / 2)
287
end
288
289
function engine.Entity:onkeypressed(key, unicode)
290
	self:keypressed(key, unicode)
291
	if self.selectedChild then self.selectedChild:onkeypressed(key, unicode) end
292
end
293
294
function engine.Entity:onkeyreleased(key)
295
	self:keyreleased(key)
296
	if self.selectedChild then self.selectedChild:onkeyreleased(key) end
297
end
298
299
function engine.Entity:onmousepressed(x, y, button)
300
	self:mousepressed(x, y, button)
301
	if self.selectedChild then self.selectedChild.selected = false end
302
	self.selectedChild = self:getChildAtLocation(x, y)
303
	if self.selectedChild and not self.selectedChild.selectable then self.selectedChild = nil end
304
	if self.selectedChild then
305
		self.selectedChild.selected = true
306
		x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
307
		self.selectedChild:onmousepressed(x, y, button)
308
	end
309
end
310
311
function engine.Entity:onmousereleased(x, y, button)
312
	self:mousereleased(x, y, button)
313
	if self.selectedChild then
314
		x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
315
		self.selectedChild:onmousereleased(x, y, button)
316
	end
317
end
318
319
-- Private methods
320
321
function engine.Entity:inBounds(x, y)
322
	return x >= 0 and x < self.width and y >= 0 and y < self.height
323
end
324
325
function engine.Entity:getChildAtLocation(x, y)
326
	for i = 1, #self.children do
327
		local child = self.children[#self.children - (i - 1)]
328
		local cx, cy = self:localCoordsToChildCoords(x, y, child)
329
		if child:inBounds(cx, cy) then return child end
330
	end
331
end
332
333
function engine.Entity:localCoordsToChildCoords(x, y, child)
334
	x = (x - child.x) / child.scaleX
335
	y = (y - child.y) / child.scaleY
336
	
337
	distance = math.sqrt((x * x) + (y * y))
338
	angle = math.atan2(y, x) - child.orientation
339
	
340
	x = math.cos(angle) * distance
341
	y = math.sin(angle) * distance
342
	
343
	x = x + child.width / 2
344
	y = y + child.height / 2
345
	
346
	return x, y
347
end
348
349
-- Virtual methods
350
351
function engine.Entity:setup(...)
352
end
353
354
function engine.Entity:destroy()
355
end
356
357
function engine.Entity:keypressed(key, unicode)	
358
end
359
360
function engine.Entity:keyreleased(key)
361
end
362
363
function engine.Entity:mousepressed(x, y, button)
364
end
365
366
function engine.Entity:mousereleased(x, y, button)
367
end
368
369
function engine.Entity:update(dt)
370
end
371
372
function engine.Entity:preDraw()
373
end
374
375
function engine.Entity:draw()
376
end