본문 바로가기

42Seoul

[42Seoul] so_long

Summary:
This project is a very small 2D game. Its purpose is to make you work with textures, sprites, and some other very basic gameplay elements.


Common Instructions

Program name
so_long
Turn in files
Makefile, *.h, *.c, maps, testures
Makefile Name, all, clean, fclean, re
Arguments A map in format *.ber
External functs.
- open ,close, read, write
- malloc, free, perror, strerror, exit
- All functions of the math library and th MiniLibX
- ft_printf and any equivalent you coded
Libft authorized
yes
Description
you must create a basic 2D game in which a dolphine escapes Earth after eating some fish. Instead of a dolphine, fish, and the Earth, you can use any character, any collectible and any place you want.

 

  • 더보기
    • 파일
      • MiniLibX 사용해야 합니다.
      • Makefile 제출.
      • 프로그램은 '.ber'확장자로 끝나는 맵 기술 파일을 파라미터로 취해야 합니다.
    • 게임 플레이
      • 게임 목표 : 맵의 모든 수집품을 수집하고, 가능한 가장 짧은 경로를 선택해 탈출
      • W,A,S,D 키를 사용해 캐릭터를 움직임(상하좌우 4방향)
      • 벽으로 이동 불가
      • shell에 현재 이동횟수 보여야 함
      • You have to use a 2D view (top-down or profile).
      •  
        꼭 실시간일 필요는 없다.
    • 그래픽
      • window로 게임을 보여야 함
      • window  관리 (다른 윈도우로 전환, 최소화, 최대화 등)
      • ESC키를 누르기와 종료버튼을 클릭하는것으로 윈도우를 닫고 프로그램을 종료
      • MiniLibX의 이미지를 사용해야 함

      • 5가지 문자
        • 0 : 빈 공간
        • 1 : 벽
        • C : 수집품 ( 최소 1개)
        • E : 탈출구 (최소 1개)
        • P :  시작점 ( 최소 1개)
      • 직사각형
      • 벽으로 둘러쌓여야 함. 
        • if not, 에러 반환
      • 유효한 경로가 있는지 체크
      • 어떠한 종류라도 parsing 할수 있어야 함.
      • 잘못된 구성이 있다면, 깔끔히 종료되고, "Error\n" + "CUSTOM_ERROR_MESSAGE" 반환

 


prerequisite

  • miniLibX란
    • 작은 그래픽 라이브러리. 무언가를 스크린에 렌더링하게 해줌
    • 간단한 window 생성, 그리기 도구, 이미지 함수 그리고 이벤트 관리 체계를 제공함
  •  function()
    • mlx_init()
      • 그래픽 시스템에 연결하고, 현재 MLX 인스턴스의 위치를 갖는 void 포인터를 반환
    • mlx_new_window()
      • 생성한 윈도우의 포인터를 반환
    • mlx_loop()
      • 윈도우 렌더링
    • mlx_hook() 
      • 특정 이벤트를 기다리고, 이벤트 발생시, 명시된 함수 호출.
    • mlx_xpm_file_to_image()
      • xpm파일을 이미지로 저장하고 그 포인터를 반환
  • hooking 이란?
    •  런타임시 OS, 앱 또는 코드 조각의 그 동작을 가로채거나 변조하는 작업.
    • 디버깅이나 모니터링 또는 그외 다양한 동작을 할수 있다.
      • ex) 키보드나, 마우스의 이벤트를 입력을 기다리다, 입력이 오면 그에 상응하는 행위를 한다거나..
  • dfs

TIPS

  • m1 mac사용자라면...
    • 컴파일시 옵션 추가.    arch -x86_64  

IDEAS

  • get_next_line() 함수를 이용해 '.ber' 맵 파일을 읽어들이고, 2차원 배열로 저장.
  • 맵이 규칙을 준수했는지, 유효한 경로가 있는지 검증.
  • 윈도우를 열어주고, 이미지를 렌더링.
  • 특정 키 후킹
  • 후킹 이벤트 발생시마다 상황을 반영해, 이미지 다시 렌더링

CODES

#include "so_long.h"

