Input - kuimoani/defold GitHub Wiki
Input
์ด ๋งค๋ด์ผ์ ์ ๋ ฅ ๋์(input action)์ ์บก์ณํ๊ณ ์ํธ์์ฉ ์คํฌ๋ฆฝํธ์ ๋ฐ์(interactive script reactions)์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํฉ๋๋ค.
Defold๋ ๋ค์ํ ์ฅ์น๋ก๋ถํฐ ์ ๋ ฅ์ ๋ฐ์ ์ ์์ผ๋ฉฐ ์ฌ์ฉ์์ ์ค๊ณ์ ์ผ์นํ๋ ์คํฌ๋ฆฝํธ ๋ก์ง์ ์์ฑํ ์ ์์ต๋๋ค. Defold๊ฐ ์ง์ํ๋ ์ ๋ ฅ์ฅ์น์ ์ข ๋ฅ๋ ์๋์ ๊ฐ์ต๋๋ค.
- ํค๋ณด๋ (ํค ์ ๋ ฅ ๋ฐ ํ ์คํธ ์ ๋ ฅ)
- ๋ง์ฐ์ค (๋ง์ฐ์คํ ๋์ ํฌํจ)
- ๋ฉํฐํฐ์น (iOS ๋ฐ Android ๊ธฐ๊ธฐ)
- ๊ฒ์ํจ๋ (์ด์์ฒด์ ๋ฅผ ํตํด ์ง์๋จ)
MS์๋์ฐ์์๋ ํ์ฌ XBox 360 ์ปจํธ๋กค๋ฌ๋ง ์ง์๋ฉ๋๋ค. 360 ์ปจํธ๋กค๋ฌ๋ฅผ ์๋์ฐ ์ฅ์น์ ์ฐ๊ฒฐํ๋ ค๋ฉด ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ ์ด ๋์๋์ง ํ์ธํ๊ณ http://www.wikihow.com/Use-Your-Xbox-360-Controller-for-Windows ๋ฅผ ์ฐธ๊ณ ๋ฐ๋๋๋ค.
๋ชจ๋ ์ ์ ์ ๋ ฅ์ ์์ง์ ์ํด ์์ง(capture)๋๋ฉฐ ๊ฒ์ ์ค๋ธ์ ํธ์ ์คํฌ๋ฆฝํธ๋ GUI ์คํฌ๋ฆฝํธ๋ก ์ ๋ฌ(dispatch)๋์ด ์ ๋ ฅ ํฌ์ปค์ค๋ฅผ ํ๋ํ๊ณ on_input() ํจ์๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
์ ๋ ฅ์ด ์คํฌ๋ฆฝํธ์ ๋๋ฌํ๊ธฐ ์ ์ ์ ๋ ฅ ๋ฐ์ธ๋ฉ(input bindings)๋ฅผ ํตํด ์๋ฏธ ์๋ ๋์(meaningful actions)์ผ๋ก ๋ฒ์ญ๋ฉ๋๋ค.

์ ๋ ฅ ํฌ์ปค์ค๋ฅผ ํ๋ํ ์ปดํฌ๋ํธ์ ๋ฐ๋ผ์ ์ด ์ ๋ ฅ์ ๊ทธ๋ฅ ๋๊ฒจ๋ฒ๋ฆด์ง on_input() ํจ์๋ก ๋๋ฌํ๋์ง ์ํ๋์ง๊ฐ ๊ฒฐ์ ๋๊ฒ ๋ฉ๋๋ค. ์๋์์ ์ด๋ค์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์์ธํ ์ดํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Input bindings
์ ๋ ฅ ๋ฐ์ธ๋ฉ์ Lua ์คํฌ๋ฆฝํธ๋ก ์ ๋ ฅ๊ฐ์ ๋ณด๋ด๊ธฐ ์ด์ ์ ์์ ์ ๋ ฅ(raw input)์ ์๋ฏธ ์๋ actions์ผ๋ก ๋ฒ์ญํ๊ธฐ ์ํ ํ ์ด๋ธ์ ๋๋ค. ์ ๋ ฅ ๋ฐ์ธ๋ฉ์ ๊ธฐ๋ณธ์ ์ผ๋ก "game.input_binding"๋ผ๋ ์ด๋ฆ์ผ๋ก ํ๋ก์ ํธ ๋ฃจํธ์ "input" ํด๋์ ์์นํด ์์ต๋๋ค. ํ์ง๋ง ์์ง์ด ๋ฐ์ธ๋ฉ์ ์ฐพ์ ์ ์๋๋ก ํ๋ก์ ํธ ์ ํ (Project settings ์ฐธ๊ณ )์ ์ ๋ฐ์ดํธํด์ ๊ฒฝ๋ก์ ์ด๋ฆ์ ์์ ํ ์๋ ์์ต๋๋ค.

