/ld27

To get this branch, use:
bzr branch /bzr/ld27
1 by Josh C
zoetrope 1.4
1
-- Class: Keys
2
-- This tracks the state of the keyboard, i.e. if a key
3
-- was just pressed or released this frame. You can look
4
-- up a key either by its name or its Unicode number.
5
-- Not all keys sensed have Unicode equivalents (e.g. modifiers
6
-- like Control or Alt).
7
--
8
-- Only one Keys object can be active at one time. The one currently
9
-- listening to the keyboard can be accessed globally via <the>.keys.
10
--
11
-- See http://love2d.org/wiki/KeyConstant for a list of key names.
12
-- This class aliases modifiers for you, so that if you want to check
13
-- whether either the left or right Control key is pressed, you can check
14
-- on 'ctrl' instead of both 'lctrl' and 'rctrl'.
15
--
16
-- Extends:
17
--		<Sprite>
18
19
Keys = Sprite:extend
20
{
21
	visible = false,
22
23
	-- Property: typed
24
	-- This is literally what is being typed during the current frame.
25
	-- e.g. if the user holds the shift key and presses the 'a' key,
26
	-- this will be set to 'A'. Consult <allPressed()> if you
27
	-- want to know what specific keys are being pressed.
28
29
	typed = '',
30
31
	-- private property: _thisFrame
32
	-- what keys are pressed this frame
33
	-- if you are interested in this, use allPressed() instead
34
35
	_thisFrame = {},
36
37
	-- private property: _lastFrame
38
	-- what keys were pressed last frame
39
	
40
	_lastFrame = {},
41
	
42
	new = function (self, obj)
43
		obj = self:extend(obj)
44
		the.keys = obj
45
		love.keypressed = function (key, unicode) obj:keyPressed(key, unicode) end
46
		love.keyreleased = function (key, unicode) obj:keyReleased(key, unicode) end
47
		if obj.onNew then obj:onNew() end
48
		return obj
49
	end,
50
	
51
	-- Method: pressed
52
	-- Are *any* of the keys passed held down this frame?
53
	--
54
	-- Arguments:
55
	--		string key descriptions passed as individual arguments
56
	--
57
	-- Returns:
58
	-- 		boolean
59
60
	pressed = function (self, ...)
61
		local keys = {...}
62
		for _, value in pairs(keys) do
63
			if STRICT then
64
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
65
			end
66
67
			if self._thisFrame[value] then
68
				return true
69
			end
70
		end
71
		
72
		return false
73
	end,
74
75
	-- Method: justPressed
76
	-- Are *any* of the keys passed pressed for the first time this frame?
77
	--
78
	-- Arguments:
79
	--		string key descriptions passed as individual arguments
80
	--
81
	-- Returns:
82
	-- 		boolean
83
84
	justPressed = function (self, ...)
85
		local keys = {...}
86
87
		for _, value in pairs(keys) do
88
			if STRICT then
89
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
90
			end
91
92
			if self._thisFrame[value] and not self._lastFrame[value] then
93
				return true
94
			end
95
		end
96
		
97
		return false
98
	end,
99
100
	-- Method: released
101
	-- Are *all* of the keys passed not held down this frame?
102
	-- 
103
	-- Arguments:
104
	--		string key descriptions passed as individual arguments
105
	--
106
	-- Returns:
107
	-- 		boolean
108
109
	released = function (self, ...)
110
		local keys = {...}
111
112
		for _, value in pairs(keys) do
113
			if STRICT then
114
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
115
			end
116
117
			if self._thisFrame[value] then
118
				return false
119
			end
120
		end
121
		
122
		return true
123
	end,
124
125
	-- Method: justReleased
126
	-- Are *any* of the keys passed released after being held last frame?
127
	--
128
	-- Arguments:
129
	--		string key descriptions passed as individual arguments
130
	--
131
	-- Returns:
132
	-- 		boolean
133
134
	justReleased = function (self, ...)
135
		local keys = {...}
136
137
		for _, value in pairs(keys) do
138
			if STRICT then
139
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
140
			end
141
142
			if self._lastFrame[value] and not self._thisFrame[value] then
143
				return true
144
			end
145
		end
146
		
147
		return false
148
	end,
149
150
	-- Method: allPressed
151
	-- Returns all buttons currently pressed this frame.
152
	--
153
	-- Arguments:
154
	--		none
155
	--
156
	-- Returns:
157
	--		string key descriptions; if nothing is pressed, nil
158
159
	allPressed = function (self)
160
		local result = {}
161
162
		for key, value in pairs(self._thisFrame) do
163
			if value then table.insert(result, key) end
164
		end
165
		
166
		return unpack(result)
167
	end,
168
169
	-- Method: allJustPressed
170
	-- Returns all keys just pressed this frame.
171
	--
172
	-- Arguments:
173
	--		none
174
	--
175
	-- Returns:
176
	--		string key descriptions; if nothing is just pressed, nil
177
178
	allJustPressed = function (self)
179
		local result = {}
180
181
		for key, value in pairs(self._thisFrame) do
182
			if value and not self._lastFrame[key] then table.insert(result, key) end
183
		end
184
		
185
		return unpack(result)
186
	end,
187
188
	-- Method: allJustReleased
189
	-- Returns all keys just released this frame.
190
	--
191
	-- Arguments:
192
	--		none
193
	--
194
	-- Returns:
195
	--		string key descriptions; if nothing is just pressed, nil
196
197
	allJustReleased = function (self)
198
		local result = {}
199
200
		for key, value in pairs(self._thisFrame) do
201
			if not value and self._lastFrame[key] then table.insert(result, key) end
202
		end
203
		
204
		return unpack(result)
205
	end,
206
207
	-- Converts a character code to a Unicode string
208
	-- see http://stackoverflow.com/questions/7780179/what-is-the-way-to-represent-a-unichar-in-lua/7799843
209
210
	unicodeChar = function (self, code)
211
		if code == nil then return nil end
212
		if code < 32 then return string.format('\\x%02x', code) end
213
		if code < 126 then return string.char(code) end
214
		if code < 65539 then return string.format("\\u%04x", code) end
215
		if code < 1114111 then return string.format("\\u%08x", code) end
216
	end,
217
218
	-- Connects to the love.keypressed callback
219
220
	keyPressed = function (self, key, unicode)
221
		self._thisFrame[key] = true
222
		if unicode and unicode >= 0x20 and unicode ~= 127 and unicode < 0x3000 then
223
			self.typed = self.typed .. self:unicodeChar(unicode)
224
		end
225
226
		-- aliases for modifiers
227
228
		if key == 'rshift' or key == 'lshift' or
229
		   key == 'rctrl' or key == 'lctrl' or
230
		   key == 'ralt' or key == 'lalt' or
231
		   key == 'rmeta' or key == 'lmeta' or
232
		   key == 'rsuper' or key == 'lsuper' then
233
			self._thisFrame[string.sub(key, 2)] = true
234
		end
235
	end,
236
237
	-- Connects to the love.keyreleased callback
238
239
	keyReleased = function (self, key, unicode)
240
		self._thisFrame[key] = false
241
242
		-- aliases for modifiers
243
244
		if key == 'rshift' or key == 'lshift' or
245
		   key == 'rctrl' or key == 'lctrl' or
246
		   key == 'ralt' or key == 'lalt' or
247
		   key == 'rmeta' or key == 'lmeta' or
248
		   key == 'rsuper' or key == 'lsuper' then
249
			self._thisFrame[string.sub(key, 2)] = false
250
		end
251
	end,
252
253
	endFrame = function (self, elapsed)
254
		for key, value in pairs(self._thisFrame) do
255
			self._lastFrame[key] = value
256
		end
257
258
		self.typed = ''
259
		Sprite.endFrame(self, elapsed)
260
	end,
261
262
	update = function() end
263
}