Make the snake in game move piece by piece instead of as a whole

Make the snake in game move piece by piece instead of as a whole



My game is a snake game where you have to get the fruit. This is the code:


#Importing random and turtle module
import random
import turtle as t #Shortening the turtle module to t

#Adding a orange background
t.bgcolor("orange")

#Creating a turtle to become the snake
snake = t.Turtle() # Creates a new turtle for the snake
snake.shape("square") # Making the snake square shaped
snake.color("green") # Making the snake green
snake.speed(0) # Making the snake not move before the game starts
snake.penup() # Disables the turtles pen allowing the turtle to move around the screen without drawing a line along the way
snake.hideturtle() #This command hides the turtle

#Creating a turtle to draw the leaves
fruit = t.Turtle() # Creates a new turtle for the fruit
fruit.shape("circle") # Making the fruit circular
fruit.color("red") # Making the fruit red
fruit.penup() # Disables the turtles pen allowing the turtle to move around the screen without drawing a line along the way
fruit.hideturtle() #This command hides the turtle
fruit.speed(0) # Making the fruit not move

#Adding more turtles to display the text for the game and the score
gamestarted = False #To know if the game has started
writeturtle = t.Turtle()# Creates a new turtle for the text
writeturtle.write("Press SPACE to play!", align="center", font=("Calibri", 16, "bold")) #This line draws text on the screen
writeturtle.hideturtle() # Hides the turtle but not the text
#Adding a score turtle
scoreturtledude = t.Turtle()# Creates a new turtle for the score
scoreturtledude.hideturtle()#This command hides the turtle
scoreturtledude.speed(0)#Make sure the turtle stays where it is so it can update the score

def outsidewindow(): #Defining the outside window function
leftwall = -t.window_width() / 2 #Calculates the left wall
rightwall = t.window_width() / 2 #Calculates the right wall
topwall = t.window_height() / 2 #Calculates the top wall
bottomwall = -t.window_height() / 2 #Calculates the bottom wall
(x, y) = snake.pos() #Then it asks the snake for its current position
outside = x< leftwall or x> rightwall or y< bottomwall or y> topwall #Comparing the snakes coordinates with the wall position
return outside #If any of the four conditions above is true then outside is true
def gameover(): #Defining gameover
snake.color("orange")#CHANGES THE COLOR OF THE SNAKE TO ORANGE(the same color as the background) so it can't be seen
fruit.color("orange")#CHANGES THE COLOR OF THE SNAKE TO ORANGE(the same color as the background) so it can't be seen
t.penup() # this disables the turtles pen
t.hideturtle() #This hides the turtle
t.write("YOUR SNAKE CRAWLED INTO THE GARDEN. GAME OVER!", align="center", font=("Calibri", 20, "normal"))#This line writes a text for when the game is over
def showscore(currentscore):
scoreturtledude.clear()# This clears the score
scoreturtledude.penup()# Disables turtle pen
x = (t.window_width() / 2) -75 # 75 pixels from the right
y = (t.window_height() / 2) -75 # And 75 pixels from the top
scoreturtledude.setpos(x, y)#Sets the turtles position
scoreturtledude.write(str(currentscore) , align="right", font=("Calibri", 40, "bold"))# WRITES THE SCOre in calibri font
def placefruit():
fruit.hideturtle()
fruit.setposition(random.randint(-200, 200), random.randint(-200, 200))
fruit.showturtle()
def startgame():
global gamestarted
if gamestarted: #If the game has already started, the return command makes the function quit so it doesn't run a second time
return
gamestarted = True

score = 0 #Sets the score to 0
writeturtle.clear() # Clears the text from the screen

snakespeed = 2
snakelength = 3
snake.shapesize(1, snakelength, 1)#This makes the snake turtle stretch from a square shape into a snake shape
snake.showturtle() #This shows the snake
showscore(score) #This uses the showscore function we defined earlier
placefruit()
while True: #This puts it in a forever loop
snake.forward(snakespeed)
if snake.distance(fruit) < 20:# Makes the snake eat the leaf when it is less than 20 pixels away
placefruit() #This line places another fruit on the screen
snakelength = snakelength + 1 #This line line and the next line together will make the snake grow longer
snake.shapesize(1, snakelength, 1)
snakespeed = snakespeed + 1 #This increases the speed of the snake
score = score + 100 #This increases the score
showscore(score) #This shows the score
if outsidewindow():
gameover()
break
def up():
if snake.heading() == 0 or snake.heading() == 180: #checks if the snake is heading left or right
snake.setheading(90)#Heads the snake straight up
def down():
if snake.heading() == 0 or snake.heading() == 180:#checks if the snake is heading left or right
snake.setheading(270)#Heads the snake straight down
def left():
if snake.heading() == 90 or snake.heading() == 270:#checks if the snake is heading up or down
snake.setheading(180)#Heads the snake straight right
def right():
if snake.heading() == 90 or snake.heading() == 270:#checks if the snake is heading up or down
snake.setheading(0)#Heads the snake straight left


t.onkey(startgame, "space") # The onkey() function binds yhe space bar to the startgame () so the game will not start until the player presses space
t.onkey(up, "Up") #The onkey() function binds the up key to the startgame
t.onkey(down, "Down")#The onkey() function binds the down key to the startgame
t.onkey(right, "Right")#The onkey() function binds the right key to the startgame
t.onkey(left, "Left")#The onkey() function binds the left key to the startgame
t.listen() # The listen function allows the program to recieve signals from the key board
t.mainloop()



This code makes a game where the snake turns altogether, but I want the snake to turn piece by piece. Could you help me?




1 Answer
1