์ฌ๊ธฐ ์ฅ์น๋ณ๋ก ํน์ ํ 5๊ฐ์ง ์ข ๋ฅ์ ํธ๋ฆฌ๊ฑฐ๊ฐ ์์ต๋๋ค.
- key_trigger ์ text_trigger ๋ ํค๋ณด๋ ๋ฒํผ ์ ๋ ฅ์ฉ
- mouse_trigger ๋ ๋ง์ฐ์ค ์ ๋ ฅ์ฉ
- gamepad_trigger ๋ ์์คํ ๊ฒ์ํจ๋์ฉ (์: Xbox ๋ Playstation ์ปจํธ๋กค๋ฌ)
- touch_trigger๋ ํฐ์น ์ ๋ ฅ์ ๋ชจ๋ ์ข ๋ฅ
- text_trigger๋ ํ ์คํธ ์ ๋ ฅ์ฉ
trigger type ์ ๋ง์ฐ์ค ์ค๋ฅธ์ชฝ ํด๋ฆญํ๊ณ "Add TYPE_triggerโฆ?"๋ฅผ ์ ํํด์ ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. ๊ฐ ํธ๋ฆฌ๊ฑฐ๋ ๋๊ฐ์ ํ๋๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
input
์ ๋ ฅ์ ๋๊ธฐํ ์ ์๋ ์คํฌ๋กค ๋ชฉ๋ก(scroll list)
action
์ ๋ ฅ์ด ๋ฐ์ํ ๋ ์์ฑ๋๋ฉฐ ์คํฌ๋ฆฝํธ๋ก ์ ๋ฌ๋๋ ์ก์ ์ ์ด๋ฆ. ์ฌ๋ฌ ์ก์ ์ ๋์ผํ ์ด๋ฆ์ ์ค์ ํ ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Space ํค์ "jump" ์ก์ ์ ๋ฐ์ธ๋ฉํ๊ณ ๊ฒ์ํจ๋ "A" ๋ฒํผ์๋ ๊ฐ์ ์ก์ ์ ๋ฐ์ธ๋ฉ ํ ์ ์์ต๋๋ค.
๋ถํํ๊ฒ๋ ํฐ์น ์ ๋ ฅ์ ๋ค๋ฅธ ์ ๋ ฅ๊ณผ ๋์ผํ ์ก์ ์ด๋ฆ์ ๊ฐ์ง์ ์๋ค๋ ๋ฒ๊ทธ๊ฐ ์๋ ค์ ธ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๊ฒ์์์ ์ข์ฐ๋ก ์ด๋ํ๊ธฐ ์ํ ํค๋ฅผ ๋ฐ์ธ๋ฉ ํ๋ ค ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ค์ ํ ์ ์์ต๋๋ค.

