/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-16 19:31:02 UTC
  • Revision ID: josh@9ix.org-20130316193102-68imraus0srbj653
don't go off the edge

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'
5
6
--inspect = require 'inspect'
6
 
--_ = require 'underscore'
 
7
require 'pepperprof'
 
8
 
 
9
util = {
 
10
   dim = function(dir)
 
11
      if dir == 'x' then
 
12
         return 'width'
 
13
      elseif dir == 'y' then
 
14
         return 'height'
 
15
      else
 
16
         print 'dir ??'
 
17
      end
 
18
   end
 
19
}
7
20
 
8
21
Player = Animation:extend {
9
22
   image = 'data/player.png',
12
25
   sequences = {
13
26
      stand = { frames = { 1 }, fps = 1 },
14
27
      walk = { frames = { 2, 3 }, fps = 5 },
15
 
      jump = { frames = { 4 }, fps = 1 }
 
28
      jump = { frames = { 4 }, fps = 1 },
 
29
      climbLeft = { frames = { 5, 6 }, fps = 5 },
 
30
      climbRight = { frames = { 7, 8 }, fps = 5 }
16
31
   },
 
32
   collisions = {},
 
33
   onWall = false,
 
34
   leftWallAt = 0,
17
35
   onNew = function (self)
18
36
              self.velocity.y = 0
19
37
              self.maxVelocity.y = 400
20
38
           end,
 
39
   doPhysics = function (self, dir, elapsed)
 
40
                  local vel = self.velocity
 
41
                  local acc = self.acceleration
 
42
                  local drag = self.drag
 
43
                  local minVel = self.minVelocity
 
44
                  local maxVel = self.maxVelocity
 
45
 
 
46
                  -- check existence of properties
 
47
 
 
48
                  if STRICT then
 
49
                     assert(vel, 'active sprite has no velocity property')
 
50
                     assert(acc, 'active sprite has no acceleration property')
 
51
                     assert(drag, 'active sprite has no drag property')
 
52
                     assert(minVel, 'active sprite has no minVelocity property')
 
53
                     assert(maxVel, 'active sprite has no maxVelocity property')
 
54
                     assert(__.include({'x','y','rotation'}, dir), 'direction should be x, y, or rotation')
 
55
                  end
 
56
 
 
57
                  vel.x = vel.x or 0
 
58
                  vel.y = vel.y or 0
 
59
                  vel.rotation = vel.rotation or 0
 
60
 
 
61
                  -- physics
 
62
 
 
63
                  if acc[dir] and acc[dir] ~= 0 then
 
64
                     vel[dir] = vel[dir] + acc[dir] * elapsed
 
65
                  else
 
66
                     if drag[dir] then
 
67
                        if vel[dir] > 0 then
 
68
                           vel[dir] = vel[dir] - drag[dir] * elapsed
 
69
                           if vel[dir] < 0 then vel[dir] = 0 end
 
70
                        elseif vel[dir] < 0 then
 
71
                           vel[dir] = vel[dir] + drag[dir] * elapsed
 
72
                           if vel[dir] > 0 then vel[dir] = 0 end
 
73
                        end
 
74
                     end
 
75
                  end
 
76
 
 
77
                  if minVel[dir] and vel[dir] < minVel[dir] then vel[dir] = minVel[dir] end
 
78
                  if maxVel[dir] and vel[dir] > maxVel[dir] then vel[dir] = maxVel[dir] end
 
79
 
 
80
                  if vel[dir] ~= 0 then self[dir] = self[dir] + vel[dir] * elapsed end
 
81
 
 
82
                  if self[dir] < 0 then self[dir] = 0 end
 
83
                  local edge = the.view.map[util.dim(dir)] -
 
84
                               the.player[util.dim(dir)]
 
85
                  -- TODO: take map position into account
 
86
                  if self[dir] > edge then self[dir] = edge end
 
87
               end,
21
88
   onStartFrame = function (self)
22
89
                     -- this is all in startframe so it happens before
23
90
                     -- physics calc at beginning of update
27
94
                     if self.falling then self.jumping = false end
28
95
                     --print(self.jumping, self.falling)
29
96
 
30
 
                     if not self.onGround then
 
97
                     if (not self.onGround) and (not self.onWall) then
31
98
                        self:play('jump')
32
99
                     end
33
100
 
34
 
                     self.velocity.x = 0
35
101
                     self.acceleration.y = 800
36
102
 
 
103
                     if self.onWall then
 
104
                        self.acceleration.y = 0
 
105
 
 
106
                        if self.onWall == 'right' then
 
107
                           self:play('climbRight')
 
108
                        elseif self.onWall == 'left' then
 
109
                           self:play('climbLeft')
 
110
                        end
 
111
 
 
112
                        if the.keys:pressed('up') then
 
113
                           self.velocity.y = -200
 
114
                        elseif the.keys:pressed('down') then
 
115
                           self.velocity.y = 200
 
116
                        else
 
117
                           self.velocity.y = 0
 
118
                           self:freeze(self.sequences[self.currentName].frames[1])
 
119
                        end
 
120
                     end
 
121
 
37
122
                     if the.keys:pressed('left') then
38
123
                        self.velocity.x = -200
39
124
                        if self.onGround then self:play('walk') end
 
125
                        if self.onWall == 'right' then
 
126
                           self.onWall = false
 
127
                           self.leftWallAt = love.timer.getTime()
 
128
                        end
40
129
                     elseif the.keys:pressed('right') then
41
130
                        self.velocity.x = 200
42
131
                        if self.onGround then self:play('walk') end
 
132
                        if self.onWall == 'left' then
 
133
                           self.onWall = false
 
134
                           self.leftWallAt = love.timer.getTime()
 
135
                        end
43
136
                     else
44
 
                        if self.onGround then self:play('stand') end
 
137
                        if not self.onWall then
 
138
                           if self.onGround then self:play('stand') end
 
139
                           self.velocity.x = 0
 
140
                        end
45
141
                     end
46
142
 
47
 
                     if the.keys:justPressed('up') and self.onGround then
 
143
                     if the.keys:justPressed('up') and
 
144
                      (self.onGround or the.console.visible or
 
145
                       (love.timer.getTime() - self.leftWallAt < .1) ) then
48
146
                        self.velocity.y = -400
49
147
                        self.jumping = true
50
148
                     end
51
149
                  end,
52
 
   onUpdate = function (self)
53
 
                 -- needs to happen right before collision
54
 
                 self.onGround = false
55
 
                end,
 
150
   update = function (self, elapsed)
 
151
               -- NOTE: this is an override, not a callback
 
152
 
 
153
               self:doPhysics('x', elapsed)
 
154
               self:collide(the.view.map)
 
155
 
 
156
               -- handle X collisions
 
157
               self.onWall = false
 
158
               for _, col in ipairs(self.collisions) do
 
159
                  col.other:displaceDir(self, 'x')
 
160
                  if self.velocity.x > 0 then
 
161
                     self.onWall = 'right'
 
162
                  elseif self.velocity.x < 0 then
 
163
                     self.onWall = 'left'
 
164
                  else
 
165
                     print 'x ??'
 
166
                  end
 
167
               end
 
168
 
 
169
               self.onGround = false -- right before Y collision callbacks
 
170
               self:doPhysics('y', elapsed)
 
171
               self:collide(the.view.map)
 
172
 
 
173
               -- handle Y collisions
 
174
               for _, col in ipairs(self.collisions) do
 
175
                  if self.velocity.y > 0 then
 
176
                     self.onGround = true
 
177
                  end
 
178
 
 
179
                  col.other:displaceDir(self, 'y')
 
180
                  self.velocity.y = 0
 
181
                  self.jumping = false
 
182
               end
 
183
 
 
184
               Animation.update(self, elapsed)
 
185
            end,
 
186
   collide = function (self, ...)
 
187
                self.collisions = {}
 
188
                Animation.collide(self, ...)
 
189
                -- I could return a true/false value here if I wanted to...
 
190
             end,
56
191
   onCollide = function (self, other, xOverlap, yOverlap)
57
 
                  -- seriously, why does this even fire?
58
192
                  if other == the.view.map then return end
59
193
 
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)
62
 
 
63
 
                  -- assumption: any other collision is with a solid map tile
64
 
                  if yOverlap > xOverlap then
65
 
                     other:displace(self)
66
 
 
67
 
                     if self.velocity.x > 0 then
68
 
                        self.onWall = 'right'
69
 
                     elseif self.velocity.x < 0 then
70
 
                        self.onWall = 'left'
71
 
                     else
72
 
                        print '??'
73
 
                     end
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
81
 
                           self.onGround = true
82
 
                        end
83
 
 
84
 
                        self.velocity.y = 0
85
 
                        other:displace(self)
86
 
                        self.jumping = false
87
 
                     end
88
 
                  else
89
 
                     print('??')
90
 
                  end
91
 
 
92
 
               end,
 
194
                  table.insert(self.collisions, {other = other,
 
195
                                                 xOverlap = xOverlap,
 
196
                                                 yOverlap = yOverlap })
 
197
               end
93
198
}
94
199
 
 
200
-- displace on a specific axis (monkey patch Sprite)
 
201
function Sprite:displaceDir(other, dir)
 
202
   if not self.solid or self == other or not other.solid then return end
 
203
   if STRICT then assert(other:instanceOf(Sprite), 'asked to displace a non-sprite') end
 
204
 
 
205
   if other.sprites then
 
206
      -- handle groups
 
207
 
 
208
      for _, spr in pairs(other.sprites) do
 
