Skip to content

Commit 8af2638

Browse files
committed
Improve input API; add consume function; fix typo
1 parent 41bbccc commit 8af2638

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

src/manager/input.lua

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ assert(type(core) == 'table' and core.version >= 1.0, 'InputManager works only w
1010
local log = core.import 'class.logger'
1111
local helper = core.import 'helper'
1212

13+
local pairs = _G.pairs
1314
local min = math.min
1415
local max = math.max
1516
local ceil = math.ceil
@@ -18,7 +19,7 @@ local setKeyRepeat = love.keyboard.setKeyRepeat
1819
local inputs = { }
1920

2021
local function bit(p)
21-
return 2 ^ (p - 1)
22+
return 2 ^ (p - 1)
2223
end
2324

2425
local function bitor(x, y)
@@ -48,15 +49,15 @@ local function bitxor(x, y)
4849
end
4950

5051
local function hasbit(x, p)
51-
return x % (p + p) >= p
52+
return x % (p + p) >= p
5253
end
5354

5455
local function setbit(x, p)
55-
return hasbit(x, p) and x or x + p
56+
return hasbit(x, p) and x or x + p
5657
end
5758

5859
local function clearbit(x, p)
59-
return hasbit(x, p) and x - p or x
60+
return hasbit(x, p) and x - p or x
6061
end
6162

6263
local function newInput()
@@ -80,10 +81,12 @@ local Manager = { frame = 0, delay = 0, timer = 0, buttons = { }, mapping = { },
8081
self.remoteplayers = 0
8182
self.keys = { }
8283
self.keymap = { }
84+
self.consumed = { }
8385
self:reset()
8486
local keys = kwargs.keys or { }
8587
for i = 1, #keys do
8688
self.keys[i] = { keys[i], bit(i) }
89+
self.consumed[i] = { }
8790
self.keymap[keys[i]] = i
8891
end
8992
if kwargs.mappings then
@@ -106,6 +109,9 @@ local Manager = { frame = 0, delay = 0, timer = 0, buttons = { }, mapping = { },
106109
self.buttons[p] = { }
107110
inputs[p] = newInput()
108111
end
112+
for p = self.localplayers + 1, self.localplayers + self.remoteplayers do
113+
inputs[p] = newInput()
114+
end
109115
end
110116

111117
--- Advance timer and frame.
@@ -116,16 +122,21 @@ local Manager = { frame = 0, delay = 0, timer = 0, buttons = { }, mapping = { },
116122

117123
--- Update inputs.
118124
function Manager:update()
119-
for i = 1, self.localplayers + self.remoteplayers do
120-
local it = inputs[i]
125+
for p = 1, self.localplayers + self.remoteplayers do
126+
local it = inputs[p]
121127
while it.prev and it.frame >= self.frame do
122128
it = it.prev
123129
end
124130
while it.next and it.next.frame <= self.frame do
125131
it = it.next
126132
end
133+
if it ~= inputs[p] then
134+
for k = 1, #self.consumed do
135+
self.consumed[k][p] = nil
136+
end
137+
end
127138
-- log:info('B%02d F%02d [%04x|%05d] -> [%04x|%05d] -> [%04x|%05d]', b, f, it.prev.data, it.prev.frame, it.data, it.frame, it.next.data, it.next.frame)
128-
inputs[i] = it
139+
inputs[p] = it
129140
end
130141
end
131142

@@ -159,13 +170,42 @@ local Manager = { frame = 0, delay = 0, timer = 0, buttons = { }, mapping = { },
159170
-- @return boolean
160171
-- @return number
161172
function Manager:hitted(button, player)
162-
local index = self.keymap[button]
163-
if index then
164-
index = self.keys[index][2]
173+
local keycode = self.keymap[button]
174+
if keycode then
175+
keycode = self.keys[keycode][2]
176+
local input = nil
177+
for p = player or 1, player or self.localplayers do
178+
input = inputs[p]
179+
local ishitted = input and input.frame == self.frame and hasbit(input.data, keycode)
180+
local prev = input and input.prev
181+
if ishitted and (not prev or prev.frame ~= self.frame and not hasbit(prev.data, keycode)) then
182+
return true, p
183+
end
184+
end
185+
end
186+
return false
187+
end
188+
189+
--- Check if button was pressed at this frame and consume it for next call.
190+
-- @param string button Hitted button.
191+
-- @param number player Player to check or nil to check any local player.
192+
-- @return boolean
193+
-- @return number
194+
function Manager:consume(button, player)
195+
local keycode = self.keymap[button]
196+
if keycode then
197+
local consumed = self.consumed[keycode]
165198
local input = nil
199+
keycode = self.keys[keycode][2]
166200
for p = player or 1, player or self.localplayers do
201+
if consumed[p] then
202+
return false
203+
end
167204
input = inputs[p]
168-
if input and input.frame == self.frame and hasbit(input.data, index) then
205+
local ishitted = input and input.frame == self.frame and hasbit(input.data, keycode)
206+
local prev = input and input.prev
207+
if ishitted and (not prev or prev.frame ~= self.frame and not hasbit(prev.data, keycode)) then
208+
consumed[p] = true
169209
return true, p
170210
end
171211
end
@@ -276,7 +316,7 @@ local Manager = { frame = 0, delay = 0, timer = 0, buttons = { }, mapping = { },
276316
left, right = right, right.next
277317
end
278318
if left and left.frame == timer then
279-
local xor = bitxor(left.data, input)
319+
-- TODO: fix this input merger
280320
local changes = bitxor(xor, left.changes)
281321
if bitor(xor, changes) == changes then
282322
left.data = input

0 commit comments

Comments
 (0)