본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 3. · 20 Views
Phaser 키보드와 마우스 입력 처리 완벽 가이드
Phaser 게임 엔진에서 키보드와 마우스 입력을 처리하는 방법을 알아봅니다. Cursor Keys부터 커스텀 키 바인딩, 마우스 클릭, 터치 입력까지 게임 개발에 필요한 모든 입력 처리 기법을 다룹니다.
목차
1. Cursor Keys 사용하기
김개발 씨는 처음으로 Phaser를 사용해 간단한 게임을 만들어 보기로 했습니다. 화면에 캐릭터는 잘 표시되는데, 방향키를 눌러도 캐릭터가 꿈쩍도 하지 않습니다.
"어떻게 해야 키보드 입력을 받을 수 있는 거지?"
Cursor Keys는 Phaser에서 가장 기본적인 키보드 입력 방식입니다. 마치 게임 컨트롤러의 십자 버튼처럼, 상하좌우 방향키와 Shift, Space 키를 한 번에 묶어서 관리할 수 있습니다.
이것을 사용하면 별도의 설정 없이도 기본적인 캐릭터 이동을 쉽게 구현할 수 있습니다.
다음 코드를 살펴봅시다.
// Scene의 create 함수에서 커서 키 생성
this.cursors = this.input.keyboard.createCursorKeys();
// update 함수에서 키 입력 확인
update() {
// 왼쪽 화살표를 누르고 있으면
if (this.cursors.left.isDown) {
this.player.x -= 5;
}
// 오른쪽 화살표를 누르고 있으면
if (this.cursors.right.isDown) {
this.player.x += 5;
}
// 스페이스바를 누르면 점프
if (this.cursors.space.isDown) {
this.player.y -= 10;
}
}
김개발 씨는 입사 3개월 차 주니어 개발자입니다. 회사에서 간단한 미니 게임을 만들어 달라는 요청을 받았습니다.
Phaser라는 게임 엔진을 처음 써보는 터라 모든 것이 낯설기만 합니다. 화면에 캐릭터 스프라이트를 띄우는 것까지는 성공했습니다.
하지만 방향키를 아무리 눌러도 캐릭터가 움직이지 않습니다. "혹시 이벤트 리스너를 달아야 하나?" 선배 개발자 박시니어 씨가 다가와 코드를 살펴봅니다.
"Phaser에서는 그렇게 복잡하게 할 필요 없어요. createCursorKeys라는 편리한 메서드가 있거든요." 그렇다면 Cursor Keys란 정확히 무엇일까요?
쉽게 비유하자면, Cursor Keys는 마치 게임패드의 방향키 세트와 같습니다. 슈퍼마켓에서 장바구니를 하나 집으면 그 안에 여러 물건을 담을 수 있듯이, createCursorKeys를 한 번 호출하면 상하좌우 화살표와 Shift, Space 키를 한꺼번에 담은 객체를 얻을 수 있습니다.
Cursor Keys가 없던 시절에는 어땠을까요? 개발자들은 각각의 키에 대해 일일이 이벤트 리스너를 등록해야 했습니다.
위쪽 화살표, 아래쪽 화살표, 왼쪽, 오른쪽... 코드가 길어지고 관리하기도 번거로웠습니다.
더 큰 문제는 키가 "눌려 있는 상태"를 추적하는 것이었습니다. keydown 이벤트는 키를 누를 때만 발생하니까요.
바로 이런 문제를 해결하기 위해 Phaser는 Cursor Keys 시스템을 제공합니다. isDown 속성을 사용하면 해당 키가 현재 눌려 있는지 아닌지를 매 프레임마다 확인할 수 있습니다.
또한 isUp 속성으로 키가 떼어진 상태인지도 알 수 있습니다. 무엇보다 코드가 직관적이고 읽기 쉬워진다는 큰 장점이 있습니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 create 함수에서 **this.input.keyboard.createCursorKeys()**를 호출합니다.
이 한 줄로 방향키와 Shift, Space 키를 모두 포함한 객체가 생성됩니다. 이 객체를 this.cursors에 저장해 둡니다.
다음으로 update 함수에서 매 프레임마다 키 상태를 확인합니다. this.cursors.left.isDown이 true면 왼쪽 화살표가 눌려 있다는 뜻입니다.
이때 플레이어의 x 좌표를 감소시켜 왼쪽으로 이동시킵니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 플랫포머 게임을 개발한다고 가정해봅시다. 캐릭터가 좌우로 이동하고 점프하는 기본 동작을 구현할 때 Cursor Keys를 활용하면 몇 줄의 코드만으로 핵심 조작을 완성할 수 있습니다.
대부분의 캐주얼 게임에서 이 패턴을 기본으로 사용합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 create 함수가 아닌 곳에서 createCursorKeys를 호출하는 것입니다. 씬이 완전히 초기화되기 전에 호출하면 에러가 발생할 수 있습니다.
따라서 반드시 create 함수 내에서 초기화해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 생각보다 훨씬 간단하네요!" Cursor Keys를 제대로 이해하면 게임의 기본 조작을 빠르게 구현할 수 있습니다.
여러분도 오늘 배운 내용을 활용해 첫 번째 움직이는 캐릭터를 만들어 보세요.
실전 팁
💡 - createCursorKeys는 반드시 create 함수에서 호출하세요
- isDown은 키가 눌려 있는 동안 계속 true를 반환합니다
- 물리 엔진을 사용한다면 직접 좌표를 변경하는 대신 velocity를 조절하세요
2. 커스텀 키 바인딩
김개발 씨의 게임에 새로운 요구사항이 생겼습니다. "WASD로도 이동할 수 있게 해주세요.
그리고 E키로 상호작용, R키로 재장전이요." Cursor Keys만으로는 부족합니다. 원하는 키를 직접 지정하는 방법이 필요합니다.
커스텀 키 바인딩은 개발자가 원하는 키보드 키를 직접 지정하여 입력을 받는 방식입니다. 마치 자동차의 키를 복사해서 여러 개 만드는 것처럼, 필요한 키마다 개별적인 입력 객체를 생성할 수 있습니다.
이것을 활용하면 게임의 조작 방식을 자유롭게 설계할 수 있습니다.
다음 코드를 살펴봅시다.
// create 함수에서 커스텀 키 등록
this.keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
this.keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
this.keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
this.keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
this.keyE = this.input.keyboard.addKey('E'); // 문자열로도 가능
// update 함수에서 사용
update() {
if (this.keyW.isDown) {
this.player.y -= 5; // 위로 이동
}
if (this.keyE.isDown && Phaser.Input.Keyboard.JustDown(this.keyE)) {
this.interact(); // E키를 막 눌렀을 때만 상호작용
}
}
게임 기획이 점점 구체화되면서 조작 방식도 복잡해졌습니다. 김개발 씨는 FPS 게임처럼 WASD로 이동하고, 숫자키로 무기를 바꾸고, E키로 문을 열 수 있게 만들어야 합니다.
"Cursor Keys는 방향키밖에 없는데, 다른 키는 어떻게 등록하죠?" 박시니어 씨가 대답합니다. "addKey 메서드를 사용하면 돼요.
키보드의 어떤 키든 입력 객체로 만들 수 있어요." 커스텀 키 바인딩이란 정확히 무엇일까요? 쉽게 비유하자면, 호텔의 마스터키와 같습니다.
호텔 매니저는 필요한 방마다 해당 방을 열 수 있는 키를 가지고 있습니다. 마찬가지로 개발자는 게임에 필요한 키마다 개별적인 입력 객체를 만들어 관리할 수 있습니다.
각 키는 독립적으로 상태를 추적합니다. 커스텀 키 바인딩이 없다면 어떻게 될까요?
모든 키 입력을 document의 keydown 이벤트로 처리해야 합니다. 이벤트 핸들러 안에서 event.keyCode를 일일이 비교해야 하고, 키가 눌려 있는 상태를 별도의 변수로 관리해야 합니다.
코드가 복잡해지고 버그가 생기기 쉬운 구조가 됩니다. Phaser의 addKey 메서드는 이 모든 것을 깔끔하게 해결해줍니다.
키를 지정하는 방법은 두 가지가 있습니다. 첫 번째는 Phaser.Input.Keyboard.KeyCodes 상수를 사용하는 것입니다.
W, A, S, D, SPACE, SHIFT, CTRL 등 거의 모든 키가 정의되어 있습니다. 두 번째는 단순히 문자열로 'E', 'R', 'F' 같이 지정하는 것입니다.
위의 코드에서 특히 주목할 부분이 있습니다. Phaser.Input.Keyboard.JustDown이라는 메서드입니다.
isDown은 키가 눌려 있는 동안 매 프레임 true를 반환합니다. 하지만 상호작용 같은 동작은 한 번만 실행되어야 합니다.
JustDown을 사용하면 키를 누른 바로 그 프레임에서만 true를 반환합니다. 실제 게임 개발에서 이 구분은 매우 중요합니다.
이동은 키를 누르고 있는 동안 계속 일어나야 하므로 isDown을 사용합니다. 하지만 점프나 공격, 아이템 사용 같은 동작은 JustDown을 사용해야 합니다.
그렇지 않으면 키를 한 번 눌렀는데 점프가 여러 번 되는 황당한 상황이 발생합니다. 실무에서는 키 바인딩을 객체로 관리하는 패턴도 많이 사용합니다.
예를 들어 options 객체에 각 동작에 해당하는 키를 저장해두고, 나중에 설정 화면에서 사용자가 키를 변경할 수 있게 하는 것입니다. 이렇게 하면 키 설정 변경 기능을 쉽게 구현할 수 있습니다.
주의할 점도 있습니다. 브라우저에서 특정 키는 기본 동작이 있습니다.
예를 들어 Space는 페이지를 스크롤하고, F5는 새로고침합니다. 게임에서 이런 키를 사용하려면 기본 동작을 막아야 할 수도 있습니다.
Phaser는 대부분 자동으로 처리해주지만, 가끔 문제가 생길 수 있으니 테스트를 꼼꼼히 해야 합니다. 김개발 씨는 WASD 이동과 각종 액션 키를 모두 구현했습니다.
"이제 정말 게임다워졌네요!"
실전 팁
💡 - JustDown은 한 번만 실행해야 하는 동작에, isDown은 지속적인 동작에 사용하세요
- 키 바인딩 정보는 객체로 관리하면 나중에 설정 변경이 쉽습니다
- 여러 키를 한 번에 등록하려면 addKeys 메서드를 활용하세요
3. 키보드 이벤트 처리
김개발 씨가 새로운 문제에 부딪혔습니다. ESC키를 누르면 일시정지 메뉴가 나와야 하는데, update 함수에서 처리하기가 애매합니다.
"키를 눌렀을 때 딱 한 번 함수를 호출하는 방법은 없나요?"
키보드 이벤트 처리는 특정 키가 눌리거나 떼어질 때 콜백 함수를 실행하는 방식입니다. 마치 초인종처럼, 누군가 버튼을 누르면 벨이 울리는 것과 같습니다.
이 방식은 메뉴 열기, 디버그 모드 토글 같은 일회성 동작을 처리할 때 유용합니다.
다음 코드를 살펴봅시다.
// create 함수에서 이벤트 리스너 등록
this.input.keyboard.on('keydown-ESC', () => {
this.togglePauseMenu();
});
// 특정 키 객체에 이벤트 연결
this.keyP = this.input.keyboard.addKey('P');
this.keyP.on('down', () => {
console.log('P키가 눌렸습니다');
});
this.keyP.on('up', () => {
console.log('P키가 떼어졌습니다');
});
// 모든 키 입력을 감지
this.input.keyboard.on('keydown', (event) => {
console.log('눌린 키:', event.key);
});
게임의 UI 기능이 늘어나면서 김개발 씨는 고민에 빠졌습니다. ESC를 누르면 일시정지, P를 누르면 인벤토리, M을 누르면 지도...
이런 동작들은 update 함수에서 매 프레임 체크하기보다 이벤트 방식이 더 적합해 보입니다. "웹 개발할 때는 addEventListener를 썼는데, Phaser에서는 어떻게 하죠?" 박시니어 씨가 설명합니다.
"Phaser도 비슷한 이벤트 시스템을 가지고 있어요. on 메서드를 사용하면 됩니다." 키보드 이벤트 처리란 정확히 무엇일까요?
쉽게 비유하자면, 회사의 전화 응대 시스템과 같습니다. 전화가 오면 자동으로 "안녕하세요, 무엇을 도와드릴까요?"라고 응대하는 것처럼, 특정 키가 눌리면 미리 등록해둔 함수가 자동으로 실행됩니다.
이것을 콜백 함수라고 부릅니다. isDown 방식과 이벤트 방식은 어떤 차이가 있을까요?
isDown은 매 프레임마다 키 상태를 확인하는 폴링(polling) 방식입니다. 이동처럼 지속적인 동작에 적합합니다.
반면 이벤트 방식은 키가 눌리거나 떼어지는 순간에만 반응합니다. 메뉴 토글, 아이템 사용처럼 일회성 동작에 적합합니다.
위의 코드에서 세 가지 패턴을 볼 수 있습니다. 첫 번째는 keydown-키이름 형식입니다.
특정 키에 대해서만 이벤트를 받고 싶을 때 사용합니다. ESC, SPACE, ENTER 같은 특수키도 이름으로 지정할 수 있습니다.
두 번째는 addKey로 만든 키 객체에 직접 이벤트를 연결하는 방식입니다. 이 방식은 해당 키에 대한 down, up 이벤트를 세밀하게 제어할 수 있습니다.
세 번째는 모든 키 입력을 감지하는 방식입니다. 채팅 입력이나 이름 입력 같은 기능을 구현할 때 유용합니다.
event 객체를 통해 어떤 키가 눌렸는지 확인할 수 있습니다. 실무에서는 이 방식이 언제 유용할까요?
디버그 모드를 예로 들어보겠습니다. 개발 중에 물리 바운딩 박스를 보거나 FPS를 표시하고 싶을 때가 있습니다.
F1 같은 키에 디버그 토글 기능을 연결해두면 편리합니다. 이런 일회성 토글은 이벤트 방식이 훨씬 깔끔합니다.
주의할 점도 있습니다. 씬이 전환되거나 종료될 때 등록한 이벤트 리스너를 정리해야 합니다.
그렇지 않으면 이전 씬의 이벤트가 계속 남아서 예상치 못한 동작이 발생할 수 있습니다. Phaser는 씬 종료 시 대부분 자동 정리해주지만, 복잡한 경우 off 메서드로 직접 해제하는 것이 안전합니다.
김개발 씨는 ESC키 이벤트를 등록하고 일시정지 메뉴를 완성했습니다. "이벤트 방식이 이럴 때 정말 편하네요!"
실전 팁
💡 - 일회성 동작은 이벤트, 지속적 동작은 isDown 방식을 사용하세요
- 씬 전환 시 이벤트 리스너 정리에 신경 쓰세요
- keydown-키이름 형식으로 특정 키만 필터링할 수 있습니다
4. 마우스 클릭 처리
이제 키보드는 어느 정도 마스터한 김개발 씨. 다음 과제는 마우스입니다.
"화면을 클릭하면 캐릭터가 그 위치로 이동하게 해주세요." 포인트 앤 클릭 방식의 이동을 구현해야 합니다.
마우스 클릭 처리는 Phaser에서 포인터 입력을 다루는 방법입니다. 마치 리모컨으로 TV를 조작하듯, 마우스로 게임 오브젝트를 클릭하거나 화면의 특정 위치를 지정할 수 있습니다.
이것을 활용하면 클릭 앤 무브, 드래그 앤 드롭 같은 직관적인 조작을 구현할 수 있습니다.
다음 코드를 살펴봅시다.
// 화면 전체 클릭 감지
this.input.on('pointerdown', (pointer) => {
console.log('클릭 위치:', pointer.x, pointer.y);
this.movePlayerTo(pointer.x, pointer.y);
});
// 특정 게임 오브젝트 클릭 감지
this.button = this.add.sprite(400, 300, 'button');
this.button.setInteractive(); // 반드시 호출해야 클릭 가능
this.button.on('pointerdown', () => {
console.log('버튼이 클릭되었습니다');
});
// 좌클릭, 우클릭 구분
this.input.on('pointerdown', (pointer) => {
if (pointer.leftButtonDown()) {
this.attack();
} else if (pointer.rightButtonDown()) {
this.useSkill();
}
});
김개발 씨가 만드는 게임에 새로운 기능이 추가되었습니다. 플레이어가 화면을 클릭하면 캐릭터가 그 위치로 걸어가야 합니다.
RTS 게임이나 디아블로 같은 게임에서 흔히 볼 수 있는 방식입니다. "키보드는 어느 정도 익혔는데, 마우스는 어떻게 다루죠?" 박시니어 씨가 화면을 가리킵니다.
"Phaser에서는 마우스, 터치, 펜 입력을 모두 **포인터(pointer)**라는 개념으로 통합해서 다뤄요." 포인터란 정확히 무엇일까요? 쉽게 비유하자면, 레이저 포인터와 같습니다.
발표자가 레이저 포인터로 스크린의 특정 위치를 가리키듯, 포인터는 화면의 특정 좌표를 가리키는 역할을 합니다. 마우스 커서의 현재 위치, 눌린 버튼 정보 등을 담고 있습니다.
위의 코드에서 세 가지 중요한 패턴을 볼 수 있습니다. 첫 번째는 화면 전체의 클릭을 감지하는 방식입니다.
this.input.on('pointerdown', ...) 형태로 씬 전체에서 발생하는 클릭을 받습니다. pointer 객체의 x, y 속성으로 클릭 위치를 알 수 있습니다.
두 번째는 특정 게임 오브젝트의 클릭을 감지하는 방식입니다. 여기서 중요한 것이 setInteractive 메서드입니다.
이 메서드를 호출하지 않으면 해당 오브젝트는 클릭 이벤트를 받지 못합니다. 많은 초보 개발자가 이것을 놓치고 "왜 클릭이 안 되지?" 하며 고민합니다.
세 번째는 좌클릭과 우클릭을 구분하는 방식입니다. leftButtonDown, rightButtonDown, middleButtonDown 메서드로 어떤 버튼이 눌렸는지 확인할 수 있습니다.
이것을 활용하면 좌클릭으로 공격, 우클릭으로 스킬 사용 같은 조작을 구현할 수 있습니다. 실무에서 자주 사용하는 패턴이 있습니다.
버튼 UI를 만들 때 pointerdown뿐만 아니라 pointerover, pointerout 이벤트도 함께 활용합니다. 마우스가 버튼 위에 올라가면 하이라이트 효과를, 벗어나면 원래 상태로 돌아가게 하는 것입니다.
이렇게 하면 사용자에게 시각적 피드백을 줄 수 있습니다. 주의할 점도 있습니다.
브라우저에서 우클릭은 기본적으로 컨텍스트 메뉴를 띄웁니다. 게임에서 우클릭을 사용하려면 이 기본 동작을 막아야 합니다.
Phaser의 게임 설정에서 disableContextMenu: true 옵션을 주면 됩니다. 또한 클릭 위치가 게임 월드 좌표인지 화면 좌표인지 구분해야 합니다.
카메라가 이동하는 게임에서는 pointer.worldX, pointer.worldY를 사용해야 정확한 월드 좌표를 얻을 수 있습니다. 김개발 씨는 클릭 앤 무브 기능을 성공적으로 구현했습니다.
"마우스 조작도 생각보다 간단하네요!"
실전 팁
💡 - 오브젝트를 클릭 가능하게 하려면 반드시 setInteractive를 호출하세요
- 카메라가 움직이는 게임에서는 worldX, worldY를 사용하세요
- 우클릭을 사용하려면 disableContextMenu 설정이 필요합니다
5. 마우스 위치 추적
김개발 씨의 게임에 새로운 요구사항이 생겼습니다. "마우스 커서 방향을 바라보며 조준하는 기능을 넣어주세요." 슈팅 게임처럼 캐릭터가 마우스 커서 쪽을 바라봐야 합니다.
실시간으로 마우스 위치를 추적하는 방법이 필요합니다.
마우스 위치 추적은 매 프레임 마우스 커서의 현재 좌표를 확인하는 방법입니다. 마치 고양이가 레이저 포인터를 쫓아다니듯, 게임 캐릭터도 마우스 커서를 실시간으로 따라가거나 바라볼 수 있습니다.
이것을 활용하면 조준 시스템, 호버 효과, 드래그 기능 등을 구현할 수 있습니다.
다음 코드를 살펴봅시다.
// update 함수에서 마우스 위치 추적
update() {
const pointer = this.input.activePointer;
// 마우스 커서 방향으로 캐릭터 회전
const angle = Phaser.Math.Angle.Between(
this.player.x, this.player.y,
pointer.worldX, pointer.worldY
);
this.player.rotation = angle;
// 마우스가 움직이는 중인지 확인
if (pointer.isDown) {
// 드래그 중
this.drawLine(pointer.worldX, pointer.worldY);
}
}
// pointermove 이벤트로도 추적 가능
this.input.on('pointermove', (pointer) => {
this.crosshair.x = pointer.x;
this.crosshair.y = pointer.y;
});
슈팅 게임을 만들기 위해 김개발 씨는 새로운 도전에 나섰습니다. 캐릭터가 WASD로 이동하면서 마우스 커서 방향으로 총을 겨누어야 합니다.
탑다운 슈터에서 흔히 볼 수 있는 조작 방식입니다. "클릭할 때만이 아니라 마우스가 움직이는 것을 계속 추적해야 하는데, 어떻게 하죠?" 박시니어 씨가 설명합니다.
"activePointer 속성을 사용하면 현재 활성화된 포인터의 정보를 언제든 가져올 수 있어요." activePointer란 무엇일까요? 쉽게 비유하자면, CCTV 카메라와 같습니다.
CCTV가 특정 위치를 계속 촬영하고 있듯이, activePointer는 마우스 커서의 현재 상태를 항상 추적하고 있습니다. x, y 좌표는 물론이고 버튼이 눌려 있는지, 움직이는 중인지 등의 정보를 담고 있습니다.
위의 코드에서 핵심적인 부분을 살펴보겠습니다. Phaser.Math.Angle.Between 함수는 두 점 사이의 각도를 라디안 단위로 반환합니다.
캐릭터의 위치와 마우스 커서의 위치를 인자로 넣으면, 캐릭터가 마우스를 바라보기 위해 회전해야 하는 각도를 알 수 있습니다. 이 값을 그대로 rotation 속성에 넣으면 캐릭터가 마우스 방향을 바라봅니다.
여기서 worldX, worldY와 x, y의 차이를 이해해야 합니다. x, y는 화면(스크린) 좌표입니다.
브라우저 창 기준으로 마우스가 어디에 있는지를 나타냅니다. 반면 worldX, worldY는 게임 월드 좌표입니다.
카메라가 이동해도 실제 게임 세계에서의 위치를 정확히 알려줍니다. 예를 들어 카메라가 오른쪽으로 500픽셀 이동했다고 가정해봅시다.
화면 왼쪽 끝을 클릭하면 x는 0이지만, worldX는 500이 됩니다. 캐릭터 위치와 비교할 때는 반드시 월드 좌표를 사용해야 합니다.
pointermove 이벤트도 유용합니다. update 함수에서 매 프레임 체크하는 대신, 마우스가 실제로 움직일 때만 콜백을 실행하고 싶다면 pointermove 이벤트를 사용합니다.
십자선(crosshair) 스프라이트를 마우스 커서 위치에 표시하는 것이 대표적인 활용 예입니다. 실무에서는 이 기능을 다양하게 활용합니다.
RTS 게임의 유닛 선택 박스, 그림판 앱의 브러시 따라다니기, 카드 게임의 카드 드래그 등이 모두 마우스 위치 추적을 기반으로 합니다. 특히 드래그 앤 드롭은 isDown 속성과 결합하여 구현합니다.
주의할 점도 있습니다. update 함수에서 매 프레임 복잡한 계산을 하면 성능에 영향을 줄 수 있습니다.
각도 계산 정도는 괜찮지만, 매번 새로운 오브젝트를 생성하거나 많은 연산을 하는 것은 피해야 합니다. 김개발 씨는 캐릭터가 마우스 방향을 바라보는 기능을 완성했습니다.
"이제 진짜 슈팅 게임 같아졌어요!"
실전 팁
💡 - 월드 좌표와 스크린 좌표의 차이를 항상 인식하세요
- 성능이 중요하다면 pointermove 이벤트가 더 효율적일 수 있습니다
- Phaser.Math에는 각도, 거리 등 유용한 수학 함수가 많습니다
6. 터치 입력 지원
게임이 완성에 가까워지자 기획팀에서 새로운 요청이 들어왔습니다. "모바일에서도 플레이할 수 있게 해주세요." 김개발 씨는 터치 스크린 지원을 고민하기 시작했습니다.
마우스와 터치, 둘 다 지원해야 할까요?
터치 입력 지원은 모바일 기기의 터치스크린을 통한 입력을 처리하는 방법입니다. 다행히도 Phaser는 마우스와 터치를 포인터라는 하나의 개념으로 통합합니다.
마치 만능 리모컨처럼, 같은 코드로 마우스 클릭과 터치를 모두 처리할 수 있습니다. 다만 멀티터치처럼 터치만의 특별한 기능도 있습니다.
다음 코드를 살펴봅시다.
// 기본적으로 pointerdown은 터치에도 반응
this.input.on('pointerdown', (pointer) => {
// 마우스든 터치든 동일하게 처리
this.handleInput(pointer.worldX, pointer.worldY);
});
// 멀티터치 지원 (최대 10개까지)
this.input.addPointer(2); // 추가로 2개의 포인터 활성화
update() {
// 첫 번째 터치
const pointer1 = this.input.pointer1;
// 두 번째 터치
const pointer2 = this.input.pointer2;
if (pointer1.isDown && pointer2.isDown) {
// 두 손가락 핀치 제스처 감지
const distance = Phaser.Math.Distance.Between(
pointer1.x, pointer1.y, pointer2.x, pointer2.y
);
this.handlePinch(distance);
}
}
모바일 게임 시장이 커지면서 김개발 씨의 게임도 모바일 지원이 필수가 되었습니다. "마우스용 코드를 다 터치용으로 바꿔야 하나요?" 박시니어 씨가 웃으며 대답합니다.
"아뇨, 이미 다 되어 있어요. Phaser의 포인터 시스템 덕분에요." 왜 별도의 작업이 필요 없을까요?
Phaser는 설계 단계부터 크로스 플랫폼을 염두에 두었습니다. pointerdown, pointerup, pointermove 같은 이벤트는 마우스 클릭이든 터치든 동일하게 발생합니다.
앞서 작성한 마우스 코드가 그대로 터치에서도 작동합니다. 이것은 마치 USB 포트와 같습니다.
키보드를 꽂든 마우스를 꽂든 USB-A 포트는 그냥 받아들입니다. 마찬가지로 Phaser의 포인터 시스템은 입력 장치가 무엇이든 일관된 인터페이스를 제공합니다.
하지만 터치만의 특별한 기능도 있습니다. 바로 멀티터치입니다.
마우스는 커서가 하나뿐이지만, 터치스크린에서는 여러 손가락으로 동시에 터치할 수 있습니다. 핀치 줌, 두 손가락 회전 같은 제스처를 구현하려면 멀티터치 지원이 필요합니다.
기본적으로 Phaser는 2개의 포인터를 지원합니다. **this.input.addPointer(n)**을 호출하면 추가로 n개의 포인터를 활성화할 수 있습니다.
최대 10개까지 가능합니다. 위의 코드에서 멀티터치를 처리하는 방법을 볼 수 있습니다.
pointer1, pointer2는 각각 첫 번째, 두 번째 터치를 나타냅니다. 두 포인터가 모두 isDown 상태면 두 손가락이 화면에 닿아 있다는 뜻입니다.
두 점 사이의 거리를 계산하면 핀치 제스처를 감지할 수 있습니다. 실무에서 터치 UI를 디자인할 때 고려해야 할 점이 있습니다.
첫째, 터치 영역을 충분히 크게 만들어야 합니다. 손가락은 마우스 커서보다 정밀도가 떨어집니다.
버튼은 최소 44x44 픽셀 이상이 권장됩니다. 둘째, 호버 상태가 없다는 것을 기억해야 합니다.
마우스는 클릭하지 않고 위에 올려둘 수 있지만, 터치는 닿으면 바로 클릭입니다. 호버에 의존하는 UI는 터치에서 제대로 작동하지 않습니다.
셋째, 가상 조이스틱 같은 터치 전용 UI가 필요할 수 있습니다. 화면 일부에 가상 방향키를 배치하거나, 조이스틱 플러그인을 사용하는 방법이 있습니다.
주의할 점도 있습니다. 모바일 브라우저에서 터치 이벤트가 마우스 이벤트로도 변환되어 두 번 발생하는 경우가 있습니다.
Phaser는 대부분 이를 자동으로 처리하지만, 가끔 문제가 생길 수 있으니 실기기 테스트는 필수입니다. 김개발 씨는 게임을 휴대폰에서 테스트해 보았습니다.
"정말이네요, 그냥 되네요!"
실전 팁
💡 - 터치 버튼은 최소 44x44 픽셀 이상으로 만드세요
- 호버 상태에 의존하는 UI는 터치에서 문제가 될 수 있습니다
- 실제 모바일 기기에서 테스트하는 것이 중요합니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
EFK 스택 로깅 완벽 가이드
마이크로서비스 환경에서 로그를 효과적으로 수집하고 분석하는 EFK 스택(Elasticsearch, Fluentd, Kibana)의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 정리한 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
분산 추적 완벽 가이드
마이크로서비스 환경에서 요청의 전체 흐름을 추적하는 분산 추적 시스템의 핵심 개념을 배웁니다. Trace, Span, Trace ID 전파, 샘플링 전략까지 실무에 필요한 모든 것을 다룹니다.
CloudFront CDN 완벽 가이드
AWS CloudFront를 활용한 콘텐츠 배포 최적화 방법을 실무 관점에서 다룹니다. 배포 생성부터 캐시 설정, HTTPS 적용까지 단계별로 알아봅니다.