Inheritance, slicing and finishing the snake game
Class Inheritance(클래스 상속)
- 클래스 이름 옆에 괄호를 치고, 상속받고자 하는 클래스를 적음
- init 메소드 안에 super().init()을 추가
- super는 상위 클래스를 나타냄
class Fish(Animal):
def __init__(self):
super().__init__()
만약 상속받은 메소드에 다른 기능도 넣고 싶다면
Detact collision with food(뱀이 먹이를 먹었는지 알아내기)
1️⃣ Food 클래스 생성후 Turtle클래스 상속받기
2️⃣ 먹이 객체를 초기화할 때 상태를 정하고, 선을 그리지 않도록 수정
3️⃣ 속도 조절해서 이동하는 과정이 애니메이션으로 보이지 않게
4️⃣ 임의의 (x, y)좌표로 이동
5️⃣ main.py에 Food객체 초기화
6️⃣ if문으로 Turtle클래스의 distance메소드를 사용해서 먹이를 먹었는지 알아내기
- 두 터틀 사이의 거리 알아내기
- 먹이 크기 10x10, 머리크기 20x20 ⇨ 뱀 머리와 먹이의 거리가 15픽셀 이내면 먹이를 먹은 것임
7️⃣ 뱀이 먹이와 충돌 후 먹이를 임의의 위치로 이동시키기
- food.py에 refresh메소드 생성
- main.py에 먹이 위치 갱신 넣어주기
Create a scoreboard(점수판을 만들어 점수 기록하기)
1️⃣ Turtle클래스 상속받은 Scoreboard 클래스 생성
2️⃣ Scoreboard객체 생성
3️⃣ 뱀이 먹이를 먹었을 때 점수 증가
- scoreboard.py에 increase_score 메소드 생성 후 main.py의 if문에 추가
Detect collision with wall(뱀이 벽에 부딪혔는지 알아내기)
1️⃣ scoreboard.py에 GAME OVER텍스트 메소드 생성
2️⃣ main.py에 if조건문
Detect collision with tail(뱀이 자기 꼬리와 부딪혔는지 알아내기)
1️⃣ 먹이를 먹었을 때 길이가 늘어나도록 작성 후 main.py에 삽입
2️⃣ 뱀을 이루는 세그먼트 리스트를 반복문으로 돌려 충돌감지
Slicing
리스트, 터플 안의 값을 필요한 범위만 쓸 수 있음
문법
0부터 4까지 (마지막은 포함하지 않음)
piano_keys[2 : 5]
2 이후로 모두
piano_keys[2 : ]
5이전으로 모두
piano_keys[ : 5]
하나씩 거르고 가져오고 싶을 때
piano_keys[: : 2]
역순으로 가져오고 싶을 때
piano_keys[ : : -1]
Final code for main.py
from turtle import Screen
from snake import Snake
from food import Food
from scoreboard import Scoreboard
import time
screen = Screen()
screen.setup(600, 600)
screen.bgcolor("black")
screen.title("My Snake Game")
screen.tracer(0)
snake = Snake()
food = Food()
scoreboard = Scoreboard()
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()
if snake.head.distance(food) < 15:
food.refresh()
snake.extend()
scoreboard.increase_score()
if snake.head.xcor() > 280 or snake.head.xcor() < -280 or snake.head.ycor() > 280 or snake.head.ycor() < -280:
game_is_on = False
scoreboard.game_over()
for segment in snake.segments[1:]:
if snake.head.distance(segment) < 10:
game_is_on = False
scoreboard.game_over()
screen.exitonclick()
Final code for scoreboard.py
from turtle import Turtle
ALIGNMENT = "center"
FONT = ("Courier", 24, "normal")
class Scoreboard(Turtle):
def __init__(self):
super().__init__()
self.score = 0
self.color("white")
self.penup()
self.goto(0, 270)
self.update_scoreboard()
self.hideturtle()
def update_scoreboard(self):
self.write(f"Score: {self.score}", align=ALIGNMENT, font=FONT)
def game_over(self):
self.goto(0, 0)
self.write("GAME OVER", align=ALIGNMENT, font=FONT)
def increase_score(self):
self.score += 1
self.clear()
self.update_scoreboard()
Final code for food.py
from turtle import Turtle
import random
class Food(Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.penup()
self.shapesize(stretch_len=0.5, stretch_wid=0.5)
self.color("blue")
self.speed("fastest")
self.refresh()
def refresh(self):
random_x = random.randint(-280, 280)
random_y = random.randint(-280, 280)
self.goto(random_x, random_y)
Final code for snake.py
from turtle import Turtle
STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]
MOVE_DISTANCE = 20
UP = 90
DOWN = 270
LEFT = 180
RIGHT = 0
class Snake:
def __init__(self):
self.segments = []
self.create_snake()
self.head = self.segments[0]
def create_snake(self):
for position in STARTING_POSITIONS:
self.add_segment(position)
def add_segment(self, position):
new_segment = Turtle("square")
new_segment.color("white")
new_segment.penup()
new_segment.goto(position)
self.segments.append(new_segment)
def extend(self):
self.add_segment(self.segments[-1].position())
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)
def up(self):
if self.head.heading() != DOWN:
self.head.setheading(UP)
def down(self):
if self.head.heading() != UP:
self.head.setheading(DOWN)
def left(self):
if self.head.heading() != RIGHT:
self.head.setheading(LEFT)
def right(self):
if self.head.heading() != LEFT:
self.head.setheading(RIGHT)