-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplaydate.lua
329 lines (282 loc) · 8.36 KB
/
playdate.lua
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
local module = {}
playdate = module
require("playbit.geometry")
-- ████████╗██╗███╗ ███╗███████╗
-- ╚══██╔══╝██║████╗ ████║██╔════╝
-- ██║ ██║██╔████╔██║█████╗
-- ██║ ██║██║╚██╔╝██║██╔══╝
-- ██║ ██║██║ ╚═╝ ██║███████╗
-- ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
function module.getTime()
local seconds = os.time()
local date = os.date("*t", seconds)
return {
year = date.year,
month = date.month,
day = date.day,
weekday = date.wday,
hour = date.hour,
minute = date.min,
second = date.sec,
-- TODO: PD also returns milliseconds to the next second, but time functions in native lua don't have millisecond precision
millisecond = 0,
}
end
function module.getCurrentTimeMilliseconds()
return love.timer.getTime() * 1000
end
function module.getSecondsSinceEpoch()
-- os.time() without params always returns in system local time, so we must convert to UTC
local nowLocal = os.time()
local nowTable = os.date("!*t", nowLocal)
local nowUtc = os.time(nowTable)
-- Playdate epoch, as described: https://sdk.play.date/2.6.0/Inside%20Playdate.html#f-getSecondsSinceEpoch
local playdateEpochUtc = os.time({
year = 2000,
month = 1,
day = 1,
hour = 0,
min = 0,
sec = 0,
})
-- TODO: PD also returns milliseconds to the next second, but time functions in native lua don't have millisecond precision
local milliseconds = 0
return os.difftime(nowUtc, playdateEpochUtc), milliseconds
end
-- ██╗███╗ ██╗██████╗ ██╗ ██╗████████╗
-- ██║████╗ ██║██╔══██╗██║ ██║╚══██╔══╝
-- ██║██╔██╗ ██║██████╔╝██║ ██║ ██║
-- ██║██║╚██╗██║██╔═══╝ ██║ ██║ ██║
-- ██║██║ ╚████║██║ ╚██████╔╝ ██║
-- ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝
local lastActiveJoystick = nil
local isCrankDocked = false
local crankPos = 0
local lastCrankPos = 0
module._buttonToKey = {
up = "kb_up",
down = "kb_down",
left = "kb_left",
right = "kb_right",
a = "kb_s",
b = "kb_a",
}
module.kButtonA = "a"
module.kButtonB = "b"
module.kButtonUp = "up"
module.kButtonDown = "down"
module.kButtonLeft = "left"
module.kButtonRight = "right"
local NONE = 0
local JUST_PRESSED = 1
local PRESSED = 2
local JUST_RELEASED = 3
local inputStates = {}
function module.buttonIsPressed(button)
local key = module._buttonToKey[button]
if not inputStates[key] then
-- no entry, assume no input
return false
end
return inputStates[key] == JUST_PRESSED or inputStates[key] == PRESSED
end
function module.buttonJustPressed(button)
local key = module._buttonToKey[button]
if not inputStates[key] then
-- no entry, assume no input
return false
end
return inputStates[key] == JUST_PRESSED
end
function module.buttonJustReleased(button)
local key = module._buttonToKey[button]
if not inputStates[key] then
-- no entry, assume no input
return false
end
return inputStates[key] == JUST_RELEASED
end
function module.getButtonState(button)
local key = module._buttonToKey[button]
local value = inputStates[key]
return value == PRESSED, value == PRESSED, value == JUST_RELEASED
end
function module.isCrankDocked()
if not lastActiveJoystick then
return isCrankDocked
end
-- TODO: is basing dock state on if stick is non-zero a bad assumption here?
-- will other games want a dedicated dock/undock button?
local x = math.abs(lastActiveJoystick:getAxis(3))
local y = math.abs(lastActiveJoystick:getAxis(4))
local len = math.sqrt(x * x + y * y)
-- TODO: deadzone sensitivity?
if len < 0.1 then
return true
end
return false
end
function module.getCrankChange()
local change = playbit.geometry.angleDiff(lastCrankPos, crankPos)
-- TODO: how does the playdate accelerate this?
local acceleratedChange = change
return change, acceleratedChange
end
-- TODO: acceleramator, emulate via leftstick, keyboard...?
function module.getCrankPosition()
if module.isCrankDocked() then
return 0
end
if not lastActiveJoystick then
return crankPos
end
local x = lastActiveJoystick:getAxis(3)
local y = lastActiveJoystick:getAxis(4)
local degrees = math.deg(math.atan2(-y, x))
if degrees < 0 then
return degrees + 360
end
return degrees
end
function love.joystickadded(joystick)
-- always take most recently added joystick as active joystick
lastActiveJoystick = joystick
end
function love.joystickremoved(joystick)
if lastActiveJoystick == nil then
return
end
if joystick:getID() == lastActiveJoystick:getID() then
lastActiveJoystick = nil
end
end
function love.gamepadpressed(joystick, gamepadButton)
lastActiveJoystick = joystick
inputStates["js_"..gamepadButton] = JUST_PRESSED
end
function love.gamepadreleased(joystick, gamepadButton)
lastActiveJoystick = joystick
inputStates["js_"..gamepadButton] = JUST_RELEASED
end
function love.mousepressed(x, y, button, istouch, presses)
if button ~= 3 then
return
end
isCrankDocked = not isCrankDocked
crankPos = 0
--[[ also reset lastCrankPos since on PD, you cant
dock the crank without rotating it back to 0 --]]
lastCrankPos = 0
end
function love.wheelmoved(x, y)
if isCrankDocked then
return
end
-- TODO: emulate PD crank acceleration?
-- TODO: configure scroll sensitivity?
crankPos = crankPos + -y * 6
if crankPos < 0 then
crankPos = 359
elseif crankPos > 359 then
crankPos = 0
end
end
-- emulate the keys that PD simulator supports
-- https://sdk.play.date/Inside%20Playdate.html#c-keyPressed
local supportedCallbackKeys = {
["1"] = true,
["2"] = true,
["3"] = true,
["4"] = true,
["5"] = true,
["6"] = true,
["7"] = true,
["8"] = true,
["9"] = true,
["0"] = true,
["q"] = true,
["w"] = true,
["e"] = true,
["r"] = true,
["t"] = true,
["y"] = true,
["u"] = true,
["i"] = true,
["o"] = true,
["p"] = true,
["a"] = true,
["s"] = true,
["d"] = true,
["f"] = true,
["g"] = true,
["h"] = true,
["j"] = true,
["k"] = true,
["l"] = true,
["z"] = true,
["x"] = true,
["c"] = true,
["v"] = true,
["b"] = true,
["n"] = true,
["m"] = true,
[";"] = true,
["'"] = true,
[","] = true,
["."] = true,
["/"] = true,
["\\"] = true,
["`"] = true,
}
function love.keypressed(key)
inputStates["kb_"..key] = JUST_PRESSED
--[[ Playdate only has a limited range of supported keys, so Playbit exposes the separate
`playbit.keyPressed` handler so that it can be used to listen to any keypress under love2d. ]]--
if playbit.keyPressed then
playbit.keyPressed(key)
end
if supportedCallbackKeys[key] then
if playdate.keyPressed then
playdate.keyPressed(key)
end
end
end
function love.keyreleased(key)
inputStates["kb_"..key] = JUST_RELEASED
if playbit.keyReleased then
playbit.keyReleased(key)
end
if supportedCallbackKeys[key] then
if playdate.keyReleased then
playdate.keyReleased(key)
end
end
end
function module.updateInput()
-- only update keys that are mapped
for k,v in pairs(module._buttonToKey) do
if inputStates[v] == JUST_PRESSED then
inputStates[v] = PRESSED
elseif inputStates[v] == JUST_RELEASED then
inputStates[v] = NONE
end
end
lastCrankPos = crankPos
end
-- ██╗ ██╗ ██╗ █████╗
-- ██║ ██║ ██║██╔══██╗
-- ██║ ██║ ██║███████║
-- ██║ ██║ ██║██╔══██║
-- ███████╗╚██████╔╝██║ ██║
-- ╚══════╝ ╚═════╝ ╚═╝ ╚═╝
function table.indexOfElement(table, element)
for i = 1, #table do
if table[i] == element then
return i
end
end
return nil
end
function printTable(...)
error("not implemented!")
end