본문 바로가기

Studying/Python

18. miniProject(8) - 뱀 게임 2 (feat. turtle)

앞서 작성하던 뱀 게임 1 에 이어지는 내용을 작성하려 한다.

 

게임에 대한 전반적인 내용은 이전 게시물을 확인해보자. 

 

https://headingtocoding.tistory.com/19

 

17. miniProject(8) - 뱀 게임 1

이번엔 좀 여러 단계를 거쳐야하는 프로젝트를 해보도록 하자. 지렁이 키우기라는 게임으로 우리에게 더 익숙한 종류의 게임을 만들어 볼것이다. 화면에 랜덤으로 노란색 먹이가 나타날 것이다

headingtocoding.tistory.com

 


이전 게시물에서 food.pysnake.py를 이미 만들었다. 

 

이제 scoreboard.py를 만들어보자. 

 

우리는 점수 추가 관련, 점수 초기화 관련,  최고 점수 업데이트 관련 부분으로 나누어서 작성할 것이다. 

 

역시 먼저 turtle.Turtleimport 한다. 

 

scoreboard.py

scoreboard를 위치시킬 기본 설정으로 ALIGNMENTcenter로, FONT("arial", 24, "normal")로 설정한다. 

 

그리고 Scoreboard class를 설정하고 이 역시 Turtle를 상속받아 작성한다. ( super().__init__() )

 

우리는 점수를 data.txt에 기록할 것이라고 앞선 게시물에서 언급했었다. 

 

이를 위해 with 문을 통해 data.txt를 열고, 이를 data라고 부르기로 하자. 

 

data.txt 파일에서 우리는 변수 high_scoredata.read() 해올 것이다. 

 

초기 점수 score0, 색은 white, 마찬가지로 지정 위치로 보낼 땐 penup(),

 

그리고 class가 선언될 떄 update_scoreboard() 함수가 호출되도록 설정한다. 

 

이제 update_scoreboard() 함술를 선언해보자. 

 

update_scoreboard() 함수는 게임이 종료되면, 즉 뱀이 죽으면 자동적으로 초기화 해줘야한다. 

 

따라서 이 함수를 선언할 떄 clear()를 같이 포함시켜준다. 그리고 현재 점수와 최고 점수를 f string을 사용하여 나타낸다. 

 

이제 최고 기록인 high_score 에 대한 설정을 해야한다.

 

위에선 단순히 data.txt에 기록된 점수를 불러오는 과정만 작성했다. 

 

그렇다면 data.txt에 최고 기록생신 시 업데이트를 해줘야할게 아닌가?

 

이런 내용을 담은 함수 reset() 를 선언하자. 

 

만약 현 점수가 최고 점수라면, 현 점수를 high_score로 선언하고, data.txt를 쓰기(w)로 open 하여 high_score를 쓴다. 

 

그리고 다시 score0으로 지정하고 다시 update_scrore() 함수를 선언한다. 

( 이렇게 되면 현재 점수 score 가 high_score 일 경우 high_score로 data.txt에 기록되고

다시 score는 0인 상태로 update_scoreboard 함수를 실행하여 화면 맨위에 나오게 되는 것 )

 

그리고 먹이를 먹고 점수를 증가시키는 함수 increase_score() 를 만들자. 

 

해당함수가 호출되면 score 를 1씩 증가하고 초기화한 후 update_scoreboard() 함수를 호출한다. 

( 이렇게 되면 점수 오를 때마다 update_scoreboard()에서 화면의 현재 점수에 1씩 변화되는 과정이 반영되는 것 ) 

 


자 이제 게임 진행 과정을 다룰 main.py 차례이다. 

 

main.py (1)

 

앞서 만들었던 food.pyFood, snake.pySnake, scoreboard.pyScoreboard class를 각각 import 한다. 

( turtle.Screen() 도 같이 import 한다. )

 

역시 screen turtle.Screen()를 지정하고 600 x 600 사이즈의 screen을 만든다. 

 

screen의 배경색은 black, titleSnake Game으로 설정한다. 

 

이 때 screen 출력 속도를 지정하기 위해 turtle.tracer() 를 사용할 것이다. 

 

tracer() 함수에 인자를 1을 주면 코드를 한 줄, 한 줄 입력할 떄마다 화면에 출력된다. 

 

그러나 tracer() 함수에 0을 넣으면 코드를 입력할떄마다 출력시키는 것이 아니라 특정 시점까지 출력하지 않고 특정 시점에 출력을 하도록 한다. 

 

여기서 말하는 특정 시점은 screen.update() 함수를 호출하는 시점이다. 

 

snake 변수에 Snake(), food Food(), scordboardScoreboard() class를 각각 지정한다. 

 

snake 를 움직일 때 우리는 방향키를 사용할 것이고 이를 대비해 snake.py에 각 방향별 메소드를 선언했었다.

 

따라서 screen.listen()을 통해 screen.onkey() 를 사용할 준비를 하고, onkey()를 통해 각 메소드와 해당 키를 입력한다. 

 

main.py (2)

 

game_is_onTrue인 상태에선 게임이 진행되도록 while 을 사용한다. 

 

위에서 screen.tracer(0) 했던 것을 게임 시작하는 동시에 screen.update() 해 화면에 출력되도록 한다. 

 

내용이 출력되는 속도를 조절하여 제대로 출력이 되는지 확인하고 속도를 조절하기 위해 time.sleep(0.1)를 사용한다. 

( import time 필요하다. )

 

이렇게 되면 0.1초를 기다리고 snakemove 함수가 작동된다. 

 

이제 뱀이 먹이를 먹는 과정을 작성해보자. 

 

이 과정은 뱀의 headfood와의 거리가 15미만일 경우로 설명할 것이다. 

( snake.head.distance(food) == (뱀 머리) 와 (food) 의 거리 )

 

따라서 사이의 거리가 15미만이라면 food.refresh(), snake.extend(), 그리고 scoreboard.increase_score()를 호출한다. 

 

그렇다면 벽에 머리가 충돌하여 죽는 경우는 어떻게 구현할까?

 

그것은 headxcor, ycor를 사용하면 된다. 

 

x 위치가 280초과이거나, -280미만이거나, y 위치가 280초과이거나, -280미만인 경우에는 게임을 초기화시켜야한다. 

 

따라서 scoreboard.reset() 하여 score를 0으로 돌리고, snake.reset() 하여 뱀을 원래 위치와 원래 사이즈로 되돌린다.

 

마지막으로 뱀의 머리가 자신의 몸통에 부딪힐 경우도 게임을 초기화시켜야하기 때문에

 

뱀을 이루는 조각들 즉, snake.segments의 segment가 head 인 경우엔 pass,

 

아닐 경우 headsegment의 거리가 18미만이면 scoreboard.reset() 하여 score를 0으로 돌리고, snake.reset() 하여 뱀을 원래 위치와 원래 사이즈로 되돌린다.

 

이렇게 되면 모든 코드를 다 작성한 것이다. 

 

게임 실행 화면