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
|
-- monkey patches for zoetrope Sprite
-- displace on a specific axis
function Sprite:displaceDir(other, dir)
if not self.solid or self == other or not other.solid then return end
if STRICT then assert(other:instanceOf(Sprite), 'asked to displace a non-sprite') end
if other.sprites then
-- handle groups
for _, spr in pairs(other.sprites) do
self:displace(spr, dir)
end
else
-- handle sprites
local dim = util.dim(dir)
local negMove = (other[dir] - self[dir]) + other[dim]
local posMove = (self[dir] + self[dim]) - other[dir]
-- TODO: re-add hinting?
if negMove < posMove then
chg = - negMove
else
chg = posMove
end
end
other[dir] = other[dir] + chg
end
-- don't use zoetrope physics
function Sprite:update(elapsed)
self:doPhysics('x', elapsed)
self:doPhysics('y', elapsed)
self:doPhysics('rotation', elapsed)
if self.onUpdate then self:onUpdate(elapsed) end
end
-- directional physics
function Sprite:doPhysics(dir, elapsed)
local vel = self.velocity
local acc = self.acceleration
local drag = self.drag
local minVel = self.minVelocity
local maxVel = self.maxVelocity
-- check existence of properties
if STRICT then
assert(vel, 'active sprite has no velocity property')
assert(acc, 'active sprite has no acceleration property')
assert(drag, 'active sprite has no drag property')
assert(minVel, 'active sprite has no minVelocity property')
assert(maxVel, 'active sprite has no maxVelocity property')
assert(dir=='x' or dir=='y' or dir=='rotation', 'direction should be x, y, or rotation')
end
vel.x = vel.x or 0
vel.y = vel.y or 0
vel.rotation = vel.rotation or 0
-- physics
if acc[dir] and acc[dir] ~= 0 then
vel[dir] = vel[dir] + acc[dir] * elapsed
else
if drag[dir] then
if vel[dir] > 0 then
vel[dir] = vel[dir] - drag[dir] * elapsed
if vel[dir] < 0 then vel[dir] = 0 end
elseif vel[dir] < 0 then
vel[dir] = vel[dir] + drag[dir] * elapsed
if vel[dir] > 0 then vel[dir] = 0 end
end
end
end
if minVel[dir] and vel[dir] < minVel[dir] then vel[dir] = minVel[dir] end
if maxVel[dir] and vel[dir] > maxVel[dir] then vel[dir] = maxVel[dir] end
-- ugly hack for falling through floor on really slow frames
if math.abs(vel[dir] * elapsed) > 16 then
print('skip')
return
end
if vel[dir] ~= 0 then self[dir] = self[dir] + vel[dir] * elapsed end
if the.activeMaze and (dir == 'x' or dir == 'y') then -- doesn't make sense for rotation
if self[dir] < 0 then self[dir] = 0 end
local edge = the.activeMaze[util.dim(dir)] - the.player[util.dim(dir)]
-- TODO: take map position into account
if self[dir] > edge then self[dir] = edge end
end
end
|