정보과목의 C언어 콘솔 게임 제작 수행평가 겸, 교내 IT 컨텐츠 경진대회 겸 간단한 게임을 제작해보았다.
코드와 실행파일은 깃허브에 올려두었다.
https://github.com/MinseobKimm/Journey-to-a-star
작품명 | Journey to a star | |
작품주제 | Astar 알고리즘을 이용한 2D타일맵 게임 |
0. 게임 플레이 방법 설명
게임의 목표는 ★(a star)에 도달하는 것 입니다.
별을 지키는 적이 플레이어를 쫓아옵니다.
적에게 잡히지 않고 최대한 빠른시간안에 별에 도달하면 됩니다.
벽을 세워서 적의 진로를 방해할 수 있습니다.
단 적과 플레이어 사이의 가능한 경로가 존재하지 않는다면 게임오버됩니다.
적은 A* 알고리즘(a star)을 이용하여 쫓아옵니다.
그리고 일반적인 A* 알고리즘과 달리 쫓아오다가도 별을 지키려하는 특성을 가집니다.
게임 클리어시 나오는 등급과 점수는 난이도가 높을수록, 시간이 조금 걸렸을수록 높습니다.
↑,←,↓,→ 또는 w,a,s,d로 캐릭터를 조작할 수 있습니다.
스페이스 바를 눌러서 벽을 설치할 수 있습니다.
시작화면에서 h를 눌러서 하드코어 모드를 플레이 할 수 있습니다.
1. 개발 동기
정보 R&E에서 Astar 알고리즘을 활용하여 간단한 인공지능을 구현했었습니다. 그 후 이를 적용하여 나만의 게임이 만들고 싶었습니다. 그래서 이와 같이 Astar 알고리즘을 활용한 “Journey to a star”라는 게임을 제작하게 되었습니다.
2. 작품의 장점이나 특징
이 게임의 가장 큰 장점은 2차원 맵에서 Astar알고리즘을 통해 플레이어를 쫓아오는 적이 구현되었다는 점입니다. Astar 알고리즘은 대표적인 길찾기 알고리즘 중 하나로, 1968년 피터 하트, 닐스 닐슨, 버트램 라팰이 처음 기술하였습니다. 이 알고리즘은 다익스트라 알고리즘을 확장시켜 만들어 졌습니다.
Astar 알고리즘을 공부하면서 저의 블로그에 내용을 정리해두었습니다.
https://minseob.tistory.com/13
적은 단순히 Astar알고리즘으로 플레이어를 쫓아오는 것이 아니라 플레이어가 별을 향해 가는 여정을 방해한다는 목표를 달성하기 위해 별을 지키면서 쫓아옵니다.이는 어떻게 보면 이 게임의 핵심이 될 수 있는 중요한 특징입니다.
3. 작품 구성도
4. 주요 기능 및 구현 방법
i. 플레이어 이동
플레이어의 이동은 총 네 가지 과정으로 구성했습니다.
1) 키보드 입력받기
2) 이동하려는 위치가 벽으로 막혀있지 않은지 확인
3) 아니라면 입력받은 키에 따라 플레이어 좌표 변경
4) 플레이어 기존 위치에 맵 출력
5) 새로운 플레이어 위치에 플레이어 출력
이 방법을 사용함으로서 system(“cls”);를 사용하여 매번 맵 전체를 다시 그릴 필요가 없었습니다.
ii. 적의 이동
이 게임에서는 적의 이동이 가장 구현하기 어려웠고, 또 가장 중요한 과정이었습니다. 적이 플레이어를 따라오도록 하기 위해 Astar 알고리즘을 공부하였으나 직접 코드를 짜기에는 무리가 있어 외부 코드를 사용하게 되었습니다. 외부 코드는 MIT라이선스를 가지고 있는 https://github.com/ralphgoodtimes/astar-plain-c
를 사용했습니다. 외부 코드를 많은 내용 수정하여 저의 게임에 사용할 수 있도록 하였습니다. main.c에서 맵 정보, 시작 좌표, 도착 좌표를 넘겨주면 astar.c에서 astar알고리즘을 통해 경로를 연결 구조체를 통해 저장합니다. 그 연결 구조체에서 이동 경로의 좌표를 역으로 하나씩 빼내다가 빼낸 좌표가 시작좌표라면 바로 전에 빼낸 그 좌표가 처음으로 적이 이동하게 되는 좌표가 됩니다. 이렇게 구한 처음 좌표값을 main.c로 반환 하는 방식입니다. 이렇게 반환된 새로운 좌표값을 받아서 적은 플레이어의 이동과 동일한 방식으로 이동하게 됩니다.
iii. 적이 a star를 지키면서 쫓아오도록 astar알고리즘 수정
이 기능은 의도하지 않았는데 어떻게 수정하다보니 적이 이전에 갔던 경로에 가중치를 두고 이동하는 것을 보고 별을 지키는 적을 통해 게임성을 만들어야겠다고 결심하게 되었습니다. 적이 길을 지키고 가만히 있는 것이 아니라 플레이어를 꾸준히 따라오면서도 플레이어가 별에 가까워지면 바로 길을 지키려고 돌아가려는 움직인 다는 점을 통해 게임의 재미요소가 존재할 수 있었다고 생각합니다.
iV. 플레이어와 적 사이에 가능한 경로가 존재하지 않을 때
플레이어와 적 사이에 경로가 존재 하지 않는다면 “NO POSSIBLE WAY” 라는 안내와 함께 게임오버되도록 구현했습니다. 이는 astar.c코드안에서 경로를 찾지 못하고 반복문을 빠져 나왔을 경우에 –5를 main.c에 return하여서 main.c안에서 –5가 return되었을 경우 GameOver()함수로 종료시키는 방법으로 구현했습니다.
V. 스페이스 바를 통해서 벽 설치
벽을 설치하는 과정은 은근 생각해야 할 것이 많았습니다. 왜냐하면 스페이스를 누르자마자 플레이어의 좌표위치의 맵이 벽으로 바뀌도록 한다면 그 순간 적의 Astar알고리즘에서의 도착지의 map값이 벽이 되므로 경로를 찾지 못하게 되버리기 때문입니다. 따라서 이를 해결하기 위한 변수 wall_check를 두고 다음과 같은 과정으로 벽을 놓도록 구현했습니다.
1)스페이스바 입력시 wall_check=1
2)플레이어 이동하였을 때 wall_check가1 이라면 기존 맵 좌표에 벽 출력
3)wall_check=0
Vi. 프로그램 전체적 루프
기본적으로 main함수 내에서 update()->render()->delay() 의 기본 구조를 가집니다. 이렇게 구현하지 않고 멀티스레드를 사용하거나 개별 함수에서 입력될때마다 update와 render를 바로 실행하면 gotoxy문에 의한 커서의 이동이 겹치면서 출력이 제대로 되지 않는 문제가 발생하게 됩니다.
Vii. 난이도 조절 기능 구현
난이도는 적의 이동속도에 따라 결정되도록 하였습니다.
이를 위해서 main함수에서 루프를 돌 때 임의의 변수 j를 선언한 후 루프를 돌때마다 1씩 더하되 1~(난이도)+3의 범위내에서 반복하도록 하였습니다. 그다음 enemyMove()함수에 j를 인자로 넘겨서 j가 1일경우 실행되지 않게 했습니다.
예를 들면 난이도가 1로 설정된경우 1~4에서 반복되는 j 중 1일때는 움직이지 않으므로 적의 속도를 플레이어의 속도의 3/4으로 낮추는 효과를 가져옵니다. 난이도가 2일때는 적의 속도가 플레이어 속도의 4/5로 설정됩니다.
Viii. 맵의 구성
맵은 사용자가 플레이하며 최대한 재미를 느낄 수 있도록 설계했습니다. 왼쪽 공터를 비워놓아 그 곳에서 적을 따돌릴려고 시도하면서 적의 이동패턴과 취약점을 파악할 수 있도록 유도했습니다. 그리고 오른쪽에는 섬세한 컨트롤이 필요한 미로 맵을 두어, 클리어 난이도를 높였습니다.
5. 화면 구성 및 인터페이스
i) 플레이 화면
2) 게임오버 화면
3) 게임 클리어 화면
텍스트언어로 처음 만들어본 게임이다. 꿈이 게임 개발쪽은 아니지만 성인이 되어서도 취미로 게임을 만들생각이다. 앞으로 많은 것을 배우고 나서 훨씬 수준 높은 게임을 만들고 싶다.
'정보 > C' 카테고리의 다른 글
벤포드의 법칙(Benford's Law) (0) | 2022.01.20 |
---|---|
원자의 전자배치 (0) | 2021.06.29 |