/ld27

To get this branch, use:
bzr branch /bzr/ld27
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