/ld27

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

« back to all changes in this revision

Viewing changes to zoetrope/core/gamepad.lua

  • Committer: Josh C
  • Date: 2013-08-25 02:04:52 UTC
  • Revision ID: josh@9ix.org-20130825020452-py8fijli8m5te5gv
improve performance with (sketchy, experimental) sprite batches

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
--
2
 
--
3
 
--
4
 
--              <Sprite>
5
 
 
6
 
Gamepad = Sprite:extend
7
 
{
8
 
        -- Property: number
9
 
        -- The index of the gamepad, starting at 1.
10
 
 
11
 
        -- Property: name
12
 
        -- The name of the gamepad, e.g. "XBox Controller".
13
 
 
14
 
        -- Property: numAxes
15
 
        -- The number of available axes, e.g. for analog controls.
16
 
 
17
 
        -- Property: numBalls
18
 
        -- The number of available balls.
19
 
 
20
 
        -- Property: numButtons
21
 
        -- The number of available buttons.
22
 
 
23
 
        -- Property: numHats
24
 
        -- The number of available hats, e.g. digital movement controls.
25
 
 
26
 
        -- Property: axes
27
 
        -- The state of all analog axes on the gamepad, indexed by number.
28
 
        -- Values range from -1 to 1, where 0 is completely neutral.
29
 
 
30
 
        -- Property: balls
31
 
        -- The amount of motion by a each ball on the gamepad, indexed by number.
32
 
        -- Not sure what the range of values is here.
33
 
 
34
 
        -- Property: hats
35
 
        -- The state of each hat on the gamepad, indexed by number. Each one has
36
 
        -- one of these values: https://love2d.org/wiki/JoystickConstant
37
 
 
38
 
        -- Property: deadZone
39
 
        -- Any motion by an analog control (from 0 to 1) less than this value is
40
 
        -- ignored when simulating digital controls.
41
 
 
42
 
        deadZone = 0.1,
43
 
 
44
 
        -- private property: _thisFrame
45
 
        -- what keys are pressed this frame
46
 
        -- if you are interested in this, use allPressed() instead
47
 
 
48
 
        _thisFrame = {},
49
 
 
50
 
        -- private property: _lastFrame
51
 
        -- what buttons were pressed last frame
52
 
 
53
 
        _lastFrame = {},
54
 
 
55
 
        new = function (self, obj)
56
 
                obj = self:extend(obj)
57
 
                assert(type(obj.number) == 'number', 'must set a gamepad number')
58
 
 
59
 
                obj.axes = {}
60
 
                obj.balls = {}
61
 
                obj.hats = {}
62
 
 
63
 
                if obj.number <= love.joystick.getNumJoysticks() then
64
 
                        if not love.joystick.isOpen(obj.number) then love.joystick.open(obj.number) end
65
 
                        obj.name = love.joystick.getName(obj.number)
66
 
                        obj.numAxes = love.joystick.getNumAxes(obj.number)
67
 
                        obj.numBalls = love.joystick.getNumBalls(obj.number)
68
 
                        obj.numButtons = love.joystick.getNumButtons(obj.number)
69
 
                        obj.numHats = love.joystick.getNumHats(obj.number)
70
 
 
71
 
                        -- set initial values for axes and balls
72
 
                        -- hat values are strings so nil comparisons are safe
73
 
 
74
 
                        for i = 1, obj.numAxes do
75
 
                                obj.axes[i] = 0
76
 
                        end
77
 
 
78
 
                        for i = 1, obj.numBalls do
79
 
                                obj.balls[i] = { x = 0, y = 0 }
80
 
                        end
81
 
                else
82
 
                        obj.name = 'NO DEVICE CONNECTED'
83
 
                        obj.numAxes = 0
84
 
                        obj.numBalls = 0
85
 
                        obj.numButtons = 0
86
 
                        obj.numHats = 0
87
 
                end
88
 
 
89
 
                love.joystickpressed = Gamepad._dispatchPress
90
 
                love.joystickreleased = Gamepad._dispatchRelease
91
 
                if obj.onNew then obj:onNew() end
92
 
                return obj
93
 
        end,
94
 
 
95
 
        -- Method: pressed
96
 
        -- Are *any* of the buttons passed held down this frame?
97
 
        --
98
 
        -- Arguments:
99
 
        --              button numbers passed as individual arguments
100
 
        --
101
 
        -- Returns:
102
 
        --              boolean
103
 
 
104
 
        pressed = function (self, ...)
105
 
                local buttons = {...}
106
 
 
107
 
                for _, value in pairs(buttons) do
108
 
                        if self._thisFrame[value] then
109
 
                                return true
110
 
                        end
111
 
                end
112
 
                
113
 
                return false
114
 
        end,
115
 
 
116
 
        -- Method: justPressed
117
 
        -- Are *any* of the buttons passed pressed for the first time this frame?
118
 
        --
119
 
        -- Arguments:
120
 
        --              button numbers passed as individual arguments
121
 
        --
122
 
        -- Returns:
123
 
        --              boolean
124
 
 
125
 
        justPressed = function (self, ...)
126
 
                local buttons = {...}
127
 
 
128
 
                for _, value in pairs(buttons) do
129
 
                        if self._thisFrame[value] and not self._lastFrame[value] then
130
 
                                return true
131
 
                        end
132
 
                end
133
 
                
134
 
                return false
135
 
        end,
136
 
 
137
 
        -- Method: released
138
 
        -- Are *all* of the buttons passed not held down this frame?
139
 
        --
140
 
        -- Arguments:
141
 
        --              button numbers passed as individual arguments
142
 
        --
143
 
        -- Returns:
144
 
        --              boolean
145
 
 
146
 
        released = function (self, ...)
147
 
                local buttons = {...}
148
 
        
149
 
                for _, value in pairs(buttons) do
150
 
                        if self._thisFrame[value] then
151
 
                                return false
152
 
                        end
153
 
                end
154
 
                
155
 
                return true
156
 
        end,
157
 
 
158
 
        -- Method: justReleased
159
 
        -- Are *any* of the buttons passed released after being held last frame?
160
 
        --
161
 
        -- Arguments:
162
 
        --              button numbers passed as individual arguments
163
 
        --
164
 
        -- Returns:
165
 
        --              boolean
166
 
 
167
 
        justReleased = function (self, ...)
168
 
                local buttons = {...}
169
 
        
170
 
                for _, value in pairs(buttons) do
171
 
                        if self._lastFrame[value] and not self._thisFrame[value] then
172
 
                                return true
173
 
                        end
174
 
                end
175
 
                
176
 
                return false
177
 
        end,
178
 
 
179
 
        -- Method: allPressed
180
 
        -- Returns all buttons currently pressed this frame.
181
 
        --
182
 
        -- Arguments:
183
 
        --              none
184
 
        --
185
 
        -- Returns:
186
 
        --              string button descriptions; if nothing is pressed, nil
187
 
 
188
 
        allPressed = function (self)
189
 
                local result = {}
190
 
 
191
 
                for key, value in pairs(self._thisFrame) do
192
 
                        if value then table.insert(result, key) end
193
 
                end
194
 
                
195
 
                return unpack(result)
196
 
        end,
197
 
 
198
 
        -- Method: allJustPressed
199
 
        -- Returns all buttons just pressed this frame.
200
 
        --
201
 
        -- Arguments:
202
 
        --              none
203
 
        --
204
 
        -- Returns:
205
 
        --              string button descriptions; if nothing is just pressed, nil
206
 
 
207
 
        allJustPressed = function (self)
208
 
                local result = {}
209
 
 
210
 
                for key, value in pairs(self._thisFrame) do
211
 
                        if value and not self._lastFrame[key] then table.insert(result, key) end
212
 
                end
213
 
                
214
 
                return unpack(result)
215
 
        end,
216
 
 
217
 
        -- Method: allJustReleased
218
 
        -- Returns all buttons just released this frame.
219
 
        --
220
 
        -- Arguments:
221
 
        --              none
222
 
        --
223
 
        -- Returns:
224
 
        --              string button descriptions; if nothing is just pressed, nil
225
 
 
226
 
        allJustReleased = function (self)
227
 
                local result = {}
228
 
 
229
 
                for key, value in pairs(self._thisFrame) do
230
 
                        if not value and self._lastFrame[key] then table.insert(result, key) end
231
 
                end
232
 
                
233
 
                return unpack(result)
234
 
        end,
235
 
 
236
 
        buttonPressed = function (self, button)
237
 
                self._thisFrame[button] = true
238
 
        end,
239
 
 
240
 
        buttonReleased = function (self, button)
241
 
                self._thisFrame[button] = false
242
 
        end,
243
 
 
244
 
        endFrame = function (self, elapsed)
245
 
                -- move button values to the previous frame
246
 
 
247
 
                for key, value in pairs(self._thisFrame) do
248
 
                        self._lastFrame[key] = value
249
 
                end
250
 
 
251
 
                -- set values
252
 
 
253
 
                for i = 1, self.numAxes do
254
 
                        self.axes[i] = love.joystick.getAxis(self.number, i)
255
 
                end
256
 
 
257
 
                for i = 1, self.numBalls do
258
 
                        self.balls[i].x, self.balls[i].y = love.joystick.getBall(self.number, i)
259
 
                end
260
 
 
261
 
                for i = 1, self.numHats do
262
 
                        self.hats[i] = love.joystick.getHat(self.number, i)
263
 
                end
264
 
 
265
 
                -- simulate digital controls
266
 
 
267
 
                self._thisFrame['up'] = false
268
 
                self._thisFrame['down'] = false
269
 
                self._thisFrame['left'] = false
270
 
                self._thisFrame['right'] = false
271
 
 
272
 
                if self.numHats > 0 then
273
 
                        local hat = self.hats[1]
274
 
 
275
 
                        if hat == 'u' then
276
 
                                self._thisFrame['up'] = true
277
 
                        elseif hat == 'd' then
278
 
                                self._thisFrame['down'] = true
279
 
                        elseif hat == 'l' then
280
 
                                self._thisFrame['left'] = true
281
 
                        elseif hat == 'r' then
282
 
                                self._thisFrame['right'] = true
283
 
                        elseif hat == 'lu' then
284
 
                                self._thisFrame['up'] = true
285
 
                                self._thisFrame['left'] = true
286
 
                        elseif hat == 'ru' then
287
 
                                self._thisFrame['up'] = true
288
 
                                self._thisFrame['right'] = true
289
 
                        elseif hat == 'ld' then
290
 
                                self._thisFrame['down'] = true
291
 
                                self._thisFrame['left'] = true
292
 
                        elseif hat == 'rd' then
293
 
                                self._thisFrame['down'] = true
294
 
                                self._thisFrame['right'] = true
295
 
                        end
296
 
                end
297
 
 
298
 
                if self.numAxes > 1 then
299
 
                        local xAxis = self.axes[1]
300
 
                        local yAxis = self.axes[2]
301
 
 
302
 
                        if math.abs(xAxis) > self.deadZone then
303
 
                                if xAxis < 0 then
304
 
                                        self._thisFrame['left'] = true
305
 
                                else
306
 
                                        self._thisFrame['right'] = true
307
 
                                end
308
 
                        end
309
 
 
310
 
                        if math.abs(yAxis) > self.deadZone then
311
 
                                if yAxis < 0 then
312
 
                                        self._thisFrame['up'] = true
313
 
                                else
314
 
                                        self._thisFrame['down'] = true
315
 
                                end
316
 
                        end
317
 
                end
318
 
        
319
 
                Sprite.endFrame(self)
320
 
        end,
321
 
 
322
 
        -- private method: _dispatchPress
323
 
        -- receives a Love joystickpressed callback and hands it off
324
 
        -- to the appropriate gamepad.
325
 
 
326
 
        _dispatchPress = function (number, button)
327
 
                if the.gamepads[number] then
328
 
                        the.gamepads[number]:buttonPressed(button)
329
 
                end
330
 
        end,
331
 
 
332
 
        -- private method: _dispatchRelease
333
 
        -- receives a Love joystickreleased callback and hands it off
334
 
        -- to the appropriate gamepad.
335
 
 
336
 
        _dispatchRelease = function (number, button)
337
 
                if the.gamepads[number] then
338
 
                        the.gamepads[number]:buttonReleased(button)
339
 
                end
340
 
        end
341
 
}