Skip to content

Instantly share code, notes, and snippets.

@ggorlen
Created July 1, 2024 17:11
Show Gist options
  • Save ggorlen/c725bdc0d0b7876e41cf055234973042 to your computer and use it in GitHub Desktop.
Save ggorlen/c725bdc0d0b7876e41cf055234973042 to your computer and use it in GitHub Desktop.
Turtle Snake
from random import randint
from turtle import Turtle
class Food:
def __init__(self, move_dist):
self.move_dist = move_dist
self.t = t = Turtle()
t.shape("circle")
t.penup()
t.shapesize(0.6)
t.color("blue")
def change_pos(self, w, h):
self.t.goto(
randint(-w / 2 + self.move_dist, w / 2 - self.move_dist),
randint(-h / 2 + self.move_dist, h / 2 - self.move_dist),
)
def pos(self):
return self.t.pos()
# See https://stackoverflow.com/q/78641345/6243352
from turtle import Screen, Turtle
from food import Food
from scoreboard import Scoreboard
from snake import Snake
def update():
snake.move()
if snake.collides_with_tail() or snake.collides_with_wall(width, height):
screen.update()
return scoreboard.game_over()
if snake.collides_with_food(food):
scoreboard.increase_score()
snake.extend()
food.change_pos(width, height)
screen.update()
screen.ontimer(update, game_speed_ms)
width, height = 600, 600
game_speed_ms = 1000 // 10
move_dist = 20
screen = Screen()
screen.tracer(0)
screen.setup(width, height)
screen.bgcolor("black")
screen.title("Snake Game")
snake = Snake(move_dist)
food = Food(move_dist)
scoreboard = Scoreboard(y=height / 2 - move_dist * 2)
UP = 90
DOWN = 270
RIGHT = 0
LEFT = 180
screen.listen()
screen.onkey(lambda: snake.turn(UP), "Up")
screen.onkey(lambda: snake.turn(LEFT), "Left")
screen.onkey(lambda: snake.turn(RIGHT), "Right")
screen.onkey(lambda: snake.turn(DOWN), "Down")
update()
screen.exitonclick()
from turtle import Turtle
class Scoreboard:
def __init__(self, x=0, y=0):
self.t = t = Turtle()
self.score = -1
t.color("white")
t.penup()
t.goto(x, y)
t.hideturtle()
self.update_scoreboard()
def update_scoreboard(self):
self.t.write(
f"Score: {self.score}", align="center", font=("Arial", 15, "normal")
)
def increase_score(self):
self.score += 1
self.t.clear()
self.update_scoreboard()
def game_over(self):
self.t.goto(0, 0)
self.t.write("Game Over", align="center", font=("Arial", 25, "normal"))
from turtle import Turtle
class Snake:
def __init__(self, move_dist):
self.move_dist = move_dist
self.segments = []
positions = [(0, 0), (-move_dist, 0), (-move_dist * 2, 0)]
self.create_snake(positions)
self.head = self.segments[0]
def create_snake(self, positions):
for snake_body in positions:
self.add_segment()
def add_segment(self):
segment = Turtle("square")
segment.penup()
segment.hideturtle()
segment.color("white")
segment.setpos(x=-self.move_dist, y=0)
self.segments.append(segment)
def extend(self):
self.add_segment()
def move(self):
for seg_num in range(len(self.segments) - 1, 0, -1):
# coord of previous segment
new_x = self.segments[seg_num - 1].xcor()
new_y = self.segments[seg_num - 1].ycor()
# previous segment moves to coord of next segment
self.segments[seg_num].goto(new_x, new_y)
self.segments[seg_num].showturtle()
self.head.forward(self.move_dist)
def turn(self, direction):
if (
direction - 180 != self.head.heading()
and direction + 180 != self.head.heading()
):
self.head.setheading(direction)
def collides_with_food(self, food):
return self.head.distance(food.pos()) < self.move_dist
def collides_with_tail(self):
for segment in self.segments[1:]:
if self.head.distance(segment) < self.move_dist // 2:
return True
return False
def collides_with_wall(self, w, h):
return (
self.head.xcor() > w / 2 + self.move_dist / 2 # right side
or self.head.xcor() < -w / 2 + self.move_dist / 2 # left side
or self.head.ycor() > h / 2 - self.move_dist / 2 # top
or self.head.ycor() < -h / 2 + self.move_dist # bottom
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment