/zoeplat

To get this branch, use:
bzr branch http://9ix.org/bzr/zoeplat

« back to all changes in this revision

Viewing changes to main.lua

  • Committer: Josh C
  • Date: 2013-03-12 17:21:28 UTC
  • Revision ID: josh@9ix.org-20130312172128-l336vwqawo81c6sm
really easy version of knowing when we reached the top of a wall.  
similar to how we're doing onGround.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
DEBUG = true
3
3
 
4
4
require 'zoetrope'
 
5
__ = require 'underscore'
 
6
--inspect = require 'inspect'
5
7
 
6
 
Player = Tile:extend {
 
8
Player = Animation:extend {
7
9
   image = 'data/player.png',
 
10
   height = 32,
 
11
   width = 32,
 
12
   sequences = {
 
13
      stand = { frames = { 1 }, fps = 1 },
 
14
      walk = { frames = { 2, 3 }, fps = 5 },
 
15
      jump = { frames = { 4 }, fps = 1 }
 
16
   },
 
17
   collisions = {},
 
18
   onWall = false,
8
19
   onNew = function (self)
9
20
              self.velocity.y = 0
10
21
              self.maxVelocity.y = 400
11
22
           end,
 
23
   doPhysics = function (self, dir, elapsed)
 
24
                  local vel = self.velocity
 
25
                  local acc = self.acceleration
 
26
                  local drag = self.drag
 
27
                  local minVel = self.minVelocity
 
28
                  local maxVel = self.maxVelocity
 
29
 
 
30
                  -- check existence of properties
 
31
 
 
32
                  if STRICT then
 
33
                     assert(vel, 'active sprite has no velocity property')
 
34
                     assert(acc, 'active sprite has no acceleration property')
 
35
                     assert(drag, 'active sprite has no drag property')
 
36
                     assert(minVel, 'active sprite has no minVelocity property')
 
37
                     assert(maxVel, 'active sprite has no maxVelocity property')
 
38
                     assert(__.include({'x','y','rotation'}, dir), 'direction should be x, y, or rotation')
 
39
                  end
 
40
 
 
41
                  vel.x = vel.x or 0
 
42
                  vel.y = vel.y or 0
 
43
                  vel.rotation = vel.rotation or 0
 
44
 
 
45
                  -- physics
 
46
 
 
47
                  if acc[dir] and acc[dir] ~= 0 then
 
48
                     vel[dir] = vel[dir] + acc[dir] * elapsed
 
49
                  else
 
50
                     if drag[dir] then
 
51
                        if vel[dir] > 0 then
 
52
                           vel[dir] = vel[dir] - drag[dir] * elapsed
 
53
                           if vel[dir] < 0 then vel[dir] = 0 end
 
54
                        elseif vel[dir] < 0 then
 
55
                           vel[dir] = vel[dir] + drag[dir] * elapsed
 
56
                           if vel[dir] > 0 then vel[dir] = 0 end
 
57
                        end
 
58
                     end
 
59
                  end
 
60
 
 
61
                  if minVel[dir] and vel[dir] < minVel[dir] then vel[dir] = minVel[dir] end
 
62
                  if maxVel[dir] and vel[dir] > maxVel[dir] then vel[dir] = maxVel[dir] end
 
63
 
 
64
                  if vel[dir] ~= 0 then self[dir] = self[dir] + vel[dir] * elapsed end
 
65
               end,
12
66
   onStartFrame = function (self)
13
67
                     -- this is all in startframe so it happens before
14
68
                     -- physics calc at beginning of update
15
69
 
16
 
                     self.velocity.x = 0
 
70
                     -- jumping/falling updates could go in EndFrame...
 
71
                     self.falling = self.velocity.y > 0
 
72
                     if self.falling then self.jumping = false end
 
73
                     --print(self.jumping, self.falling)
 
74
 
 
75
                     if (not self.onGround) and (not self.onWall) then
 
76
                        self:play('jump')
 
77
                     end
 
78
 
17
79
                     self.acceleration.y = 800
18
80
 
 
81
                     if self.onWall then
 
82
                        self.acceleration.y = 0
 
83
 
 
84
                        if the.keys:pressed('up') then
 
85
                           self.velocity.y = -200
 
86
                           self:play('stand')
 
87
                        elseif the.keys:pressed('down') then
 
88
                           self.velocity.y = 200
 
89
                           self:play('stand')
 
90
                        else
 
91
                           self.velocity.y = 0
 
92
                           self:play('stand')
 
93
                        end
 
94
                     end
 
95
 
19
96
                     if the.keys:pressed('left') then
20
97
                        self.velocity.x = -200
 
98
                        if self.onGround then self:play('walk') end
 
99
                        if self.onWall == 'right' then self.onWall = false end
21
100
                     elseif the.keys:pressed('right') then
22
101
                        self.velocity.x = 200
 
102
                        if self.onGround then self:play('walk') end
 
103
                        if self.onWall == 'left' then self.onWall = false end
 
104
                     else
 
105
                        if self.onGround then self:play('stand') end
 
106
                        if not self.onWall then
 
107
                           self.velocity.x = 0
 
108
                        end
23
109
                     end
24
110
 
25
 
                     if the.keys:justPressed('up') then
 
111
                     if the.keys:justPressed('up') and self.onGround then
26
112
                        self.velocity.y = -400
 
113
                        self.jumping = true
27
114
                     end
28
115
                  end,
 
116
   update = function (self, elapsed)
 
117
               -- NOTE: this is an override, not a callback
 
118
 
 
119
               self:doPhysics('x', elapsed)
 
120
               self:collide(the.view.map)
 
121
 
 
122
               -- handle X collisions
 
123
               self.onWall = false
 
124
               for _, col in ipairs(self.collisions) do
 
125
                  col.other:displaceDir(self, 'x')
 
126
                  if self.velocity.x > 0 then
 
127
                     self.onWall = 'right'
 
128
                  elseif self.velocity.x < 0 then
 
129
                     self.onWall = 'left'
 
130
                  else
 
131
                     print 'x ??'
 
132
                  end
 
133
               end
 
134
 
 
135
               self.onGround = false -- right before Y collision callbacks
 
136
               self:doPhysics('y', elapsed)
 
137
               self:collide(the.view.map)
 
138
 
 
139
               -- handle Y collisions
 
140
               for _, col in ipairs(self.collisions) do
 
141
                  if self.velocity.y > 0 then
 
142
                     self.onGround = true
 
143
                  end
 
144
 
 
145
                  col.other:displaceDir(self, 'y')
 
146
                  self.velocity.y = 0
 
147
                  self.jumping = false
 
148
               end
 
149
 
 
150
               Animation.update(self, elapsed)
 
151
            end,
 
152
   collide = function (self, ...)
 
153
                self.collisions = {}
 
154
                Animation.collide(self, ...)
 
155
                -- I could return a true/false value here if I wanted to...
 
156
             end,
29
157
   onCollide = function (self, other, xOverlap, yOverlap)
30
 
                  -- seriously, why does this even fire?
31
158
                  if other == the.view.map then return end
32
159
 
33
 
                  --print(string.format('col s{x=%i y=%i w=%i h=%i} %s', self.x, self.y, self.width, self.height, tostring(other)))
34
 
                  --print('vel.x:'..self.velocity.x.." vel.y:"..self.velocity.y)
35
 
 
36
 
                  -- assumption: any other collision is with a solid map tile
37
 
                  if yOverlap > xOverlap then
38
 
                     other:displace(self)
39
 
                  elseif xOverlap > yOverlap then
40
 
                     -- check if we've moved since collisions were generated
41
 
                     local xov, yov = self:overlap(other.x, other.y,
42
 
                                                   other.width, other.height)
43
 
                     if xov ~= 0 and yov ~= 0 then
44
 
                        self.velocity.y = 0
45
 
                        other:displace(self)
46
 
                     end
47
 
                  else
48
 
                     print('??')
49
 
                  end
50
 
 
 
160
                  table.insert(self.collisions, {other = other,
 
161
                                                 xOverlap = xOverlap,
 
162
                                                 yOverlap = yOverlap })
51
163
               end
52
164
}
53
165
 
 
166
-- displace on a specific axis (monkey patch Sprite)
 
167
function Sprite:displaceDir(other, dir)
 
168
   if not self.solid or self == other or not other.solid then return end
 
169
   if STRICT then assert(other:instanceOf(Sprite), 'asked to displace a non-sprite') end
 
170
 
 
171
   if other.sprites then
 
172
      -- handle groups
 
173
 
 
174
      for _, spr in pairs(other.sprites) do
 
175
         self:displace(spr, dir)
 
176
      end
 
177
   else
 
178
      -- handle sprites
 
179
      local dim
 
180
      if dir == 'x' then
 
181
         dim = 'width'
 
182
      elseif dir == 'y' then
 
183
         dim = 'height'
 
184
      else
 
185
         print 'dir ??'
 
186
      end
 
187
 
 
188
      local negMove = (other[dir] - self[dir]) + other[dim]
 
189
      local posMove = (self[dir] + self[dim]) - other[dir]
 
190
 
 
191
      -- TODO: re-add hinting?
 
192
      if negMove < posMove then
 
193
         chg = - negMove
 
194
      else
 
195
         chg = posMove
 
196
      end
 
197
   end
 
198
 
 
199
   other[dir] = other[dir] + chg
 
200
end
 
201
 
54
202
GameView = View:extend {
55
203
   onNew = function (self)
56
204
              self:loadLayers('data/map.lua')
59
207
           end,
60
208
   onUpdate = function (self)
61
209
                 --print('tick')
62
 
                 the.player:collide(self.map)
 
210
                 --the.player:collide(self.map)
63
211
                 --self.map:collide(the.player)
64
212
              end
65
213
}
67
215
the.app = App:new {
68
216
   onRun = function (self)
69
217
              self.view = GameView:new()
 
218
              self.console:watch('onGround', 'the.player.onGround')
 
219
              self.console:watch('onWall', 'the.player.onWall')
70
220
           end,
71
221
   onUpdate = function (self, dt)
72
 
                 -- apparently I can do this w/ C-A-q if DEBUG is on
73
 
                 -- if the.keys:justPressed('escape') then
74
 
                 --    love.event.quit()
75
 
                 -- end
 
222
                 if the.keys:justPressed('escape') and 
 
223
                   not self.console.visible then
 
224
                    self.quit()
 
225
                 end
76
226
              end
77
227
}
 
 
b'\\ No newline at end of file'