13
14
stand = { frames = { 1 }, fps = 1 },
14
15
walk = { frames = { 2, 3 }, fps = 5 },
15
jump = { frames = { 4 }, fps = 1 }
16
jump = { frames = { 4 }, fps = 1 },
17
climbLeft = { frames = { 5, 6 }, fps = 5 },
18
climbRight = { frames = { 7, 8 }, fps = 5 }
17
23
onNew = function (self)
18
24
self.velocity.y = 0
19
25
self.maxVelocity.y = 400
27
doPhysics = function (self, dir, elapsed)
28
local vel = self.velocity
29
local acc = self.acceleration
30
local drag = self.drag
31
local minVel = self.minVelocity
32
local maxVel = self.maxVelocity
34
-- check existence of properties
37
assert(vel, 'active sprite has no velocity property')
38
assert(acc, 'active sprite has no acceleration property')
39
assert(drag, 'active sprite has no drag property')
40
assert(minVel, 'active sprite has no minVelocity property')
41
assert(maxVel, 'active sprite has no maxVelocity property')
42
assert(__.include({'x','y','rotation'}, dir), 'direction should be x, y, or rotation')
47
vel.rotation = vel.rotation or 0
51
if acc[dir] and acc[dir] ~= 0 then
52
vel[dir] = vel[dir] + acc[dir] * elapsed
56
vel[dir] = vel[dir] - drag[dir] * elapsed
57
if vel[dir] < 0 then vel[dir] = 0 end
58
elseif vel[dir] < 0 then
59
vel[dir] = vel[dir] + drag[dir] * elapsed
60
if vel[dir] > 0 then vel[dir] = 0 end
65
if minVel[dir] and vel[dir] < minVel[dir] then vel[dir] = minVel[dir] end
66
if maxVel[dir] and vel[dir] > maxVel[dir] then vel[dir] = maxVel[dir] end
68
if vel[dir] ~= 0 then self[dir] = self[dir] + vel[dir] * elapsed end
21
70
onStartFrame = function (self)
22
71
-- this is all in startframe so it happens before
23
72
-- physics calc at beginning of update
27
76
if self.falling then self.jumping = false end
28
77
--print(self.jumping, self.falling)
30
if not self.onGround then
79
if (not self.onGround) and (not self.onWall) then
35
83
self.acceleration.y = 800
86
self.acceleration.y = 0
88
if self.onWall == 'right' then
89
self:play('climbRight')
90
elseif self.onWall == 'left' then
91
self:play('climbLeft')
94
if the.keys:pressed('up') then
95
self.velocity.y = -200
96
elseif the.keys:pressed('down') then
100
self:freeze(self.sequences[self.currentName].frames[1])
37
104
if the.keys:pressed('left') then
38
105
self.velocity.x = -200
39
106
if self.onGround then self:play('walk') end
107
if self.onWall == 'right' then
109
self.leftWallAt = love.timer.getTime()
40
111
elseif the.keys:pressed('right') then
41
112
self.velocity.x = 200
42
113
if self.onGround then self:play('walk') end
114
if self.onWall == 'left' then
116
self.leftWallAt = love.timer.getTime()
44
if self.onGround then self:play('stand') end
119
if not self.onWall then
120
if self.onGround then self:play('stand') end
47
if the.keys:justPressed('up') and self.onGround then
125
if the.keys:justPressed('up') and
127
(love.timer.getTime() - self.leftWallAt < .1) ) then
48
128
self.velocity.y = -400
49
129
self.jumping = true
52
onUpdate = function (self)
53
-- needs to happen right before collision
132
update = function (self, elapsed)
133
-- NOTE: this is an override, not a callback
135
self:doPhysics('x', elapsed)
136
self:collide(the.view.map)
138
-- handle X collisions
140
for _, col in ipairs(self.collisions) do
141
col.other:displaceDir(self, 'x')
142
if self.velocity.x > 0 then
143
self.onWall = 'right'
144
elseif self.velocity.x < 0 then
151
self.onGround = false -- right before Y collision callbacks
152
self:doPhysics('y', elapsed)
153
self:collide(the.view.map)
155
-- handle Y collisions
156
for _, col in ipairs(self.collisions) do
157
if self.velocity.y > 0 then
161
col.other:displaceDir(self, 'y')
166
Animation.update(self, elapsed)
168
collide = function (self, ...)
170
Animation.collide(self, ...)
171
-- I could return a true/false value here if I wanted to...
56
173
onCollide = function (self, other, xOverlap, yOverlap)
57
-- seriously, why does this even fire?
58
174
if other == the.view.map then return end
60
--print(string.format('col s{x=%i y=%i w=%i h=%i} %s', self.x, self.y, self.width, self.height, tostring(other)))
61
--print('vel.x:'..self.velocity.x.." vel.y:"..self.velocity.y)
63
-- assumption: any other collision is with a solid map tile
64
if yOverlap > xOverlap then
67
if self.velocity.x > 0 then
69
elseif self.velocity.x < 0 then
74
elseif xOverlap > yOverlap then
75
-- check if we've moved since collisions were generated
76
local xov, yov = self:overlap(other.x, other.y,
77
other.width, other.height)
78
if xov ~= 0 and yov ~= 0 then
79
--print('y collision')
80
if self.velocity.y > 0 then
176
table.insert(self.collisions, {other = other,
178
yOverlap = yOverlap })
182
-- displace on a specific axis (monkey patch Sprite)
183
function Sprite:displaceDir(other, dir)
184
if not self.solid or self == other or not other.solid then return end
185
if STRICT then assert(other:instanceOf(Sprite), 'asked to displace a non-sprite') end
187
if other.sprites then
190
for _, spr in pairs(other.sprites) do
191
self:displace(spr, dir)
198
elseif dir == 'y' then
204
local negMove = (other[dir] - self[dir]) + other[dim]
205
local posMove = (self[dir] + self[dim]) - other[dir]
207
-- TODO: re-add hinting?
208
if negMove < posMove then
215
other[dir] = other[dir] + chg
95
218
GameView = View:extend {
96
219
onNew = function (self)
97
220
self:loadLayers('data/map.lua')
108
231
the.app = App:new {
109
232
onRun = function (self)
110
233
self.view = GameView:new()
111
--print(inspect(_(the.app):keys()))
112
234
self.console:watch('onGround', 'the.player.onGround')
113
235
self.console:watch('onWall', 'the.player.onWall')
236
self.console:watch('updateTook', 'the.updateTook')
237
self.console:watch('drawTook', 'the.drawTook')
239
--the.profiler = newProfiler('time', 2000)
240
--the.profiler = newProfiler()
241
--the.profiler:start()
115
243
onUpdate = function (self, dt)
116
if the.keys:justPressed('escape') and
117
not self.console.visible then
244
if the.keys:justPressed('escape') then
247
local outfile = io.open( "profile.txt", "w+" )
248
the.profiler:report( outfile )
b'\\ No newline at end of file'
255
update = function (self, dt)
256
the.updateStart = love.timer.getMicroTime()
258
if the.updateStart then
259
the.updateTook = love.timer.getMicroTime() - the.updateStart