본문 바로가기

Studying/Python

17. miniProject(8) - 뱀 게임 1 (feat. turtle)

이번엔 좀 여러 단계를 거쳐야하는 프로젝트를 해보도록 하자. 

 

지렁이 키우기라는 게임으로 우리에게 더 익숙한 종류의 게임을 만들어 볼것이다. 

 

화면에 랜덤으로 노란색 먹이가 나타날 것이다. 

 

몸길이가 20x20 정사각형 3개로 시작하는 뱀은 키보드에 맞게 화면을 돌아다니다 먹이를 먹으면 길이가 1개 추가된다. 

 

뱀은 화면의 각 모서리에 머리를 부딪히면 죽는다. 또 몸길이가 너무 길어졌을 떄, 머리가 자신의 몸통과 부딪혀도 죽는다. 

 

화면의 상단에는 현재 스코어와 최고 스코어가 표현될 것이고 최고 스코어는 data.txt 파일로 관리할 것이다. 

 

뱀이 죽을 경우 자동으로 게임은 초기화, 재시작된다. 

 

파일은 게임진행관련하여 main.py, 먹이가 랜덤으로 화면에 나타날 food.py, 점수판을 관리하는 socreboard.py,

 

그리고 뱀의 움직임 등을 관리할 snake.py로 나누어서 작성할 것이다. 

 


먼저 snake.py부터 시작해보자. 

 

snake 기본 설정

snake의 가장 기본 설정이다. 

 

snake의 시작 포지션 STARTING_POSITIONS은 (0, 0)으로부터 왼쪽으로 3칸이다. 

 

기본 이동 거리는 MOVE_DISTANCE로 20으로 설정한다. 한번에 뱀 몸통 한칸만큼 간다는 소리이고 이를 통해 게임 난이도를 나중에 관리할 수도 있다. 

 

그리고 각 방향을 나타낼 변수로 UP, DOWN, LEFT, RIGHT에 직각이 되는 각도를 할당했는데 이는 이따가 setheading을 통해 사용될 숫자이다. 

 

class Snake(1)

 

이제 Snake class를 만들어보자. 

 

class를 새로 만들었으니까 def __init__(sefl)를 통해 초기화해주자. 

 

이 때, 몸통을 이루는 정사각형을 관리할 빈 list segments를 만들고, 뱀의 headsegments의 첫 인자를 할당한다. 

( self.segments = []   //  self.head = self.segments[0] )

 

그리고 초기화하면서 자동적으로 creat_snake() 함수라 실행되도록 만든다. ( self.create_snake() )

 

그리고 create_snake() 함수를 선언한다. 

 

앞서 선언했던 STARTING_POSITIONS의 각 position에 해당하는 변수(위치) 를 add_segment() 함수에 인자로 넘긴다.   ( 이렇게 되면 각각의 시작 위치에 맞게 뱀의 몸통(정사각형)을 생성하도록 add_segment 함수를 사용하는 것 )

 

이제 add_segment(self, position) 함수를 선언하자. ( 이 떄 인자로 윗줄에서 말한 position을 넣자 )

 

Turtle의 모양을 흰색  square로 설정하고 이를 new_segment로 저장한다. 

 

우리는  snake 가 이동하는 것만 보면 되고 기록되는 것은 원하지 않기에 penup() 한다. 

 

이렇게 생성된 new_segment를 함수인자로 받았던 position으로 보낸다. 

( 이렇게 되면 인자로 받을 position 위치에 뱀이 생성되는 것 )

 

이번엔 snake가 죽고 게임이 다시 시작되는 경우를 생각해서 reset() 함수를 만들어보자. 

 

게임이  다시 시작되도록 하기 위해선 화면에 snake가 사라졌다가 다시 STARTING_POSITIONS로 위치하도록 한다.

 

따라서 뱀 몸통에 해당하는 segments의 각 몸통을 for 문을 통해 (1000, 1000) 위치로 보내버린다. (화면 밖으로)

 

그리고 segments.clear()을 사용하여 초기화한 후, 위에서 만든 create_snake() 함수로 다시 snake를 만들고 head를 지정한다. 

 

snake가 먹이를 먹으면 몸통 길이가 한 칸 증가해야한다. 

 

이 때 꼬리에 한 칸 늘어나게 한다기보다 head position 앞에, 즉 segments[-1] 위치에 추가하도록 설정한다. 

( 이렇게 되면 새로 생기는 몸통 한 칸이 add_segment() 함수를 통해 -1 위치에 들어가고 새로운 head가 생성되는 것 )

 

class Snake(2)

 

이제 뱀이 실제 움직이는 move() 함수를 선언한다. 

 

뱀의 머리칸이 1, 두번째 칸이 2라고 해보자. 뱀이 앞으로 이동하면 2의 x 위치는 1의 이전 위치를 받게 된다. 

 

이와 비슷한 원리로 new_x, new_y 변수에 각각의 새로운 x, y 좌표를 할당하고 그 좌표로 각각의 segment가 이동하도록 for 문을 사용한다.

 

우리가 키보드를 사용할 떄 main.py에서  함수로 사용될 4개의 방향 함수를 만들자. 

 

뱀이 오른쪽으로 이동하고 있을 때, 곧바로 왼쪽으로 이동하는 것과 같은 경우를 막기 위해 if 조건을 추가해주자. 

( 위에서 말했듯이 setheading 사용 )

 


이제 화면에 랜덤하게 나타날 food를 만들어보자. 

 

food.py

 

food.py는 좀 간단한다. 

 

먼저 Food class를 선언한다. 

 

이때, 우리는 turtle.Turtle를 상속받아 사용하니까 super().__init__()를 잊지말고 쓰자. 

 

모양은 circle, 색은 yellow, 역시 pen 그리기는 필요없으니 penup(),  circle의 크기는 0.5 x 0.5로 설정한다. 

 

그리고 food는 없어진 다음 바로 화면에 출력이 되야하기 때문에 speedfastest로 설정한다. 

(먹이가 랜덤한 위치로 이동하는 걸 보여줄 필요가 없다)

 

그리고 뱀이 먹이를 먹으면, 새롭게 먹이가 나타나야한다. 이를 관리할 함수로 refresh() 를 선언하고 랜덤한 위치에서 나타나도록 설정한다. 

 

이렇게 하면 snake.pyfood.py를 완성한 것이다. 

 

이제 scoreboard.py와 게임 진행을 다룰 main.py를 작성하면 된다. 

 

나머지 부분은 다음 게시물에서 다루도록 하자.