Below I've merged your game with this short example of how to move a segmented snake around the screen that I wrote earlier -- I'm surprised your search of SO didn't turn this up.



I've also made some other changes to accomodate this motion. Your snake changes from a turtle to a list of turtles, with the final turtle in the list being the head of the snake. The keyboard arrow handlers no longer change the snake's direction directly, they merely set a new direction variable for when the next turtle movement occurs -- this prevents conflicts in adjusting the turtle.



Your while True: has no place in an event-driven world like turtle so it's been replaced with an ontimer() event -- otherwise you potentially lock out events:


while True:


ontimer()


from random import randint
from turtle import Turtle, Screen # force object-oriented turtle

SCORE_FONT = ("Calibri", 40, "bold")
MESSAGE_FONT = ("Calibri", 24, "bold")

SEGMENT_SIZE = 20

def outsidewindow():
(x, y) = snake[-1].pos() # Ask the snake head for its current position
return not (leftwall < x < rightwall and bottomwall < y < topwall)

def gameover():
for segment in snake:
segment.hideturtle()
fruit.hideturtle()
writeturtle.write("Your snake crawled into the garden! Game over!", align="center", font=MESSAGE_FONT)

def showscore(currentscore):
scoreturtledude.undo() # Clear the previous score
scoreturtledude.write(currentscore, align="right", font=SCORE_FONT)

def placefruit():
fruit.hideturtle()
fruit.setposition(randint(-200, 200), randint(-200, 200))
fruit.showturtle()

def startgame():
screen.onkey(None, "space") # So this doesn't run a second time

writeturtle.clear() # Clear the text from the screen

showscore(score)

for segment in snake: # Show the snake
segment.showturtle()

placefruit()

rungame()

def rungame():
global score, snakelength

segment = snake[-1].clone() if len(snake) < snakelength else snake.pop(0)

screen.tracer(False) # segment.hideturtle()
segment.setposition(snake[-1].position())
segment.setheading(snake[-1].heading())
segment.setheading(direction)
segment.forward(SEGMENT_SIZE)

if outsidewindow():
gameover()
return

screen.tracer(True) # segment.showturtle()
snake.append(segment)

if snake[-1].distance(fruit) < SEGMENT_SIZE: # Make the snake eat the fruit when it is nearby
placefruit() # Place another fruit on the screen
snakelength += 1
score += 100
showscore(score)

screen.ontimer(rungame, max(50, 150 - 10 * len(snake))) # Speed up slightly as snake grows

def up():
global direction

current = snake[-1].heading()

if current == 0 or current == 180: # Check if the snake is heading left or right
direction = 90 # Head the snake up

def down():
global direction

current = snake[-1].heading()

if current == 0 or current == 180: # Check if the snake is heading left or right
direction = 270 # Head the snake down

def left():
global direction

current = snake[-1].heading()

if current == 90 or current == 270: # Check if the snake is heading up or down
direction = 180 # Head the snake left

def right():
global direction

current = snake[-1].heading()

if current == 90 or current == 270: # Check if the snake is heading up or down
direction = 0 # Head the snake right

screen = Screen()
screen.bgcolor("orange")

leftwall = -screen.window_width() / 2 # Calculate the left wall
rightwall = screen.window_width() / 2 # Calculate the right wall
topwall = screen.window_height() / 2 # Calculate the top wall
bottomwall = -screen.window_height() / 2 # Calculate the bottom wall

# Creating a turtle to become the snake
head = Turtle("square", visible=False) # Create a new turtle for the snake
head.color("green") # Make the snake green
head.penup() # Disable the turtle's pen, allowing the turtle to move around the screen without leaving a trail

snake = [head]
snakelength = 3
score = 0
direction = 0

# Creating a turtle to draw the leaves
fruit = Turtle("circle", visible=False) # Create a turtle for the fruit
fruit.penup() # Raise the turtle's pen, allowing turtle to move around screen without leaving a trail
fruit.color("red")

# Add more turtles to display the text for the game and the score
writeturtle = Turtle(visible=False) # Create a new turtle for the text
writeturtle.write("Press SPACE to play!", align="center", font=MESSAGE_FONT)

# Add a score turtle
scoreturtledude = Turtle(visible=False) # Create a new turtle for the score
scoreturtledude.penup() # Disable turtle pen
x = screen.window_width() / 2 - 75 # 75 pixels from the right
y = screen.window_height() / 2 - 75 # And 75 pixels from the top
scoreturtledude.setpos(x, y) # Set the turtle's position
scoreturtledude.write('', align="right", font=SCORE_FONT)

screen.onkey(startgame, "space") # Bind space bar to startgame() so game will start when player presses space
screen.onkey(up, "Up") # Bind the up key to up()
screen.onkey(down, "Down") # Bind the down key to down()
screen.onkey(right, "Right") # Bind the right key to right()
screen.onkey(left, "Left") # Bind the left key to left()
screen.listen() # Allow the window to receive signals from the keyboard

screen.mainloop()



enter image description here



You've a number of issues in your code, e.g. little ones like what turtle is gameover() referring to when it does t.hideturtle()? But two major ones are:


gameover()


t.hideturtle()



Reread what speed(0) does -- you've misunderstood it.


speed(0)



You need to learn to write better comments. This is silly:



fruit.color("red") # Making the fruit red



This is pretty good:



t.listen() # The listen function allows the program to recieve signals from the key board





Snake Crawled into the ....... This text is too big.
– Black Thunder
Sep 4 at 4:25



Snake Crawled into the .......





@BlackThunder, it's not related to the OP's problem being addressed, and works fine on my screen, but I shrank it for your playing pleasure. Thanks.
– cdlane
Sep 4 at 4:28




Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)