타자 연습 게임, 타이핑 몬스터(7) - 스테이지, 타수

회사일 하면서 별도로 집에서 취미로 게임 개발하는게 참 쉽지가 않은 것 같습니다. 아무리 힘들어도
명색이 타자연습게임인데 타수랑 정확도를 표시하지 않고 마무리하는 건 좀 아닌 듯 하다는 생각이 들었습니다.
그리고 타자연습 게임은 플레이어의 타이핑 수준에 맞도록 게임의 속도 조절이 필요한데
그런 처리를 하려면 게임 스테이지가 분리되서 각 스테이지별로 속도를 따로 처리해 줘야 해야합니다.
그래서 스테이지를 적용하고 본인의 능력을 알 수 있도록 타수와 평균타수, 정확도를 표시하고
몇 마리를 잡아야 다음 스테이지를 넘어가는지 알 수 있도록 목표 수도 같이 표시하는게 좋을 것 같습니다.
스테이지 정보는 아래와 같은 구성으로 설계했습니다.
stage | 스테이지 번호 |
mobCnt | 등장 최대 몬스터 수, 해당 수 만큼 정확하게 타이핑을 해야 다음 스테이지로 넘어감 |
spawnMinTime | 몹이 등장하는 최소시간 |
spawnMaxTime | 몹이 등장하는 최대시간 |
mobMinSpeed | 몹 최소 속도 |
mobMaxSpeed | 몹 최대 속도 |
mobSkillProba | 몹 스킬 시전 확률, 스테이지가 높을 수록 확률 높임 |
wordMinLen | 타이핑할 문자의 최소 글자 수 |
wordMaxLen | 타이핑할 문자의 최대 글자 수 |
스테이지 번호가 높아질 수록 난이도를 어렵게 하려면
몹이 등장하는 시간을 관리해줘야합니다. 등장 최소, 최대시간을 조절해서 유저가 점차
빠르게 등장하는 느낌이 들 수 있도록 처리해 봤습니다.
동일하게 몹의 속도와 문자의 최소,최대 글자수도 스테이지별로 관리해줬습니다.
위의 데이터는 JSON 형태로 생성했습니다.
원래 sqlite를 이용해서 DB로 관리하려고 했는데
DB를 통해서 관리하는 건 좀 더 복잡한 게임을 개발하게 되면 적용해 볼 생각입니다.
[{ "stage": 1, "mobCnt": 10, "spawnMinTime": 3000, "spawnMaxTime": 3500, "mobMinSpeed": 0.3, "mobMaxSpeed": 0.3, "mobSkillProba": 0.000009, "wordMinLen": 2, "wordMaxLen": 3 },
{ "stage": 2, "mobCnt": 15, "spawnMinTime": 2800, "spawnMaxTime": 3300, "mobMinSpeed": 0.3, "mobMaxSpeed": 0.3, "mobSkillProba": 0.000008, "wordMinLen": 2, "wordMaxLen": 3 },
{ "stage": 3, "mobCnt": 20, "spawnMinTime": 2600, "spawnMaxTime": 3100, "mobMinSpeed": 0.3, "mobMaxSpeed": 0.4, "mobSkillProba": 0.00009, "wordMinLen": 2, "wordMaxLen": 4 },
....
화면 상단 중앙에는 스테이지 표시!!

화면 하단 우측에는 스테이지에서 처리해야할 몬스터 수와 현재 입력 중인 타수, 평균 타수, 정확도를 표시했습니다.

그리고 플레이어가 사망하는 시점에는 GAME OVER를 화면 중앙에 표시하고
다시 플레이 할지 물어보도록 변경했습니다. 이 부분은 기존에 개발한 운석 피하기 게임과 동일합니다.

타수 구하는 공식은 chatgpt한테 물어본 걸로 해 보니 너무 어이없는 값이 나와서 제 느낌대로 해봤습니다.
느낌상 chatgpt는 영어권 출신(?)이라 타수를 구하는 기준이 한국어가 아닌 영어의 단어가 기준 아닌가 추측해 봅니다.
타이핑 몬스터는 한국어 전용 게임이라 한국어 기준으로 할 생각입니다.
제 나름대로 공식을 간단하게 생각해 봤습니다.
우선, '안녕'이라는 글자를 입력하는 경우를 생각해 봤습니다.
ㅇ ㅏ ㄴ | 3 타 |
ㄴ ㅕ ㅇ | 3 타 |
안녕을 완성하려면 총 6번 키보드를 눌러야 합니다.
제가 만약 1초만에 안녕이라는 단어를 타이핑했다고 가정하면 60초에는 몇 타를 칠 수 있을까요?
간단한 수학 문제입니다.
방정식을 만들면 1초 : 6타 = 60초 : x 이므로 x = 360, 이렇게 360타가 나오게 됩니다.
그런데 게임에서 좀 돌려보면 가끔 제가 어마무시한 속도로 쳤다고 나오는 경우가 있습니다. ^^;
제 키보드 평균타수가 300~400정도 였인데 가끔 700을 찍는 걸 보면 뭔가 오류는 있는 것 같습니다.
시간을 체크하는 부분이 강하게 의심이 드는데 이건 차차 찾아보도록 하겠습니다.
타이핑 글자가 정확한지 체크하는 로직에
현재 스테이지의 최대 몹수를 확인하고 이를 넘겨서
타이핑 성공한 경우에는 다음 스테이지로 넘어가도록 처리했습니다.
추가로 오타 입력 시, 정확도를 계산을 위해
타이핑 오류 횟수(typing_error_cnt)도 계산하도록 처리했습니다.
def check_hit(self, text, typing_speed):
if text == "":
return
hit_yn = False
for e in self.enemy_text_sprites:
if e.text == text:
hit_yn = True
e.destroy()
if e.rect.centerx >= cfg.SCREEN_WIDTH / 2:
self.player.attack("RIGHT")
self.resources.machinegun.play()
else:
self.player.attack("LEFT")
self.resources.machinegun.play()
break
if hit_yn:
self.stage_hit_cnt += 1
self.typing_correct_cnt += 1
self.typing_speed = typing_speed
self.typing_total_speed += typing_speed
self.typing_speed_avg = round(self.typing_total_speed / self.typing_correct_cnt, 2)
if self.stage_hit_cnt >= self.stage_hit_goal_cnt:
self.stage_no += 1
self.stage_hit_goal_cnt = self.resources.stage_info[self.stage_no]["mobCnt"]
self.stage_hit_cnt = 0
self.resources.stage_up.play()
self.spawn.next_stage()
else:
self.typing_error_cnt += 1
제가 직접 품질팀 담당자가 되어서 스테이지 1부터 최종 스테이지까지 돌려본 결과
최종 스테이지는 정말 어렵네요. -_-)3;
그리고 몹을 너무 많이 잡아야하는 문제도 있는 듯 합니다. 개발하는 거 보다 테스트하다가 치쳤습니다.
게임 개발에서 이런 부분을 레벨 디자인이라고 한다고 들었습니다.
레벨 디자인이 잘 되어야 플레이하는 사람들이 중간에 포기하지 않고
끝까지 게임을 할 수 있다고... ㅠㅠ
버그는 그닥 별로 없어 보이는데 이 게임의 레벨 디자인이 많이 꽝인 듯 합니다.
게임 개발할 시간도 부족한 상황인데
레벨 디자인까지는 좀 무리인 듯 싶습니다.
나중에 좀비 에셋도 많이 만들고 좀 더 그럴싸한 게임으로 고도화할 때
조금 더 다듬는 걸로 하겠습니다.
다음 포스트는 정말 마지막입니다.
초기 메뉴 화면과 인스톨 파일까지 정리해러 올리고 길고
긴 타이핑 몬스터, 타자연습게임 개발을 마무리할 생각입니다.
개발된 소스코드를 첨부합니다.
첨부된 소스와 에셋은 뭐 대단한 거는 아니지만 마음껏 사용하셔도 무방합니다.