42Seoul [so_long]
so_long
요약: 이 프로젝트는 아주 간단한 2D 게임을 만들어 볼 겁니다. 텍스쳐, 스프라이트, 기본적인 게임플레이 요소들을 다뤄볼 있도록 설계되어 있어요.
- 이번과제에서는 간단한 게임을 만드는 과제입니다..!
앞서 지켜야하는 사항들은 마찬가지..!
프로그램 이름 | so_long |
---|---|
제출할 파일 | all,clean,gclean,re,bonus |
makefile규칙 | *.bar형식의 맵 |
인자 | open, close, read, write, malloc, free, perror, strerror, exitMinilibX 라이브러리 내의 모든 함수들 |
사용가능한 외부 함수 | 사용 가능 |
설명 | 여러분은 돌고래가 물고기 몇 마리를 잡아먹은 뒤 지구를 탈출하는 작은 2D 게임을 만들어야 합니다. 굳이 돌고래나 물고기가 될 필요는 없습니다. 주인공이 특정 수집품을 모은 뒤 공간을 떠나는 방식이면 됩니다. |
규칙
-
반드시 miniLibX를 사용해야 합니다. (운영체제에서 이용 가능한 라이브러리와 과제에서 제공되는 소스 중 하나를 사용하셔야 합니다) 만약 제공받은 소스를 이용해 작업하기로 했다면, Libft의 공통 지침 (Common Instructions) 과 같은 규칙을 따라야 합니다.
-
작업 창 관리는 부드럽게 동작하여야 합니다. (창 최소화, 다른 창으로 전환 등의 동작)
-
예시로는 물고기를 잡아먹는 돌고래를 들었지만, 주제는 어떤 것으로 정하셔도 상관 없습니다.
-
지도는 세 가지 요소들로 구성되어 있습니다: 벽, 수집품, 그리고 빈 공간
-
플레이어의 목표는 모든 수집품을 모으고 최소한의 움직임으로 맵을 탈출하는 것입니다.
-
각 움직임마다 현재까지 움직인 횟수가 쉘에 출력되어야 합니다.
-
플레이어는 다음 방향으로 움직여야 합니다: 상하좌우
-
게임은 2D 시점으로 제작하여야 합니다. (탑뷰 또는 프로필)
-
실시간으로 진행되는 게임일 필요는 없습니다.
-
플레이어는 벽을 뚫고 지나갈 수 없습니다.
- 프로그램은 다음과 같은 룰을 따르며 이미지를 화면에 표시하여야 합니다
- W, A, S, D 키를 이용하여 주인공을 조작합니다.
- ESC는 창을 닫고 게임을 정상적으로 종료합니다.
- 창 좌상단의 빨간 버튼 (mac) 또는 우상단의 빨간 X (windows) 를 누르면 창을 닫고 게임을 정상적으로 종료합니다.
- minilibX의 images를 사용하는 것을 강력히 추천합니다!
- 여러분의 프로그램은 .ber 확장자의 파일을 첫 번째 인자로 받아야 합니다.
- 지도는 단 5개의 가능한 문자열로만 구성되어야 합니다: 0은 빈 공간, 1은 벽, C는 수집품, E는 맵의 출구, P는 주인공의 시작지점입니다.
- 지도는 벽으로 둘러쌓여 있어야 합니다. 그렇지 않으면 에러를 반환해야 합니다.
- 지도는 최소한 하나의 출구, 하나의 물고기 (수집품), 하나의 시작 지점을 포함해야 합니다.
- 지도에서 출구로 가는 길의 유무 판단 (검증)은 굳이 해주지 않으셔도 됩니다.
- 지도는 반드시 직사각형 모양이어야 합니다.
- 이하의 규칙을 준수한 모든 종류의 지도를 파싱할 수 있어야 합니다.
- 지도 파일에서 어떠한 허점이 발견된다면, 프로그램은 “Error\n” 과 여러분이 직접 정한 에러 메시지를 출력한 후 제대로 종료되어야 합니다.
1111111111111
10010000000C1
1000011111001
1P0011E000001
1111111111111
---
1111111111111111111111111111111111
1E0000000000000C00000C000000000001
1010010100100000101001000000010101
1010010010101010001001000000010101
1P0000000C00C0000000000000000000C1
1111111111111111111111111111111111
보너스
-
보너스 리스트
- 적 추가. 주인공이 적에게 닿으면 게임에서 패배합니다.
- 스프라이트에 움직임을 주는 건 어떨까요?
- 쉘 대신, 화면상에 현재까지 움직인 횟수를 출력할 수도 있습니다.
시작하기전에 필요한 정보들
문제를 해결하기위한 정보도 있지만 문제를 순차적으로 접근하는 것이 유리하다..!
순차적으로 접근하기 위해 정리하자면
- 해당 라이브러리 사용법
- 키 매칭
- 맵 만들기
정도로 정리된다.
MiniLibx
man으로 검색하면 나오는 첫 문장이 학생을 위한 간단한 window인테페이스 라이브러리로 나온다.
MiniLibx는 그래픽라이브러리로 크게 그래픽에 대한 지식없이도 렌더링할 수 있게 해주는 라이브러리다.
스스로 많이 사용하지 않을 것 같기 때문에 함수의 구조자체는 공부할 수 있겠지만 함수의 기능을 전부 공부하지 않겠다.
이 라이브러리가 창관리를 자동으로 해준다.
기본적으로 해당 라이브러리를 사용하기 위해선 해당 과제란에서 다운 받아서 사용한다.
같은 폴더에 해당 라이브러리를 넣어두고 기본적인 main.c를 작성하여 테스트한다.
#include "./mlx/mlx.h"
int main(void)
{
void *mlx_ptr;
void *win_ptr;
mlx_ptr = mlx_init();
win_ptr = mlx_new_window(mlx_ptr, 300, 300, "mlx_test");
mlx_loop(mlx_ptr);
}
cc -L./mlx -lmlx -framework OpenGL -framework AppKit main.c
위의 컴파일 명령어를 통해 실행파일을 테스트 한다.
- void * mlx_init(void)
- 나의 소프트웨어와 OS의 디스플레이를 연결해주는 함수
- 연결 실패시 NULL리턴
- void * mlx_new_window(void mlx_ptr, int size_x, int size_y, char *title)
- 디스플레이에 새로운 윈도우를 띄우는 함수로 가로/세로 크기를 받아서 띄운다.(title은 이름)
- int mlx_loop(void *mlx_ptr)
- 띄운 창에서 키보드와 마우스의 입력을 loop하며 기다린다.(계속해서 다시 그린다.)
- 이벤트를 받기 위해서 꼭 써야하는 함수
이벤트 제어
대기할 때 이벤트가 발생하면 해당 이벤트에 맞는 함수를 실행할 수 있다.
- 키를 눌렀을 경우
- 마우스 버튼을 눌렀을 경우
- 창의 일부를 다시 그리는 경우 expose이벤트라고 한다.
int mlx_hook(void win_ptr, int x_event, int x_mask, int (funct)(), void *param);
이 과제에서 가장 사용하기 쉽고 범용성이 좋은 이벤트함수로 X11의 이벤트 x_mask는 사용하지 않는다, 해당 함수, 인자값으로 전달한다.
해당 키가 눌리면 해당 동작이 실행되는 파싱함수로 한번 감싸고 세분화하여 호출하면 된다.
이미지 그리기
이 과제에서 이미지를 그리기 위한 과정은 2가지다.
- 해당 xpm파일을 변수로 연결짓기 init 과정
- 해당 이미지 변수를 크기에 맞게 window에 찍기
1번 함수는 mlx_xpm_file_to_image()
함수로 void형 포인터로 받는다.
void *mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height)
2번 함수는 해당 win에 찍어는 함수로 크기, 이미지를 필요로 한다.
int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y)
위와 마찬가지로 함수로 묶어서 해당 함수를 호출하는 식으로 작성하면 된다.
xpm
xpm파일이란 X11 Pixmap Graphic이라고 한다.
X11이 자주 등장한다.
X Windows 시스템에서 사용하는 비트 맵 이미지
네트워크로 연결된 클라이언트 서버 컴퓨터를 실행하는 데 사용되는 (GUI)
단색, 회색조 및 컬러 픽스맵 데이터를 지원합니다. pixmap을 C 프로그래밍 언어의 정적 문자 배열로 저장합니다.
풀이 과정
앞서 말한 순서에서 조금 변형해서 개발하였다.
- 윈도우 띄우기
- 이미지 찍기
- 키 매칭
- 게임 규식 설정
- 게임 에러 처리
크게 어렵지 않은 과제였지만 함수를 가볍게 만들기 위해 노력했던것 같다.
++ error 처리 규칙에 있어서 조금 문제가 있었다.
get_next_line으로 읽어서 한줄로 처리하다 보니
1111
10P1
1EC1
11111
111
이러한 맵형태가 인정되어 버려서 읽어들이면서 검증을 추가하고
1
1
1
1
1
0
...
이러한 형태도 입력 받을 수 있으니 width가 3이상만 직사각형 맵으로 인식 가능하도록 하였다.
댓글남기기