209
         self:displace(spr, dir)
 
210
      end
 
211
   else
 
212
      -- handle sprites
 
213
      local dim = util.dim(dir)
 
214
 
 
215
      local negMove = (other[dir] - self[dir]) + other[dim]
 
216
      local posMove = (self[dir] + self[dim]) - other[dir]
 
217
 
 
218
      -- TODO: re-add hinting?
 
219
      if negMove < posMove then
 
220
         chg = - negMove
 
221
      else
 
222
         chg = posMove
 
223
      end
 
224
   end
 
225
 
 
226
   other[dir] = other[dir] + chg
 
227
end
 
228
 
95
229
GameView = View:extend {
96
230
   onNew = function (self)
97
231
              self:loadLayers('data/map.lua')
100
234
           end,
101
235
   onUpdate = function (self)
102
236
                 --print('tick')
103
 
                 the.player:collide(self.map)
 
237
                 --the.player:collide(self.map)
104
238
                 --self.map:collide(the.player)
105
239
              end
106
240
}
108
242
the.app = App:new {
109
243
   onRun = function (self)
110
244
              self.view = GameView:new()
111
 
              --print(inspect(_(the.app):keys()))
112
245
              self.console:watch('onGround', 'the.player.onGround')
113
246
              self.console:watch('onWall', 'the.player.onWall')
 
247
              self.console:watch('updateTook', 'the.updateTook')
 
248
              self.console:watch('drawTook', 'the.drawTook')
 
249
 
 
250
              --the.profiler = newProfiler('time', 2000)
 
251
              --the.profiler = newProfiler()
 
252
              --the.profiler:start()
114
253
           end,
115
254
   onUpdate = function (self, dt)
116
 
                 if the.keys:justPressed('escape') and 
117
 
                   not self.console.visible then
118
 
                    love.event.quit()
 
255
                 if the.keys:justPressed('escape') then
 
256
                    if the.profiler then
 
257
                       the.profiler:stop()
 
258
                       local outfile = io.open( "profile.txt", "w+" )
 
259
                       the.profiler:report( outfile )
 
260
                       outfile:close()
 
261
                    end
 
262
 
 
263
                    self.quit()
119
264
                 end
120
 
              end
121
 
}
 
 
b'\\ No newline at end of file'
 
265
              end,
 
266
   update = function (self, dt)
 
267
               the.updateStart = love.timer.getMicroTime()
 
268
               App.update(self, dt)
 
269
               if the.updateStart then
 
270
                  the.updateTook = love.timer.getMicroTime() - the.updateStart
 
271
               end
 
272
            end
 
273
}