Python Forum
Snake Game - obstacle problem
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Snake Game - obstacle problem
#1
Hi everyone,
I'm a relatively new in python programming and I tried to make a Snake game using a turtle graphics, partly following a tutorial on the internet. Everything worked fine, but then I decided I wanted to add obstacles/bushes. The problem is, that both the food and the bush spawn randomly, which is good, but I don't know how to exclude the coordinates of the bush from the possible coordinates of the food. In different words, I don't want the food to ever spawn inside the bush or touch it. But I can't figure out how to do it.

food = turtle.Turtle()
food.color("violetred4")
food.shape("circle")
food.speed(0)  
food.penup()
x = random.randint(-280, 280)
y = random.randint(-280, 280)
food.goto(x, y)  

bush = turtle.Turtle()
bush.color("olivedrab4")
bush.shape("square")
bush.speed(0)
bush.penup()
bush.shapesize(10, 10)
x = random.randint(-280, 280)
y = random.randint(-280, 280)
bush.goto(x, y)
I tried to put into the code something like this, but it didn't work. I assume that's because it will refresh the window and change the coordinates after the snake eats the food and not before.

    if food.distance(bush) < 50:
        x = random.randint(-280, 280)
        y = random.randint(-280, 280)
        food.goto(x, y)
Can someone help me with this? Here is the whole code:

import turtle
import time
import random

delay = 0.1  # makes the snake go slower

score = 0
high_score = 0

game = turtle.Screen()  # creates a game board
game.bgcolor("darkslategray1")
game.title("Snake Game")
game.setup(width=600, height=600)
game.tracer(0)  # turns off the screen updates

# creates the snake's head
head = turtle.Turtle()
head.color("black")
head.shape("square")
head.speed(0)
head.penup()  # won't draw lines where the snake goes
head.goto(0, 0)  # makes the head begin at the center of the board
head.direction = "stop"  # the head won't move until we press a key

# creates a food for the snake
food = turtle.Turtle()
food.color("violetred4")
food.shape("circle")
food.speed(0)  # the food is not moving
food.penup()
x = random.randint(-280, 280)
y = random.randint(-280, 280)
food.goto(x, y)  # the food will start at random position

# creates an obstacles
bush = turtle.Turtle()
bush.color("olivedrab4")
bush.shape("square")
bush.speed(0)
bush.penup()
bush.shapesize(10, 10)
x = random.randint(-280, 280)
y = random.randint(-280, 280)
bush.goto(x, y)

segments = []  # we create segments so every time the snake eats a food, it will grow

# score counter - pen allows us to draw on the board
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("black")  # the color of the text
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("SCORE: 0  HIGH SCORE: 0", align="center", font=("Georgia", 20, "bold",))


# this function allows our snake to move in desired direction
def move():
    if head.direction == "up":
        y = head.ycor()
        head.sety(y + 20)

    if head.direction == "down":
        y = head.ycor()
        head.sety(y - 20)

    if head.direction == "left":
        x = head.xcor()
        head.setx(x - 20)

    if head.direction == "right":
        x = head.xcor()
        head.setx(x + 20)


# these functions won't allow the snake to move from up to down, from left to right etc. without turning first
def go_up():
    if head.direction != "down":
        head.direction = "up"


def go_down():
    if head.direction != "up":
        head.direction = "down"


def go_left():
    if head.direction != "right":
        head.direction = "left"


def go_right():
    if head.direction != "left":
        head.direction = "right"


# let's bind keyboards to the 'move' function
game.listen()
game.onkeypress(go_up, "w")
game.onkeypress(go_down, "s")
game.onkeypress(go_left, "a")
game.onkeypress(go_right, "d")

