업무에 파이썬 활용할 줄 알기

Day20 | 중급 | 뱀 게임 만들기 1편: 애니메이션 & 좌표 본문

Python/[Udemy] 100개의 프로젝트로 Python 개발 완전 정복

Day20 | 중급 | 뱀 게임 만들기 1편: 애니메이션 & 좌표

SEO 데이터분석가 2024. 1. 4. 15:13

20일차 목표: 오늘 하루 작업할 것

Building the famous Snake Game.

 

7개 단계로 쪼개어 1편에서 3개, 2편에서 4개를 해결할 예정

1. Create a snake body

2. Move the snake

3. Control the snake

4. Detect collision with food

5. Create a scoreboard 

6. Detect collision

7. Detect collision with tail

 

 

화면을 구성하고, 뱀 몸체 만들기

My solution

from turtle import Screen, Turtle

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My snake Game")

# TODO: Create 3 turtles and position them like so (default size: 20*20)
## Each turtle should be a white square


first_position = [0, -20, -40]
for i in range(3):
    snake = Turtle(shape="square")
    snake.color("white")
    snake.penup()
    snake.goto(x=first_position[i], y=0)

 

Angela's solution

나는 for문에 여전히 리스트를 활용하고 있지 못함

이번에는 위치를 tuple로 나타냄

from turtle import Screen, Turtle

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My snake Game")

# TODO: Create 3 turtles and position them like so (default size: 20*20)
## Each turtle should be a white square


starting_positions = [(0,0), (-20,0), (-40,0)]
for position in starting_positions:
    new_segment = Turtle(shape="square")
    new_segment.color("white")
    new_segment.goto(position)

화면 상에서 뱀 움직이기

첫번째 문제상황: 뱀이 움직일 때 깜박거림

해결과정:

  • racer()와 update() 이용하기
  • update()를 어디에 위치해줘야할지 모를 때, time.sleep()으로 테스트 해보기
  • 세개의 터틀이 다 움직이고 나서야 화면이 업데이트 되도록 screen.update() 위치 조정하기

 

두번째 문제상황: 방향을 턴할 때, 세개의 터틀이 연결되지 않고 끊어짐

  • 해결책: 세번째를 두번째의 위치로, 두번째를 첫번째의 위치로, 그리고 첫번째 위치조정
    즉, 꼬리가 머리를 따라갈 수 있도록
  • 이걸 코드로 어떻게 구현할 것인가:
    기존의 for문을 지우고, 3번째 터틀에서 1번째 터틀로 가는 역순서의 for문 만들기

screen.tracer(), screen.update()

 

3개 터틀 앞으로 움직이기/깜박거림 문제해결 구현 단계

screen.tracer(), time.sleep()으로 해결

from turtle import Screen, Turtle
import time

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My snake Game")
screen.tracer(0)

# TODO: Create 3 turtles and position them like so (default size: 20*20)
## Each turtle should be a white square

starting_positions = [(0,0), (-20,0), (-40,0)]

segments = []

for position in starting_positions:
    new_segment = Turtle(shape="square")
    new_segment.color("white")
    new_segment.penup()
    new_segment.goto(position)
    segments.append(new_segment)

game_is_on = True
while game_is_on:
    screen.update()
    time.sleep(0.1)

    for seg in segments:
        seg.forward(20)

 

터틀 끊어지는 현상 해결

문제점: 머리부터 순서대로 움직이면 끊어지는 현상 생김

해결책: 뱀꼬리(마지막 segment)부터 반대 순서로 움직여주기 → 끊어지는 현상 해결

from turtle import Screen, Turtle
import time

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My snake Game")
screen.tracer(0)

# TODO: Create 3 turtles and position them like so (default size: 20*20)
## Each turtle should be a white square

starting_positions = [(0,0), (-20,0), (-40,0)]

segments = []

for position in starting_positions:
    new_segment = Turtle(shape="square")
    new_segment.color("white")
    new_segment.penup()
    new_segment.goto(position)
    segments.append(new_segment)