์ฌ๊ธฐ์, KEY_LEFT์ KEY_RIGHT ์ ๋ ฅ์ ๊ฐ๊ฐ "move_left" ์ "move_right" ๋ผ๋ ์ก์ ์ด๋ฆ์ผ๋ก ๋ฐ์ธ๋ฉ ๋์์ต๋๋ค. ๋ ผ๋ฆฌ์ ์ธ ์ก์ ๊ณผ ํ๋์จ์ด์ ์ ๋ ฅ์ ๋ถ๋ฆฌํ๋ ์ด์ ๋ ๋์ค์ ํ๋์จ์ด ์ ๋ ฅ์ด ์ด๋ค ๋์์ ํธ๋ฆฌ๊ฑฐ ํ ์ง ๋ณ๊ฒฝํด์ผํ ๊ฒฝ์ฐ ํ ๊ณณ๋ง ์์ ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
Acquiring and releasing input focus
์ ๋ ฅ ๋์(input action)์ ๋ฃ๊ธฐ ์ํด์๋, ๊ฒ์ ์ค๋ธ์ ํธ์ ์คํฌ๋ฆฝํธ(ํน์ GUI ์คํฌ๋ฆฝํธ)๋ฅผ ์์ฑํ๊ณ ์คํฌ๋ฆฝํธ์์ "acquire_input_focus" ๋ฉ์ธ์ง๋ฅผ ์์ ์ ๊ฒ์ ์ค๋ธ์ ํธ๋ก ๋ณด๋ด๋ฉด ๋ฉ๋๋ค.
function init(self)
msg.post(".", "acquire_input_focus")
end
์ด ๋ฉ์ธ์ง๋ Defold์๊ฒ ํ์ฌ ๊ฒ์ ์ค๋ธ์ ํธ์ ์ ๋ ฅ ๋์์ ์ง์ ์๋ ค์ค๋๋ค. ๊ธฐ์ ์ ์ผ๋ก, ์ด ์ค๋ธ์ ํธ์๊ฒ ๋ฐ์ํ๋ ์ผ์ ์ ๋ ฅ์คํ(input stack)(์์ธํ ์ค๋ช ์ ์๋ ์ฐธ๊ณ )์ ์ถ๊ฐ๋ฉ๋๋ค. ์ ๋ ฅ ๋์ ๋ฃ๊ธฐ๋ฅผ ์ค์งํ๊ธฐ ์ํด์๋ ๊ฒ์ ์ค๋ธ์ ํธ์ "release_input_focus" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค.
...
msg.post(".", "release_input_focus")
...
on_input()
์ ๋ ฅ ๋์์ ๋ฐ์ํ๊ธฐ ์ํด์๋, ๊ฒ์ ์ค๋ธ์ ํธ(์ ๋ ฅ ํฌ์ปค์ค๋ฅผ ํ๋ํ)์ ์คํฌ๋ฆฝํธ์ on_input() ํจ์๊ฐ ํ์ํฉ๋๋ค. ๊ฒ์ ์์ง์ ์ด ํจ์์ ์ ๋ ฅ ๋์๋ค์ ์ ๋ฌ(dispatch) ํฉ๋๋ค.
function on_input(self, action_id, action)
์ด ํจ์๋ 2๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ทจํฉ๋๋ค. ("self" ์ ์ธ) :
action_id
์ธํ ๋ฐ์ธ๋ฉ(input bindings)์์ ์ค์ ๋ ๋ฉ์ธ์ง์ ์ด๋ฆ. ํด์ฌ๋จ
action
๋ฉ์ธ์ง ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ์๋ Lua ํ ์ด๋ธ
์ฐ๋ฆฌ๊ฐ ์์์ ์ค์ ํ๋ "move_left" ๊ณผ "move_right" ๋ฐ์ธ๋ฉ์ ๋ค๋ฃจ๊ธฐ ์ํด์๋ ์๋ ์ฝ๋์ฒ๋ผ ์์ฑํ๋ฉด ๋ฉ๋๋ค.
function on_input(self, action_id, action)
if action_id == hash("move_left") and action.pressed then
local pos = go.get_position()
pos.x = pos.x - 100
go.set_position(pos)
elseif action_id == hash("move_right") and action.pressed then
local pos = go.get_position()
pos.x = pos.x + 100
go.set_position(pos)
end
end
์ปฌ๋ ์ ํ๋ก์๋ก ์์ ํ๋ ค๋ฉด, ์ปฌ๋ ์ ์ ํตํด ์ ๋ ฅ์ด ์ด๋ป๊ฒ ์ ๋ฌ๋๋์ง๋ฅผ ์ดํดํ๋๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ง์ฝ ์ปฌ๋ ์ ํ๋ก์๋ฅผ ์ฌ์ฉํด ์ ๋ ฅ์ ํ๋ํ ์ ์๋ค๋ฉด, ์๋ Input and Collection Proxies๋ฅผ ์ฝ์ด ๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
Action fields
๊ฐ๊ฐ์ ์ ๋ ฅ ๋ฉ์ธ์ง์ ๋ํด on_input() ํจ์๋ก ์ ๋ฌ๋๋ ์ก์ ํ๋ผ๋ฏธํฐ๋ ์ ๋ ฅ๊ฐ, ์ ๋ ฅ์ ์์น, ์ ๋ ฅ ๋ฒํผ์ "pressed", "repeated", "released" ์ํ์ ๊ฐ์ ์ ์ฉํ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ์๋ Lua ํ ์ด๋ธ์ ๋๋ค.
action.pressed
์ ๋ ฅ์ด ๊ฒ์ถ๋ ์ฒซ๋ฒ์งธ ํ๋ ์์์ true, ๊ทธ์ธ์๋ false
action.repeated
์ ๋ ฅ์ด ๋ฐ๋ณต๋๊ณ ์์ผ๋ฉด true, ๊ทธ ์ธ์๋ false. ์ด ๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋งค ํ๋ ์๋ง๋ค ์ค์ ๋์ง๋ ์์ง๋ง [ํ๋ก์ ํธ ์ค์ (project settings)](Project settings#input)์ repeat_delay์ repeat_interval ์ ์ค์ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
action.released
์ ๋ ฅ์ด ํด์ง(release)๋ ํ๋ ์์ true, ๊ทธ ์ธ์๋ false
์ฌ์ฉ ๊ฐ๋ฅํ ์ก์ ํ๋๋ฅผ ์์ธํ ๋ณด๊ณ ์ถ๋ค๋ฉด on_input() ์ฐธ๊ณ
Screen positions
๋ง์ฐ์ค ์ ๋ ฅ ๋ฐ ํฐ์น ์ ๋ ฅ์ ์์น(x, y) ๋ฟ๋ง ์๋๋ผ ์ด๋ ๋ฐ๊ฒฝ(dx, dy)๋ ์ก์ ํ ์ด๋ธ์ ํ๋๋ฅผ ์ ํ ํฉ๋๋ค. ๋ํ ์ด ์ ๋ ฅ์ ์ค์ ํ๋ฉด ๊ณต๊ฐ์ ๋ํ์ฌ ๊ณ์ฐ๋ ์๋์ ๊ฐ์ ํน์ ํ๋๋ ์ ํ ํฉ๋๋ค.
screen_x and screen_y
์ค์ ํ๋ฉด์์์ ์์น
screen_dx and screen_dy
๋ง์ง๋ง ์ ๋ฐ์ดํธ ์ดํ์ ์ค์ ํ๋ฉด์์์ ๋ณ๊ฒฝ๋ ์์น(delta)
์ด ํ๋๋ ๋ ํฐ๋ ๋์คํ๋ ์ด์์ ๋ฎ์ ํด์๋์ ๊ฒ์์ ํ๋ํด์ ์คํํ๋ ค ํ๋ ๊ฒฝ์ฐ์ฒ๋ผ ๊ฒ์์๋์์์ ์์น์ ํ๋ฉด์์์ ํฝ์ ์์น๊ฐ์ด ์๋ก ๋ค๋ฅด๊ฒ ๋์ค๋ ์ฅ์น์์ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด 1024x768 ํด์๋์ ๊ฒ์์ iPad์์ ์คํํ๋ฉด 2048x1536 ๋ฌผ๋ฆฌ ํด์๋์ ๋งคํ๋์ด "๋ ผ๋ฆฌ์ " ํฝ์ ์ด 4๊ฐ์ ์ค์ ํฝ์ ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
Key triggers
ํค ํธ๋ฆฌ๊ฑฐ๋ ๋ฒํผ ์ ๋ ฅ์ ๋ฐ์ํ๋ ๊ฐ๋จํ ํค ์ ๋ ฅ์ ๋๋ค. ์ด ๊ธฐ๋ฅ์ ์์์ ์ค์ ํ "move_left"์ "move_right"์ฒ๋ผ ํน์ ๋ฒํผ๊ณผ ํน์ ํจ์๋ฅผ ์ฎ๋ ๊ฒ์ด ํ์ํ ๊ฒ์์ผ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค. ๋ง์ฝ ์์์ ํค ์ ๋ ฅ์ ์ฝ์ด์ผ ํ๋ ๊ฒฝ์ฐ, text triggers ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. (์๋ ์ฐธ๊ณ )
Mouse triggers
๋ง์ฐ์ค ํธ๋ฆฌ๊ฑฐ๋ input bindings์์ ์ค์ ํ ํ ์ ๋ ฅ๊ณผ ๋ง์ฐ์ค ๋ฒํผ ์ ๋ ฅ์ผ๋ก ์ ๊ณต๋ฉ๋๋ค.
Mouse button inputs
๋ง์ฐ์ค๊ฐ ๋๋ ธ๋์ง(press) ๊ฐ์งํ ๋ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. "MOUSE_BUTTON_LEFT", "MOUSE_BUTTON_RIGHT", "MOUSE_BUTTON_MIDDLE" ์ ๋ ฅ์ "MOUSE_BUTTON_1", "MOUSE_BUTTON_2", "MOUSE_BUTTON_3"๊ณผ ๋์ผํฉ๋๋ค. ํ์ฌ MOUSE_BUTTON_LEFT (๋๋ MOUSE_BUTTON_1)์ ๋ ฅ ์ก์ ์ ๋จ์ผ ํฐ์น ์ ๋ ฅ(single touch inputs)์ ๋ํด์๋ ์ ์ก๋ฉ๋๋ค.
Mouse wheel inputs
์คํฌ๋กค ๋์์ ๊ฐ์งํ ๋ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. action.value ํ๋๋ ํ ์ด ์คํฌ๋กค ๋ ๋ 1, ๊ทธ ์ธ์๋ 0 ๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. (์คํฌ๋กค ๋์์ ๋ฒํผ ์ ๋ ฅ๊ณผ ๋์ผํ๊ฒ ์ฒ๋ฆฌ๋๋ฉฐ Defold๋ ํ์ฌ ํฐ์นํจ๋์ ๋ฏธ์ธํ ์คํฌ๋กค ์ ๋ ฅ์ ์ง์ํ์ง ์์ต๋๋ค.)
Mouse movement
๋ง์ฐ์ค ์์ง์์ input bindings์์ ๋ฐ์ธ๋ฉ ํ ์ ์๊ณ action_id ์ด๋ฆ์ ์ค์ ํ ์๋ ์์ต๋๋ค. ๋์ , action_id๋ nil๋ก ์ค์ ๋๊ณ ์ก์ ํ ์ด๋ธ์๋ ๋ง์ฐ์ค์ ์์น์ ์ด๋๊ฐ(delta movement)์ด ์ฑ์์ง๊ฒ ๋ฉ๋๋ค.
Gamepad triggers
๊ฒ์ ํจ๋ ํธ๋ฆฌ๊ฑฐ๋ ๊ฒ์ ํจ์์ ํ์ค ๊ฒ์ ํจ๋ ์ ๋ ฅ์ ๋ฐ์ธ๋ฉํด ์ค๋๋ค. Defold๋ ์ด์์ฒด์ ๋ฅผ ํตํด ์ฌ๋ฌ ๊ฒ์ ํจ๋๋ฅผ ์ง์ํ๋ฉฐ ์๋์ ๊ฐ์ ๋ฐ์ธ๋ฉ์ ์ ๊ณตํฉ๋๋ค.
- ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ์คํฑ(๋ฐฉํฅ, ํด๋ฆญ)
- ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ๋์งํ ํจ๋
- ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ํธ๋ฆฌ๊ฑฐ
- ์ผ์ชฝ, ์ค๋ฅธ์ชฝ ์๋ ๋ฒํผ
- ์์, ๋ค๋ก๊ฐ๊ธฐ, ๊ฐ์ด๋ ๋ฒํผ
์ผ๋ฐ์ ์ผ๋ก Xbox ์ปจํธ๋กค๋ฌ์์๋ A, B, X, Y ๋ฒํผ์ผ๋ก, Playstation ์ปจํธ๋กค๋ฌ์์๋ square, circle, triangle, cross ๋ฒํผ์ผ๋ก ํด์๋ฉ๋๋ค.
๊ฒ์ํจ๋ ์ ๋ ฅ์ ์ก์ ํ ์ด๋ธ์ gamepad ํ๋๋ฅผ ์ ๋ ฅ์ด ๋ฐ์ํ ๊ฒ์ ํจ๋์ ๋ฒํธ๋ก ์ค์ ํฉ๋๋ค.
function on_input(self, action_id, action)
if action_id == hash("gamepad_start") then
...
if action.gamepad == 0 then
-- gamepad ๊ฐ 0์ด๋ฉด ๊ฒ์ ์ ์์ ํ๋ ค๋ ๋์์
...
end
end
end
Touch triggers
ํฐ์น์ ๋ฉํฐํฐ์น ํธ๋ฆฌ๊ฑฐ๋ ์ก์ ํ ์ด๋ธ์ action.touch ์ด๋ผ๋ ํ์ ํ ์ด๋ธ์ ์ฑ์๋๋ค. ์ด ํ ์ด๋ธ์ ์์๋ค์ 1~n ์์(n์ ํฐ์น๋ ์ ๋ ฅ์ ์)๋ก ๋ฒํธ๊ฐ ๋์ด๋๋ฉฐ ์ ๋ ฅ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
์ฌ์ฉ๊ฐ๋ฅํ ํฐ์น ์ก์ ํ๋๋ฅผ ์์ธํ ์๊ณ ์ถ๋ค๋ฉด on_input() ์ฐธ๊ณ
ํ ์ด๋ธ์ด ๋ฐฐ์ด์ฒ๋ผ ๋๋ฒ๋ง ๋์ด ์์ผ๋ฏ๋ก, ์๋์ ๊ฐ์ด ์ฝ๊ฒ ์กฐํํ ์ ์์ต๋๋ค.
function on_input(self, action_id, action)
if action_id == hash("touch") and #action.touch > 1 and #action.touch < 4 then
-- 2~3๊ฐ ํฐ์น์ง์ ์ด ๋ฐ์ํ๋ฉด ๋ง๋ฒ ์คํํฌ ํํฐํด์ ๊ฐ ํฌ์ธํธ์ ์คํฐ์ํค๊ธฐ
for i, tpoint in ipairs(action.touch) do
local pos = vmath.vector3(tpoint.x, tpoint.y, 0)
factory.create("#factory", pos)
end
end
end
์ฌ๊ธฐ์๋ "factory" ์ปดํฌ๋ํธ๊ฐ factory.create()๋ฅผ ํตํด ๊ฐ๋จํ ํํฐํด ์ดํํธ๋ฅผ ์คํฐํ๋๋ฐ ์ฌ์ฉ๋์์ต๋๋ค. ๋ ์ธ๊ฐ ์๊ฐ๋ฝ์ผ๋ก ์ฅ์น์ ํ๋ฉด์ ํฐ์นํ๋ฉด ์๊ฐ๋ฝ์ ๋ฐ๋ผ ํํฐํด์ด ๋ฐ๋ผ๋ค๋๋ฉฐ ์คํฐ๋๊ฒ ๋ฉ๋๋ค.

Text triggers
ํ ์คํธ ํธ๋ฆฌ๊ฑฐ๋ ์์์ ํ ์คํธ ์ ๋ ฅ์ ์ฝ์ ์ ์๊ฒ ํด ์ค๋๋ค. ํ ์คํธ ํธ๋ฆฌ๊ฑฐ๋ ๋ ๊ฐ์ง ์ข ๋ฅ๊ฐ ์์ต๋๋ค.
TEXT
์ด ์ ๋ ฅ ํธ๋ฆฌ๊ฑฐ๋ ๋ณดํต์ ํ ์คํธ ์ ๋ ฅ์ ์บก์ณํฉ๋๋ค.
ํ ์คํธ ํธ๋ฆฌ๊ฑฐ๋ ์ก์ ํ ์ด๋ธ์ "text" ํ๋๋ฅผ ์ ๋ ฅ๋ ๋ฌธ์๋ฅผ ํฌํจํ ๋ฌธ์์ด๋ก ์ ํ ํฉ๋๋ค. ์ด ๋์์ ๋ฒํผ์ด ๋๋ ค์ง ๋(press)์๋ง ๋ฐ์ํ๋ฉฐ, "release"๋ "repeated" ๋์์๋ ๋ฐ์ํ์ง ์์ต๋๋ค.
function on_input(self, action_id, action)
if action_id == hash("text") then
-- ์
๋ ฅ๋ ๋ฌธ์๋ฅผ "text" ๋
ธ๋์ ์ด์ด ๋ถ์ด๊ธฐ...
local node = gui.get_node("text")
local text = gui.get_text(node)
text = text .. action.text
gui.set_text(node, text)
end
end
MARKED_TEXT
์ด ๊ธฐ๋ฅ์ ๋จ์ผ ์ ๋ ฅ์ ๋งคํ๋๋ ์ฌ๋ฌ ๊ฐ์ ํค ์ ๋ ฅ๊ฐ์ ์์์์ฉ ํค๋ณด๋์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, iOS์ "Japanese-Kana" ํค๋ณด๋์ ๊ฒฝ์ฐ์ 10๊ฐ์ ํค๋ก ๊ตฌ์ฑ๋ ํค๋ณด๋๋ฅผ ๊ฐ์ง๊ณ ์๋๋ฐ, ์ ์ ๊ฐ ํค๋ฅผ ์กฐํฉํ์ฌ ํค๋ณด๋์ ์์ชฝ์ ์ฌ์ฉ๊ฐ๋ฅํ ์ฌ๋ณผ์ด ํ์๋๊ฒ ๋ฉ๋๋ค.

๊ฐ๊ฐ์ ํค ์ ๋ ฅ์ ๋ณ๋ ์ก์ ์ ์์ฑํ๋ฉฐ "text" ํ๋์์ ์ ๋ ฅ๋ ํค์ ๋ ฅ์ ๋ชจ์์ ์ก์ ํ๋์ ์ค์ ํ๊ฒ ๋ฉ๋๋ค.
{
repeated = false,
released = false,
text = ใ,
value = 0,
pressed = false,
}
์ ์ ๊ฐ ์ฌ๋ณผ์ด๋ ์กฐํฉ๋ ์ฌ๋ณผ์ ์ ํํ๋ฉด, ๋ณดํต์ ํ ์คํธ ํธ๋ฆฌ๊ฑฐ ์ก์ ์ด ์ ์ก๋ฉ๋๋ค.
The input stack
์ ๋ ฅ ํฌ์ปค์ค๋ฅผ ํ๋ํ๋ ๊ฒ์ ์ค๋ธ์ ํธ๋ ์ ๋ ฅ์ ์์ ํ๋ ์ค๋ธ์ ํธ ๋ฆฌ์คํธ์ ์ฐ์ ์ถ๊ฐ๋ฉ๋๋ค. ์ด ๋ฆฌ์คํธ๋ ์ธํ ์คํ(input stack)์ผ๋ก ๋ถ๋ฆฌ๋๋ฐ, ์ ๋ ฅ ๋์์ ๊ฐ์ฅ ์์์ ์ค๋ธ์ ํธ ์ปดํฌ๋ํธ๋ก ๋จผ์ ์ ๋ฌ๋๊ณ ๋ค๋ฆ ์ปดํฌ๋ํธ๋ก ์ฐจ๋ก๋ก ์ ๋ฌ๋๊ฒ ๋ฉ๋๋ค.

์ด ๋์์ ์ ๋ฌ(dispatch)์ ๋์ผํ ํ๋ ์ ๋ด์์ ๋ฐ์ํ๋ฏ๋ก ์คํ์ ์๋๋ฐฉํฅ์ผ๋ก ์ ๋ ฅ์ด ์ ๋ฌ๋๋ ๊ฒ์ ์๋์ ์ผ๋ก ์กฐ์ํ์ง ์์๋ค๋ฉด, (์๋ "Consuming input" ์ฐธ๊ณ ) ๋ชจ๋ ์์ ์ปดํฌ๋ํธ์ on_input() ํจ์๊ฐ ๋์์ ์ ๋ ฅ์ ๋ฐ๋๊ฒ ์ฒ๋ผ ๋ณด์ด๊ฒ ๋ฉ๋๋ค.
Stack order
๋ชจ๋ ์ ๋ ฅ์ ํ๋ํ๋ ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ ์๋ค๋ฉด, ์ธํ ์คํ์ ์์์ ์ฐจ๋ก ์ฐจ๋ก ์ถ๊ฐ๋๊ฒ ๋ฉ๋๋ค.
-- "listener1.script"์์
function init(self)
msg.post(".", "acquire_input_focus")
end
-- "listener2.script"์์
function init(self)
msg.post(".", "acquire_input_focus")
end
ํ์ง๋ง, ์ค๋ธ์ ํธ๊ฐ์ ์ด๊ธฐํ๋ ์ ๋ฐ์ดํธ ์์๋ ์ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ํน์ ํ ์์๋ก ๋ฆฌ์ค๋๊ฐ ์คํ์ ๋ํ๋ ๊ฒ์ด๋ผ๋ ๋ณด์ฅ์ ๋์ง ์์ต๋๋ค.
ํน์ ์์๋ก ์คํ์ ๋ฆฌ์ค๋๊ฐ ํ์ํ ์ํฉ์ด๋ผ๋ฉด, ๋ฉ์ธ์ง๋ค์ ์ฐ๊ฒฐํ์ฌ ์ค๋ธ์ ํธ๊ฐ์ ํน์ ์ ๋ ฅ ์์๋ฅผ ๊ฐ์ ๋ก ์ ์ฉํ๋ฉด ๋ฉ๋๋ค.
-- "listener1.script"์์
function init(self)
-- ์ฌ๊ธฐ์ ๋จผ์ ์
๋ ฅ์ ํ๋ํ๊ณ "listener2"๋ก ๋ณด๋
msg.post(".", "acquire_input_focus")
msg.post("listener2", "acquire_input")
end
-- "listener2.script"์์
function on_message(self, message_id, message, sender)
if message_id == hash("acquire_input") then
-- ๋ฉ์ธ์ง๋ฅผ ๋ฐ์ผ๋ฉด ์
๋ ฅ ํ๋ํ๊ธฐ
msg.post(".", "acquire_input_focus")
end
end
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ์ธํ ์คํ์ด ์๋์ ๊ฐ์ด ์ ๋ ฌ๋ฉ๋๋ค.

Consuming input
์ปดํฌ๋ํธ์ on_input() ์ฝ๋๋ ์ก์ ์ ์คํ ์๋๋ก ๋ณด๋ผ์ง ๋ง์ง๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค.
- ๋ง์ฝ on_input() ์ฝ๋๊ฐ false๋ฅผ ๋ฐํํ๊ฑฐ๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์ผ๋ฉด(return๋ฌธ์ ์๋ตํ๋ฉด lua์์ ์์๋ก false๊ฐ์ ์๋ฏธํ๋ nil์ ๋ฐํํจ), ์ ๋ ฅ ์ก์ ์ ์ธํ ์คํ์ ๋ค์ ๊ฒ์ ์ค๋ธ์ ํธ๋ก ๋๊น๋๋ค.
- ๋ง์ฝ ๊ฒ์ ์ค๋ธ์ ํธ ์ปดํฌ๋ํธ์ ์คํฌ๋ฆฝํธ๊ฐ on_input()์์ true๋ฅผ ๋ฐํํ๋ฉด, ์ด ์ ๋ ฅ์ ์๋น(consume)๋์ด ๋ฒ๋ฆฌ๋ฉฐ ์ธํ ์คํ์ ๋ค์ ์ค๋ธ์ ํธ๋ก ์ ๋ฌํ์ง ์์ต๋๋ค.
๊ฒ์ ์ค๋ธ์ ํธ๋ ์ฌ๋ฌ ์คํฌ๋ฆฝํธ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ๋ชจ๋ ์ ๋ ฅ ๋์์ ์ด ๊ฒ์ ์ค๋ธ์ ํธ์ ์ปดํฌ๋ํธ๋ค์๊ฒ ๋ธ๋ก๋์บ์คํธ ๋ฉ๋๋ค.
on_input() ํจ์๊ฐ ์๋ ๊ฒ์ ์ค๋ธ์ ํธ๋ on_input() ํจ์๊ฐ false๋ฅผ ๋ฐํํ๋ ๊ฒ ์ฒ๋ผ ์ ๋ ฅ ์ก์ ์ ์คํ ์์๋๋ก ๋๊ธฐ๊ฒ ๋ฉ๋๋ค.

์ฌ๊ธฐ, ์ ๋ ฅ ์๋น(input consumption)๊ฐ ๊ฒ์์ ๊ฐ๊ธฐ ๋ค๋ฅธ ํํธ๊ฐ์ ์ ๋ ฅ์ ์ ์ดํ๋ ๊ฐ๋จํ๊ณ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ๋ช ๊ฐ์ง ์ฌ๋ก๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ผ์์ ์ผ๋ก ํ์ ๋ฉ๋ด๊ฐ ํ์ํด์ ๊ฒ์์ ํ ๋ถ๋ถ์์ ์ ๋ ฅ์ ์์ ํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
ํฐ์น ์ ๋ ฅ์ ํตํด ๋ง๋ฒ์ฌ๋ฅผ ์ปจํธ๋กคํ๋ ๊ฒ์์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ํ๋ฉด ํ ๊ตฌ์์๋ HUD ๋ฉ๋ด๊ฐ ํ๋ ์ด์ด๊ฐ ๊ฒ์์ ์ค์ง(pause)ํ ์ง ํ์ํ๊ณ ์์ต๋๋ค.

์ผ์์ค์ง ๋ฉ๋ด๋ ์ฒ์์๋ ์จ๊ฒจ์ ธ(disable) ์์ผ๋ฉฐ, ์ ์ ๊ฐ "PAUSE" HUD ๋ฉ๋ด๋ฅผ ํฐ์นํ๋ฉด ํ์ฑํ ๋ฉ๋๋ค.
function init(self)
msg.post(".", "acquire_input_focus")
end
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
local x = action.x
local y = action.y
-- "pause" ๋
ธ๋๋ฅผ ๊ฐ์ ธ์์ ์ ์ ๊ฐ ํฐ์นํ๋์ง ํ์ธํ๊ธฐ
local pausenode = gui.get_node("pause")
if gui.pick_node(pausenode, x, y) then
-- pause ๋ฉ๋ด์๊ฒ ์๋ ค์ฃผ๊ธฐ
msg.post("pause_menu", "show")
end
end
end

pause ๋ฉ๋ด๋ ์์์ด ์ ํ์ง ๋ฐฐ๊ฒฝ๊ณผ ๋ช ๊ฐ์ง ์์ ๋ฉ๋ด ์์ดํ ์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค. "background" ๋ ธ๋๋ฅผ ํ์ฑํ/๋นํ์ฑํ ํด์ pause ๋ฉ๋ด ์ ์ฒด GUI๊ฐ ๋ํ๋ฌ๋ค ์ฌ๋ผ์ก๋ค ํ ์ ์์ต๋๋ค.

pause ๋ฉ๋ด GUI๋ ์๋ ์ฝ๋๋ก ์คํ๋ฉ๋๋ค.
function init(self)
-- background ๋
ธ๋๋ฅผ ๊ฐ์ ธ์ ๋นํ์ฑํ ํ๊ธฐ
-- ๋ชจ๋ ๊ฒ์ด ์์ ๋
ธ๋๋ก ๋์ด์์
local node = gui.get_node("background")
gui.set_enabled(node, false)
end
function on_message(self, message_id, message, sender)
if message_id == hash("show") then
-- ์ฐ์ , pause ๋ฉ๋ด ๋ณด์ด๊ธฐ
local node = gui.get_node("background")
gui.set_enabled(node, true)
-- ์ด์ ์
๋ ฅ์ ํ๋ํ๋ฉด ์ฐ๋ฆฌ๋ ์
๋ ฅ์คํ ๋งจ ์์ ์๊ฒ ์ง!
msg.post(".", "acquire_input_focus")
end
end
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
local x = action.x
local y = action.y
-- ๋
ธ๋๋ฅผ ๊ฐ์ ธ์์ ๋๋ ธ๋์ง ํ์ธํ๊ธฐ
local loadnode = gui.get_node("load")
local savenode = gui.get_node("save")
local resumenode = gui.get_node("resume")
if gui.pick_node(loadnode, x, y) then
print("THE GAME WILL LOAD...")
elseif gui.pick_node(savenode, x, y) then
print("THE GAME WILL SAVE...")
elseif gui.pick_node(resumenode, x, y) then
-- ๊ฒ์ ์ฌ๊ฐ(resume)ํ๊ธฐ...
-- ์ฐ์ , pause ๋ฉ๋ด๋ถํฐ ์จ๊ธฐ๊ธฐ
local node = gui.get_node("background")
gui.set_enabled(node, false)
-- ๋ง์ง๋ง์ผ๋ก ์
๋ ฅ ํด์ง(release)ํ๊ธฐ
msg.post(".", "release_input_focus")
end
end
-- ์
๋ ฅ์ ์์ ํ๋ ๋์์, ์
๋ ฅ์ ์๋น(consume)ํด๋ฒ๋ฆฌ์
-- pause ๋ฉ๋ด๊ฐ ๋ณด์ด๋ ๋์์ ๊ฒ์ ์ปจํธ๋กค์ ๋นํ์ฑํ ํจ
return true
end
pause ๋ฉ๋ด์ GUI ์คํฌ๋ฆฝํธ์ on_input() ํจ์๋ ๋ฉ๋ด๊ฐ ๋ณด์ด๋ ๋์์ true๋ฅผ ๋ฐํํฉ๋๋ค. ์ฆ, ๋ชจ๋ ์ ๋ ฅ ์ก์ ์ ์๋ชจ(consume)ํ๋ฏ๋ก ์ด ๊ฒ์์ ์ฌ์ฉ์ ์ ๋ ฅ์ ํจ๊ณผ์ ์ผ๋ก ์ค์ง์ํฌ ์ ์์ต๋๋ค.
Input and Collection Proxies
์ธํ ์คํ์ ์ค์ ๋ก๋ ์ ์ญ(global)์ด ์๋๋ฉฐ ๊ฐ ์ปฌ๋ ์ ์ ๋ํด ๋ณ๋์ ๋ก์ปฌ ์ธํ ์คํ(local input stack)์ผ๋ก ์กด์ฌํฉ๋๋ค. ๋ง์ฝ ๊ฒ์์ด ์ปฌ๋ ์ ํ๋ก์ ๊ตฌ์กฐ๋ก ์ฌ์ฉ๋๋ค๋ฉด ์ปฌ๋ ์ ์ ํตํด ์ ๋ ฅ์ด ์ ๋ฌ๋๋ ๋ฐฉ์์ ๋ํด ์ดํดํ ํ์๊ฐ ์์ต๋๋ค.
์ ๋ ฅ ์ก์ ์ด ํ์ฌ ์ปฌ๋ ์ ์ ์ธํ ์คํ ์๋๋ก ์ ๋ฌ๋์ด ์ปฌ๋ ์ ํ๋ก์ ์ปดํฌ๋ํธ๊ฐ ํ์ฑํ๋ ๊ฒ์ ์ค๋ธ์ ํธ์ ๋๋ฌํ๋ฉด, ์ด ์ก์ ์ ๋ฉ์ธ ์ปฌ๋ ์ ์ ์คํ ์์๋๋ก ๋์ด๊ฐ๊ธฐ ์ ์, ์ด๋ฏธ ๋์ ์ผ๋ก ๋ก๋๋ ์ปฌ๋ ์ ์ ์ธํ ์คํ๋ถํฐ ์งํ๋ฉ๋๋ค. ์๋ ๋ค์ด์ด๊ทธ๋จ์ ์ด ํ๋ก์ธ์ค๋ฅผ ๋ช ํํ๊ฒ ๋ณด์ฌ์ค๋๋ค.

๋์ ์ผ๋ก ๋ก๋๋ ์ปฌ๋ ์ ์ ๋ชจ๋ on_input() ์ปดํฌ๋ํธ ์ฝ๋๊ฐ ์ ๋ ฅ ์ก์ ์ ๋ฐ๊ธฐ ์ํด์๋, ์ปฌ๋ ์ ํ๋ก์๋ฅผ ํฌํจํ๊ณ ์๋ ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ ๋ฐ๋์ ์ธํ ์คํ์ ์์ด์ผ ํฉ๋๋ค.
์ปฌ๋ ์ ํ๋ก์์ ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ on_input() ์ฝ๋๋ฅผ ํฌํจํ๊ณ ์์ง ์๋๋ผ๋, ์ ๋ ฅ์คํ์ ์์์ ์ถ๊ฐํ๊ธฐ ์ํด์ "acquire_input_focus" ๋ฉ์ธ์ง๊ฐ ๋ฐ๋์ ์ ์ก๋์ด์ผ ํ๋ฉฐ, ๋ก๋๋ ์ปฌ๋ ์ ๋ด์ ์๋ ๊ฒ์์ค๋ธ์ ํธ๋ ์ปฌ๋ ์ ์ ์ธํ ์คํ์ ์ถ๊ฐ๋๊ธฐ ์ํด "acquire_input_focus" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ผ ํฉ๋๋ค.
์ ๋ ฅ ์คํ์ ์ด๋ค ๋จ๊ณ์์๋ on_input() ํจ์๊ฐ true๋ฅผ ๋ฐํํ๋ฉด, ์ด ์ ๋ ฅ์ ์๋น(consume)๋์ด ์ด๋ ํ ๋์๋ ๋๊ธฐ์ง ์๊ณ ์๋ฌด ์ผ๋ ๋ฐ์ํ์ง ์๊ฒ ๋ฉ๋๋ค. ํ์์ ๋ฐ๋ผ์, ๋ก๋๋ ์ปฌ๋ ์ ์ด ๋ฉ์ธ ์ปฌ๋ ์ ์์ ์์ ์ค์ธ ์ก์ ์ ๋์ ๋ชปํ๋๋ก ์ ๋ ฅ์ ์๋นํด ๋ฒ๋ฆด ์๋ ์์ต๋๋ค.