# we create an always true loop, so the game keeps going
while True:
    game.update()

    if food.distance(bush) < 50:
        x = random.randint(-280, 280)
        y = random.randint(-280, 280)
        food.goto(x, y)

    # we check if the snake will touch the border on both x and y coordinates - if yes, game over
    if head.xcor() > 290 or head.xcor() < -290 or head.ycor() > 290 or head.ycor() < -290:
        time.sleep(1.5)
        head.goto(0, 0)  # the head will go to the center and the game starts again
        head.direction = "stop"

        for segment in segments:  # it will hide the segments of the snake, meaning he died
            segment.goto(1000, 1000)

        segments.clear()  # will remove the segments

        score = 0  # will reset the score

        delay = 0.1

        pen.clear()  # will clear the score counter
        pen.write("SCORE: {}  HIGH SCORE: {}".format(score, high_score), align="center", font=("Georgia", 20, "bold"))

    if head.distance(food) < 25:  # checking if snake 'ate' the food
        x = random.randint(-280, 280)  # the food will move to random place
        y = random.randint(-280, 280)
        food.goto(x, y)  # when snakes eat food, both food and bushes will change position

        # Add a segment
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.color("cyan4")
        new_segment.shape("square")
        new_segment.penup()
        segments.append(new_segment)  # will add a new segment

        delay -= 0.002  # it will shorten the delay every time the snake gets new segment, making game faster

        # will increase the score
        score += 10

        if score > high_score:
            high_score = score  # sets a new high score

        pen.clear()
        pen.write("SCORE: {}  HIGH SCORE: {}".format(score, high_score), align="center", font=("Georgia", 20, "bold"))

    for index in range(len(segments) - 1, 0, -1):  # reverse the order of segments
        x = segments[index - 1].xcor()
        y = segments[index - 1].ycor()
        segments[index].goto(x, y)

    if len(segments) > 0:  # move first segment to the place of head
        x = head.xcor()
        y = head.ycor()
        segments[0].goto(x, y)

    move()

    # will check if the snake collided with his own body
    for segment in segments:
        if segment.distance(head) < 20:
            time.sleep(1)
            head.goto(0, 0)
            head.direction = "stop"

            # hide the segments after death so they don't stay here
            for segment in segments:
                segment.goto(1000, 1000)

            # clears the segments list so the snakes starts with just his head
            segments.clear()

            # resets the score to zero
            score = 0

            # resets the delay to the original one
            delay = 0.1

            pen.clear()  # clears the score
            pen.write("SCORE: {}  HIGH SCORE: {}".format(score, high_score), align="center",
                      font=("Georgia", 20, "bold"))

    time.sleep(delay)

game.mainloop()  
Reply
#2
I found something that appears to work okay from what I could tell. I'm sure there's a more efficient way to do it, but the code is as follows. You may want to include more logic to make sure the bush doesn't spawn on the center (snake) as well.

# creates an obstacles
bush = turtle.Turtle()
bush.color("olivedrab4")
bush.shape("square")
bush.speed(0)
bush.penup()
bush.shapesize(10, 10)
t = random.randint(-280, 280)
u = random.randint(-280, 280)
if t - 250 < x or t + 250 > x:
    if t > 0:
        t -= 250
    else:
        t += 250
if u - 250 < y or u + 250 > y:
    if u > 0:
        u -= 250
    else:
        u += 250
Reply
#3
Just wanted to give you a heads up: my solution above didn't work out once tested enough times. Not sure if it's on the right track or not, but just didn't want to cause any additional headaches by my previous statement which said that it worked. Silenced
Reply
#4
Thanks for trying to help me out :) eventually I figured it out. So for anyone with the same problem, this is what I did:

while True:
    game.update()

    if food.distance(bomb1) < 40 or food.distance(bomb2) < 40 or food.distance(bomb3) < 40 \
            or food.distance(bomb4) < 40 or food.distance(bomb5) < 40:
        food.goto(random.randint(-250, 250), random.randint(-250, 250))
        game.update() 
I tested it and it works - if the apple spawns too close to the bomb, it will immediately spawn again somewhere else.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to add segments to the snake body blacklight 1 2,877 Sep-13-2023, 07:33 AM
Last Post: angelabarrios
  [PyGame] Snake game: how to get an instance for my snake's body multiple times? hajebazil 2 2,139 Jan-30-2022, 04:58 AM
Last Post: hajebazil
  help with snake game blacklight 3 2,597 Jul-30-2020, 01:13 AM
Last Post: nilamo
  [PyGame] Problem With Entering Game Loop ElevenDecember 3 2,663 Jan-19-2020, 08:25 AM
Last Post: michael1789
  [PyGame] Problem when moving game window michael1789 15 8,779 Jan-17-2020, 01:40 PM
Last Post: metulburr
  [PyGame] Made my first Python program: Snake. Please help me improve it andrerocha1998 7 6,140 Feb-19-2019, 07:08 PM
Last Post: Windspar
  Creating Snake game in Turtle Shadower 1 8,645 Feb-11-2019, 07:00 PM
Last Post: woooee
  [PyGame] Game Logic problem with a "The Game of Life" Replication Coda 2 3,134 Dec-24-2018, 09:26 AM
Last Post: Coda
  [PyGame] Pong game key.event problem erickDarko 2 4,172 Dec-12-2018, 03:17 PM
Last Post: erickDarko
  [PyGame] Basic Snake game (using OOP) PyAlex 1 12,532 Sep-10-2018, 09:02 PM
Last Post: Mekire

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020