크레센도 Phaser + TypeScript TIL 5
다시하기를 누르면 1스테이지로 돌아갔다
게임오버 후 다시하기를 누르면 매번 1스테이지부터였다. S4에서 죽었는데 처음부터 다시 하라면 아무도 안 한다.
원인은 다시하기 버튼이 스테이지와 합류 멤버 정보를 일부러 지우고 있어서였다. 씬 밖 저장소(앞선 TIL 3의 registry)는 재시작해도 값이 남으니, 안 건드리면 현재 스테이지에서 이어진다.
“게임오버 = 현재 스테이지 재도전, 엔딩 클리어 = 처음부터”로 나눴다. 초기화는 클리어 때만 한다. 재시작에는 종류가 있고, 무엇을 남기고 무엇을 지우는지는 그 종류마다 따로 정한다.
보스전에는 잡몹이 없어서 회복이 없었다
컴패니언이 모일수록 화력은 세지는데 회복 수단이 없어서, 예준(힐)이 오기 전 스테이지에서 하민 체력이 버티지 못했다. 회복 수단을 넣기로 했다.
잡몹을 잡으면 일정 확률로 체력 하트가 떨어진다. 그런데 보스전은 칼리고 단독이라 잡몹이 없다. 그래서 보스 체력이 75%·50%·25%를 지날 때마다 하트를 뿌리게 따로 처리했다.
회복 수단을 “잡몹 드롭”으로만 정하면 잡몹이 없는 구간에서 조용히 사라진다. 규칙을 하나 넣을 때 그 규칙이 성립 안 하는 구간이 있는지 스테이지를 하나씩 짚어 본다.
스턴 한 번에 연달아 맞아 죽었다
피격 무적(맞은 직후 잠깐 안 맞는 시간)이 0.45초, 스턴(맞고 헤롱거리는 시간)이 1.2초였다. 무적이 먼저 풀리고 스턴이 남는 0.75초 동안 움직이지 못한 채 계속 맞았다. 한 번 걸리면 그대로 죽는 패턴이 됐다.
스턴을 줄 때 무적도 스턴 길이만큼 늘리기로 했다. 움직이지 못하는 동안은 추가 피해를 막는다.
두 값을 따로 정하면 둘 사이의 틈에서 억울한 상황이 나온다. “움직일 수 없음”과 “맞을 수 있음”이 겹치는 구간이 있는지 본다. 그 구간은 난이도가 아니라 벌이다.
공격이 무거워서 경직을 줄였다
공격 애니메이션이 700ms인데 그동안 내내 이동이 막히니 조작이 무거웠다. 앞선 TIL 2에서 공격 중 이동을 막기로 한 것의 뒷이야기다.
이동을 막는 시간을 애니메이션 전체가 아니라 타격 판정이 들어가는 구간(약 400ms)까지로 줄였다. 그 뒤엔 방향키를 누르면 공격이 취소되고 움직인다. 타격은 보장되고 반응은 살아난다.
경직 시간과 애니메이션 길이는 다른 값이다. 앞선 TIL 1에서 판정 구간을 애니메이션과 분리했듯, 경직도 분리한다. 애니메이션은 보이는 것이고 경직은 조작에 관한 것이라 같은 숫자일 이유가 없다.
UHD 모니터에서 글씨가 뭉개졌다
크레센도는 480×270의 낮은 해상도로 그리고 화면 크기에 맞춰 확대하는 픽셀아트 방식이다. 도트 캐릭터는 이 방식이 잘 맞는데, 글씨도 같이 확대되면서 UHD 모니터에서 뭉개졌다.
Phaser는 기본적으로 캔버스 하나에 캐릭터·배경·글씨를 전부 그린다. 글씨 해상도만 올리는 설정도 있지만 해 보니 여전히 뭉개졌고, 한글은 글자 수가 많아 비트맵 폰트로 미리 굽는 것도 비현실적이다.
그래서 글씨만 캔버스 밖으로 뺐다. Phaser는 캔버스 위에 투명한 HTML 층(DOM 레이어 — 브라우저가 HTML 요소를 그리는 층)을 올리는 기능이 있다. 거기에 둔 글씨는 브라우저가 벡터 폰트로 직접 그리니 어떤 배율에도 선명하다. 픽셀 폰트(Galmuri11)로 게임 분위기도 맞췄다.
대신 이 층의 글씨는 항상 캔버스 위에 있어서 게임 오브젝트 뒤로 숨길 수 없다. HUD처럼 늘 맨 위에 있는 글씨에는 맞고, 월드 안에 묻혀야 하는 글씨에는 못 쓴다. 선명함을 얻는 대신 층 순서를 잃은 것이다.