int	main(int argc, char **argv)
{
	t_game	*game;
    
	game = malloc(sizeof(t_game));
					//포인터로 선언해줬기에 동적할당해줘야 한다.
	game->mlx = mlx_init();
					//mlx를 실행해주며 반환된 포인터를 저장해준다.
	game->img.player = mlx_xpm_file_to_image(mlx, "./images/player.xpm", &width, &height);
					//xpm파일을 구조체에 이미지로 만들어 구조체에 저장해준다.
	gnl_ber_to_array(filename, game);
					//get_next_line()함수를 사용하여, '.ber'맵파일을 2차원 배열로 만들어 저장해줌.
	check_map(game);
					//확장자, 벽, 구성요소, 직사각형 형태, 유효경로 등을 검증
	game->win = mlx_new_window(game->mlx, game->width * XPM_BIT, game->height * XPM_BIT, "so_long");
					//mlx라이브러리의 윈도우 생성 함수.
	render_img(game);
					//이미지를 윈도우에 그려줌.
	mlx_hook(game->win, KEY_PRESS, 0, &hook_key_press, game);	    								
	mlx_hook(game->win, DESTROY_NOTIFY, 0, &esc_game, game);
			//특정 이벤트를 기다린다. 이벤트 발생시, 명시된 함수 실행. 그 함수의 파라미터로 game 보내줌
	mlx_loop(game->mlx);
					//프로그램이 이벤트를 기다리도록 만들어줌
	free(game);
}
/* 
hook_key_press()
*/

int	hook_key_press(int key_code, t_game *game)
{
	if (key_code == KEY_A)
 		move_player(game, KEY_A);

			/*-----생략-------*/
}
/*
move_player()
*/

void	move_player(t_game *game, int key_code)
{
	t_vector	vect;
	t_vector	new_vect;

	vect = current_position(game);
		//현위치 좌표를 받아옴.
	new_vect = new_position(game);
		//이동할 좌표를 받아옴.

	/*-----이동위치의 타입에 따라 설정-----*/
    
	/*----만약 이동이 가능하다면----*/

	game->map[vect.i][vect.j] = '0';
	game->map[new_vect.i][new_vect.j] = 'P';
		//현위치는 공터로, 이동할 위치는 플레이어 위치로 바꿔줌
	ft_putnbr_fd(++game->num_step, 1);
		//걸음수 증가, 출력
	render_img(game);
		//변경 정보를 반영하여 이미지 다시 렌더링
}
/*
render_img()
*/
    void	render_img(t_game *game)
    {
		for(int i=0; i<game->height; i++){
			for(int j=0; j<game->wiedt; j++){
				if (game->map[i][j] == 'P')
					mlx_put_image_to_window(game->mlx, game->win, game->img.player,\
					j * XPM_BIT, i * XPM_BIT);
						//윈도에 이미지 넣어줌.
			}
		}
	}

유효 경로 검증

 

주어진 맵에 게임 완료를 위한 유효한 경로가 있는지 확인하는 함수를 만들어야 했다.

유효한 경로의 조건을 무엇일까 고민했다. 일단, 출구, 수집품 그리고 플레이어가 벽으로 둘러쌓이지 않아야 하고,

가는길에 폐쇄된 길목이 없어야 하고... 그 정확한 조건을 도출하기가 어려웠다.

그래서 dfs 알고리즘을 사용해보기로 했다. 

사실 여러번 공부해봤지만, 사용할 기회가 적어서 그런지, 개념이 완벽히 이해가 안가고 머리 안을 둥둥 떠다니는것 같아

막연히 어려웠던 알고리즘이었다.

 

일단 chatGPT에게 재귀함수로 dfs 알고리즘의 예제를 부탁했다.

 

해당 코드의 동작을 자세히 뜯어 보면,

  1. 정점의 수, 시작 위치, 인접행렬 을 아는 상태에서 시작한다.
  2. 각각의 정점에 대해 방문 여부를 확인할수 있는 배열을 만들어준다.
  3. 현재 정점과 연결되어 있으며, 아직 방문을 안한 정점이 있다면, 그 정점을 탐색해주는것이다.

이를 이용해 유효 경로가 있는지를 확인해주었다.


시연영상

 

 

 

 

'42Seoul' 카테고리의 다른 글

ft_printf.c  (0) 2022.12.21
get_next_line.c  (0) 2022.12.17