game_is_on = True
while game_is_on:
    screen.update()
    time.sleep(0.1)

    for seg_num in range(len(segments) - 1, 0, -1):
        new_x = segments[seg_num - 1].xcor()
        new_y = segments[seg_num - 1].ycor()
        segments[seg_num].goto(new_x, new_y)
    segments[0].forward(20)

 

뱀 클래스를 만들고, 객체지향 프로그래밍 하기

My solution (오류발생) in snake.py

STARTING_POSITIONS = [(0,0), (-20,0), (-40,0)]
SEGMENTS = []

from turtle import Turtle

class Snake:
    def __init__(self):
        self.three_turtles =
        for position in STARTING_POSITIONS:
            new_segment = Turtle(shape="square")
            new_segment.color("white")
            new_segment.penup()
            new_segment.goto(position)
            SEGMENTS.append(new_segment)

    def move(self):
        for seg_num in range(len(SEGMENTS) - 1, 0, -1):
            new_x = SEGMENTS[seg_num - 1].xcor()
            new_y = SEGMENTS[seg_num - 1].ycor()
            SEGMENTS[seg_num].goto(new_x, new_y)
        SEGMENTS[0].forward(20)

 

Angela's solution in snake.py

from turtle import Turtle
STARTING_POSITIONS = [(0,0), (-20,0), (-40,0)]
MOVE_DISTANCE = 20

class Snake:
    def __init__(self):
        self.segments = []
        self.create_snake()
    def create_snake(self):
        for position in STARTING_POSITIONS:
            new_segment = Turtle(shape="square")
            new_segment.color("white")
            new_segment.penup()
            new_segment.goto(position)
            self.segments.append(new_segment)
    def move(self):
        for seg_num in range(len(self.segments) - 1, 0, -1):
            new_x = self.segments[seg_num - 1].xcor()
            new_y = self.segments[seg_num - 1].ycor()
            self.segments[seg_num].goto(new_x, new_y)
        self.segments[0].forward(MOVE_DISTANCE)

 

키 입력으로 뱀의 방향 바꾸기

My solution (오답)

아 머리만 방향을 잡으면 되는거였구나..!

Angela's solution

처음엔 단순 'segments[0]'으로 해줬다가 자주쓰는 코드다 보니 

객체 초기화에 self.head = self.segments[0]로 속성을 따로 만들어줬다

from turtle import Turtle
STARTING_POSITIONS = [(0,0), (-20,0), (-40,0)]
MOVE_DISTANCE = 20
class Snake:
    def __init__(self):
        self.segments = []
        self.create_snake()
        self.head = self.segments[0]
    def create_snake(self):
        for position in STARTING_POSITIONS:
            new_segment = Turtle(shape="square")
            new_segment.color("white")
            new_segment.penup()
            new_segment.goto(position)
            self.segments.append(new_segment)

    def move(self):
        for seg_num in range(len(self.segments) - 1, 0, -1):
            new_x = self.segments[seg_num - 1].xcor()
            new_y = self.segments[seg_num - 1].ycor()
            self.segments[seg_num].goto(new_x, new_y)
        self.head.forward(MOVE_DISTANCE)

    def up(self):
        self.head.setheading(90)

    def down(self):
        self.head.setheading(270)

    def left(self):
        self.head.setheading(180)

    def right(self):
        self.head.setheading(0)

 

※ 추가로 더 조치해주어야 하는 것

반대방향으로 가지못하게 해야함

Angela's solution in snake.py

 

Angela's solution in main.py

from turtle import Screen, Turtle
from snake import Snake
import time


screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My snake Game")
screen.tracer(0)

snake = Snake()

screen.listen()
screen.onkey(snake.up, "Up")
screen.onkey(snake.down, "Down")
screen.onkey(snake.left, "Left")
screen.onkey(snake.right, "Right")

game_is_on = True
while game_is_on:
    screen.update()
    time.sleep(0.1)

    snake.move()