Sunday, January 31, 2021

Python - Project - Snake Game - Part 1 (Day 20)

This is a 100 Days challenge to learn a new language (Python). 100 Days of Code - The Complete Python Pro Bootcamp 

I will post some notes to motivate myself to finish this challenge.


Project - Snake Game



We will build a snake game on day 20 and 21.

Break down the problem:

  1. Create a snake body (day 20)
  2. Move the snake (day 20)
  3. Control the snake (day 20)
  4  Detect collision with food (day 21)
  5. Create a scoreboard (day 21)
  6. Detect collision with wall (day 21)
  7. Detect collision with tail (day 21)


Note



1. In order to make our snake move smoothly, using tracer to turn off the animation.

from turtle import Screen
# Get screen instance
screen = Screen()

# Turn turtle animation off
screen.tracer(0)

# Perform a TurtleScreen update
screen.update()


2. Using time module to slow down the while loop

import time

time.sleep(0.1)


3. Create a Snake Class to wrap the relating functionality


Snake Game (Part 1)



snake.py
from turtle import Turtle

# Constants
STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]
MOVING_DISTANCE = 20
UP = 90
DOWN = 270
LEFT = 180
RIGHT = 0


class Snake:
    """Snake Class"""

    # Constructor
    def __init__(self):
        # Define an attribute to track snake body
        self.segments = []

        # Call func to init snake
        self.create_snake()

        # Create a attribute instead of using magic number 0
        self.head = self.segments[0]

    # Methods - create snake
    def create_snake(self):
        """Adding segment(turtle object) to segments list"""

        for position in STARTING_POSITIONS:
            segment = Turtle()
            segment.shape("square")
            segment.color("white")
            segment.penup()
            segment.setpos(position)

            self.segments.append(segment)

    # Methods - move
    def move(self):
        """move"""

        # Starting from tail, make each segment move to
# the position of the previous segment
        for index in range(len(self.segments) - 1, 0, -1):
            new_x = self.segments[index - 1].xcor()
            new_y = self.segments[index - 1].ycor()
            self.segments[index].setpos(new_x, new_y)

        # Magic number!!
        # self.segments[0].forward(MOVING_DISTANCE)

        # Using attribute instead of magic number
        self.head.forward(MOVING_DISTANCE)

    def move_up(self):
        """move_up"""

        if self.head.heading() != DOWN:
            self.head.setheading(UP)

    def move_right(self):
        """move_right"""

        if self.head.heading() != LEFT:
            self.head.setheading(RIGHT)

    def move_left(self):
        """move_left"""

        if self.head.heading() != RIGHT:
            self.head.setheading(LEFT)

    def move_down(self):
        """move_down"""

        if self.head.heading() != UP:
            self.head.setheading(DOWN)

main.py
import time
from turtle import Screen
from snake import Snake

# Screen Setup
screen = Screen()
screen.setup(width=600, height=600)
screen.title("My Snake Game")
screen.bgcolor("black")
# Turn turtle animation off# Disable screen
screen.tracer(0)

# init a snake
snake = Snake()

# Listen events
# Bind fun to key-release event of key
screen.onkey(snake.move_up, "Up")
screen.onkey(snake.move_down, "Down")
screen.onkey(snake.move_right, "Right")
screen.onkey(snake.move_left, "Left")
# Set focus on TurtleScreen (in order to collect key-events)
screen.listen()

game_is_on = True

while game_is_on:
    # Perform a TurtleScreen update# Update Screen
    screen.update()

    # Give some delay for this while loop
    time.sleep(0.1)

    # Keep moving
    snake.move()


# Bind bye() method to mouse clicks on the Screen.
screen.exitonclick()


Highlight



1. Defining constants can help you to config the game easily

2. Define attributes if possible, and please don't use magic number

No comments:

Post a Comment