/ld27

To get this branch, use:
bzr branch /bzr/ld27
25 by Josh C
overhaul collision and physics to fix an annoying collision resolution
1
-- monkey patches for zoetrope Sprite
2
3
-- displace on a specific axis
4
function Sprite:displaceDir(other, dir)
5
   if not self.solid or self == other or not other.solid then return end
6
   if STRICT then assert(other:instanceOf(Sprite), 'asked to displace a non-sprite') end
7
8
   if other.sprites then
9
      -- handle groups
10
11
      for _, spr in pairs(other.sprites) do
12
         self:displace(spr, dir)
13
      end
14
   else
15
      -- handle sprites
16
      local dim = util.dim(dir)
17
18
      local negMove = (other[dir] - self[dir]) + other[dim]
19
      local posMove = (self[dir] + self[dim]) - other[dir]
20
21
      -- TODO: re-add hinting?
22
      if negMove < posMove then
23
         chg = - negMove
24
      else
25
         chg = posMove
26
      end
27
   end
28
29
   other[dir] = other[dir] + chg
30
end
31
32
-- don't use zoetrope physics
33
function Sprite:update(elapsed)
34
   self:doPhysics('x', elapsed)
35
   self:doPhysics('y', elapsed)
36
   self:doPhysics('rotation', elapsed)
37
38
   if self.onUpdate then self:onUpdate(elapsed) end
39
end
40
41
-- directional physics
42
function Sprite:doPhysics(dir, elapsed)
43
   local vel = self.velocity
44
   local acc = self.acceleration
45
   local drag = self.drag
46
   local minVel = self.minVelocity
47
   local maxVel = self.maxVelocity
48
49
   -- check existence of properties
50
51
   if STRICT then
52
      assert(vel, 'active sprite has no velocity property')
53
      assert(acc, 'active sprite has no acceleration property')
54
      assert(drag, 'active sprite has no drag property')
55
      assert(minVel, 'active sprite has no minVelocity property')
56
      assert(maxVel, 'active sprite has no maxVelocity property')
57
      assert(dir=='x' or dir=='y' or dir=='rotation', 'direction should be x, y, or rotation')
58
   end
59
60
   vel.x = vel.x or 0
61
   vel.y = vel.y or 0
62
   vel.rotation = vel.rotation or 0
63
64
   -- physics
65
66
   if acc[dir] and acc[dir] ~= 0 then
67
      vel[dir] = vel[dir] + acc[dir] * elapsed
68
   else
69
      if drag[dir] then
70
         if vel[dir] > 0 then
71
            vel[dir] = vel[dir] - drag[dir] * elapsed
72
            if vel[dir] < 0 then vel[dir] = 0 end
73
         elseif vel[dir] < 0 then
74
            vel[dir] = vel[dir] + drag[dir] * elapsed
75
            if vel[dir] > 0 then vel[dir] = 0 end
76
         end
77
      end
78
   end
79
80
   if minVel[dir] and vel[dir] < minVel[dir] then vel[dir] = minVel[dir] end
81
   if maxVel[dir] and vel[dir] > maxVel[dir] then vel[dir] = maxVel[dir] end
82
83
   -- ugly hack for falling through floor on really slow frames
26 by Josh C
correct tile size for slow frame hack
84
   if math.abs(vel[dir] * elapsed) > 16 then
25 by Josh C
overhaul collision and physics to fix an annoying collision resolution
85
      print('skip')
86
      return
87
   end
88
89
   if vel[dir] ~= 0 then self[dir] = self[dir] + vel[dir] * elapsed end
90
27 by Josh C
title screen
91
   if the.activeMaze and (dir == 'x' or dir == 'y') then -- doesn't make sense for rotation
25 by Josh C
overhaul collision and physics to fix an annoying collision resolution
92
      if self[dir] < 0 then self[dir] = 0 end
93
      local edge = the.activeMaze[util.dim(dir)] - the.player[util.dim(dir)]
94
      -- TODO: take map position into account
95
      if self[dir] > edge then self[dir] = edge end
96
   end
97
end