Turtle graphics snake game - python

I just started turtle graphics yesterday. I decided to make a little snake game in turtle graphics. But later on, I got some problems after another. :(
The problem is that, I couldn't level up the game whenever my snake eats the food :( and the movement of my snake is a little bit not the same to the typical snake game... so I'm here to ask for suggestions what to do to solve these problems. so please lend me your ideas :D
well, here's my very long long code..
from turtle import *
import random
title("Snake Game") #title of the game
setup(555,555) #sets the screensize into 555x555 px
bgcolor("orange") #background color
#pressed key functions
def up():
penup()
pendown()
head(90)
def right():
penup()
pendown()
head(0)
def left():
penup()
pendown()
head(180)
def down():
penup()
pendown()
head(270)
#draw dot
def dotx():
pen2.penup()
pen2.goto(x1,y1)
pen2.pendown()
pen2.dot(20,"green")
#heading of the snake
def head(x):
for i in range(9999999):
for ii in range(20):
seth(x)
fd(2)
if xcor()>=250.0 or ycor()>=250.0 or xcor()<=-250.0 or ycor()<=-250.0:
clear()
pen2.clear()
pen4.write("GAME OVER")
break
elif (xcor() in x2) and (ycor() in y2):
pen2.clear()
pen4.write("EATEN",False,'center',font=('Arial',15,'normal'))
if xcor()>=250.0 or ycor()>=250.0 or xcor()<=-250.0 or ycor()<=-250.0:
clear()
pen2.clear()
pen4.write("GAME OVER")
break
clear()
color("white")
pensize(5) #pensize
shape('turtle')
#hideturtle()
delay(2) #delay of animation
speed(10) #speed of animation
pen2=Pen() #dots
pen2.hideturtle()
pen4=Pen()
pen4.hideturtle()
pen4.color("white")
#border
pen3=Pen()
pen3.color("white")
pen3.pensize(3)
pen3.hideturtle()
pen3.speed(10)
pen3.penup()
pen3.goto(-250,-250)
pen3.pendown()
for p3 in range(4):
pen3.fd(500)
pen3.left(90)
#dots coordinates
x1=random.randint(-225,225)
y1=random.randint(-225,225)
x2=list(range(x1-6,x1+6))
y2=list(range(y1-6,y1+6))
dotx() #call dots
#controls
onkey(up,"Up")
onkey(right,"Right")
onkey(left,"Left")
onkey(down,"Down")
listen()

To make the snake grow I find it easy to create a list and use pop and insert functions to have a constant list of all of the snake locations. Then you can use turtles stamp method to stamp all of these list locations so that it displays in all locations. Here's an example of a turtle snake game I made a while ago so you can see how to use these concepts
pos.insert(0,[round((snake.xcor())),round((snake.ycor()))]) #round x turns the float value of position into integer
pos.pop(-1)
for x in range(1, len(pos)):
if pos[x] == pos[0]:
sys.exit()
elif pos[x]!= pos[0]:
pass;
#pop removes last element of list, used to update position
else: #insert inserts an element into list at position
pos.insert(0,[round((snake.xcor())),round((snake.ycor()))])

Related

having trouble registering collision

I've been having trouble with getting my bullet (named asteroid) and my zombie. more specifically, I'm having trouble getting my game to register collision between these two turtles, it gets even weirder when you reverse the lesser than symbol into a greater than symbol. I do not know what is up with my code, any help is appreciated.(I have included the entirety of my code, since I am unsure of the source of the problem, I just know which part isn't working, I would recommend starting there.)
#the bullet that doesn't hit it's target
#Turtle Graphics game
import turtle
import random
import time
#set up screen
wn = turtle.Screen()
wn.bgcolor("grey")
finish= False
def randor1():
rand=random.randint(-280,280)
def randor2():
rand=random.randint(50,280)
def check_target_pos():
#side boundary checking
if zombie.xcor() > 280 or zombie.xcor() <- 280:
zombie.right(180)
#top/bottom boundary checking
if zombie.ycor() > 280 or zombie.ycor() <- 280:
zombie.right(180)
def check_turtle_pos():
#side boundary checking
if asteroid.xcor() > 280 or asteroid.xcor() <- 280:
asteroid.right(180)
#top/bottom boundary checking
if asteroid.ycor() > 280 or asteroid.ycor() <- 280:
asteroid.right(180)
def new_asteroid():# the turtle bullet,will change the name later on
for i in range(50):
asteroid.forward(10)
asteroid.goto(0,0)
def k2():#turn turtle left
asteroid.left(45)
def k3():#turn turtle right
asteroid.right(45)
#Draw border for arena
mypen = turtle.Turtle()
mypen.penup()
mypen.setposition(-300,-300)
mypen.pendown()
mypen.pensize(3)
for side in range(4):
mypen.forward(600)
mypen.left(90)
mypen.hideturtle()
#create turtle turtle, again will change name later
asteroid = turtle.Turtle()
asteroid.color("green")
asteroid.shape("turtle")
asteroid.penup()
asteroid.speed(0)
#create turtle zombie
def zombies():
global zombie
zombie= turtle.Turtle()
zombie.hideturtle()
zombie.color("green")
zombie.shape("circle")
zombie.penup()
zombie.speed(0)
x= random.randint(-280,280)
y= random.randint(50,280)
zombie.goto(x,y)
zombie.showturtle()
zombies()
while (finish!= True):
check_target_pos()
check_turtle_pos()
zombie.forward(1)
def end():
finish==True
wn.bye()
if asteroid.distance(zombie)<40: #problem area
end()
wn.onkey(new_asteroid, "space")#shoot button.
wn.onkey(k2, "Left")#turn left button
wn.onkey(k3, "Right") #turn right button
wn.onkey(end, "e")#exit
wn.listen()#so all the on key functions above work
Your code is somewhat a mess and doesn't facilitate the event-driven nature of turtle. There is no place for while True: loops nor time.sleep() or such in this environment. You also seem to be confusing your gun with your bullet (you're flinging your gun into space to kill the zombie, not its bullet!)
I've rewritten your code below using an event-based model with ontimer(). This is a single bullet implementation (you can't fire again until your bullet hits something or disappears into the distance):
from turtle import Screen, Turtle
from random import randint
def check_bullet_position():
if bullet.distance(turtle) > 240:
bullet.hideturtle()
if bullet.distance(zombie) < 20:
bullet.hideturtle()
reset_zombie()
def shoot_bullet():
if bullet.isvisible():
return
bullet.setheading(turtle.heading())
bullet.setposition(turtle.position())
bullet.forward(15)
bullet.showturtle()
def turn_left():
turtle.left(20)
def turn_right():
turtle.right(20)
def reset_zombie():
while zombie.distance(turtle) < 240:
x = randint(-280, 280)
y = randint(-280, 280)
zombie.goto(x, y)
zombie.setheading(zombie.towards(turtle))
def move():
zombie.forward(1)
if bullet.isvisible():
bullet.forward(2)
check_bullet_position()
screen.update()
if turtle.distance(zombie) > 20:
screen.ontimer(move)
# Set up screen
screen = Screen()
screen.tracer(False)
screen.bgcolor('grey')
# Draw border for arena
pen = Turtle()
pen.hideturtle()
pen.pensize(3)
pen.penup()
pen.setposition(-300, -300)
pen.pendown()
for _ in range(4):
pen.forward(600)
pen.left(90)
# Create turtle turtle
turtle = Turtle()
turtle.shape('turtle')
turtle.color('green')
turtle.penup()
# Create turtle bullet
bullet = Turtle()
bullet.hideturtle()
bullet.shape('circle')
bullet.shapesize(0.5)
bullet.color('yellow')
bullet.penup()
# Create turtle zombie
zombie = Turtle()
zombie.shape('circle')
zombie.color('red')
zombie.penup()
reset_zombie()
screen.onkey(shoot_bullet, 'space')
screen.onkey(turn_left, 'Left')
screen.onkey(turn_right, 'Right')
screen.onkey(screen.bye, 'e') # exit
screen.listen() # enable onkey() functions above
move()
screen.mainloop()
This should give you a starting point for building the game you envision. It is possible to write a multiple bullet implementation, it just take a little more thought and design work.
Your searching for a collision outside of the loop where you shot the projectile.
The easiest way to make your code work is to add the collision detection to the new_asteroid() function. But I don't think that's the right way.
Your technique is what is referred to as blocking. while you're projectile is moving, no other code is running. hence your collision detection is not working. change Line 38 to this.
def new_asteroid():# the turtle bullet,will change the name later on
for i in range(50):
asteroid.forward(10)
if asteroid.distance(zombie) < 40: # problem area
end()
asteroid.goto(0,0)
To create a non-blocking version of this function you would have to divide the for loop up to increments called by your main loop. so that your projectile moves once per iteration, instead of all at once.
Your program also crashes on exit. May I recommend re organizing your code into functions, then execution. it makes it much more readable. Happy gaming.

Obstacle freezes during player input - Python Turtle

My Python turtle game obstacle freezes when the player receives input and continues afterward:
# Written in Python 3
# By
# February 4th, 2019
# Purpose: Mimic the no-wifi Google Chrome dinosaur game
# Bonus 6
import turtle # Used for graphics
from turtle import Screen # Used for inputs
import random# Used to generate a random number
import time
# Creates a turtle with the proper size and color
player = turtle.Turtle()
player.shape("square")
player.color("#cc0000")
player.turtlesize(1.5, 1.5)
player.penup()
player.goto(-50, 0)
# Creates the ground
ground = turtle.Turtle()
ground.shape("square")
ground.turtlesize(0.25, 300)
ground.penup()
ground.goto(0, -18)
# This function makes the square jump, unbinds 'Up', return to the ground, then rebinds 'Up'
def jump():
Screen().onkey(null, 'Up')
player.speed(2)
if player.ycor() == 0:
player.goto((player.xcor()), (player.ycor()+100))
print("G")
player.speed(1.5)
player.goto(-50, 0)
Screen().onkey(jump, 'Up')
# Blank function
def null():
n =1
Screen().onkey(jump, 'Up')
Screen().listen()
# Ignore this
x = 3 * random.sample(range(4), 4)
print (x)
print (x[1])
# Creating obstacles (not finished, just moves)
obst1 = turtle.Turtle()
obst1.shape("square")
obst1.turtlesize(3, 2)
obst1.penup()
obst1.goto(300,0)
obst1.speed(1)
obst1.setx(-300)
I want the obstacle to continue moving while I jump. I only have Python 3 and its standard modules. I cannot download PIP or anything else like it, for some reason. I'm trying to mimic the dinosaur game from Google Chrome. I'm new to this sort of thing so please explain any suggestions in as much detail as possible. Thanks a lot!
The way you wrote your code, you can only move one turtle at a time. Below is a rework of your code where the user controls the player, but the obstacle is controlled by a timer so they can move at the same time:
from turtle import Screen, Turtle
# This function unbinds 'Up', makes the square jump, return to the ground, then rebinds 'Up'
def jump():
screen.onkey(None, 'Up')
if player.ycor() == 0:
player.forward(150)
player.backward(150)
screen.onkey(jump, 'Up')
def move():
obstacle.forward(6)
if obstacle.xcor() > -400:
screen.ontimer(move, 100)
# Creates the ground
ground = Turtle('square')
ground.turtlesize(0.25, 45)
ground.penup()
ground.sety(-15)
# Creates a turtle with the proper size and color
player = Turtle('square')
player.color('red')
player.turtlesize(1.5)
player.speed('slowest')
player.penup()
player.setx(-100)
player.setheading(90)
screen = Screen()
screen.onkey(jump, 'Up')
screen.listen()
# Creating obstacles (not finished, just moves)
obstacle = Turtle('square')
obstacle.turtlesize(3, 1.5)
obstacle.speed('fastest')
obstacle.penup()
obstacle.setposition(400, 15)
obstacle.setheading(180)
move()
screen.mainloop()
This should more closely simulate the type of motion you're trying to achieve.

Python turtle mouse does not follow directly

How do you make turtle move without using turtle.goto(x,y) but turtle.speed(speed) and turtle.heading(angle)? I need this for a game I am making. Where the mouse is, I want to make it go in that direction. But when I change it, it goes to that place then to my mouse:
import turtle
screen = turtle.Screen()
screen.title("Test")
screen.bgcolor("white")
screen.setup(width=600, height=600)
ship = turtle.Turtle()
ship.speed(1)
ship.shape("triangle")
ship.penup()
ship.goto(0,0)
ship.direction = "stop"
ship.turtlesize(3)
turtle.hideturtle()
def onmove(self, fun, add=None):
if fun is None:
self.cv.unbind('<Motion>')
else:
def eventfun(event):
fun(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale)
self.cv.bind('<Motion>', eventfun, add)
def goto_handler(x, y):
onmove(turtle.Screen(), None)
ship.setheading(ship.towards(x, y)) #this is where you use the x,y cordinates and I have seat them to got to x,y and set heading
ship.goto(x,y)
onmove(turtle.Screen(), goto_handler)
onmove(screen, goto_handler)
If you only setheading and speed it just turns that way and does not move. If you try this code it works -- it is just that I use ship.goto(x, y) which makes it go to (x, y). But when you change your mouse when it is moving, it first goes to (x, y) then to your new mouse position. I pretty much just want it to just follow the mouse but I can not do that.
I believe the code below gives you the motion you desire. It only uses onmove() to stash the target's position and uses an ontimer() to aim and move the turtle. It also stops when the target has been enveloped:
from turtle import Screen, Turtle, Vec2D
def onmove(self, fun, add=None):
if fun is None:
self.cv.unbind('<Motion>')
else:
def eventfun(event):
fun(Vec2D(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale))
self.cv.bind('<Motion>', eventfun, add)
def goto_handler(position):
global target
onmove(screen, None)
target = position
onmove(screen, goto_handler)
def move():
if ship.distance(target) > 5:
ship.setheading(ship.towards(target))
ship.forward(5)
screen.ontimer(move, 50)
screen = Screen()
screen.title("Test")
screen.setup(width=600, height=600)
ship = Turtle("triangle")
ship.turtlesize(3)
ship.speed('fast')
ship.penup()
target = (0, 0)
onmove(screen, goto_handler)
move()
screen.mainloop()

players not moving simultaneously

I am attempting to make a game in python with the turtle module, I have the square moving towards the player (the circle) and the aim is for the circle to jump over the square and not get hit.
The player can jump by pressing the spacebar,
but every time you hit the space bar to jump the player jumps, but the square stops moving and you are unable to jump over.
here is my code:
import turtle
import time
wn = turtle.Screen()
wn.bgcolor("white")
wn.title("dinosaur run")
wn.tracer(1,20)
floor = turtle.Turtle()
floor.fd(370)
floor.bk(370*2)
floor.ht()
player = turtle.Turtle()
player.shape("circle")
player.penup()
player.setpos(-370,14)
def jump():
player.lt(90)
player.fd(40)
time.sleep(0.5)
player.bk(40)
player.rt(90)
turtle.listen()
turtle.onkey(jump, "space")
class cactus(turtle.Turtle):
turtle.shape("square")
turtle.penup()
turtle.speed(0)
turtle.setpos(370,14)
cactusspeed = 2
while True:
x = turtle.xcor()
x -= cactusspeed
turtle.setx(x)
Thanks a lot,
all ideas welcome,
I've tried wn.update() at the end
As provided above, your code doesn't run at all as cactusspeed never gets defined. And your class cactus doesn't have a hope of working as currently laid out (reread about Python classes.) Finally, your while True: has no business in an event driven world like turtle.
Below is my rework of your code to use an ontimer() event to control the cactus independent of the player. I also eliminated the sleep() and simply made the player move slower and jump higher. I believe this should give you the dynamic you're looking for:
from turtle import Turtle, Screen
def jump():
player.forward(100)
player.backward(100)
def move():
if cactus.xcor() < -screen.window_width()/2:
cactus.hideturtle()
cactus.setx(370)
cactus.showturtle()
else:
cactus.forward(cactusspeed)
screen.ontimer(move, 40)
screen = Screen()
floor = Turtle(visible=False)
floor.speed('fastest')
floor.fd(370)
floor.bk(370 * 2)
player = Turtle("circle", visible=False)
player.penup()
player.setpos(-370, 14)
player.setheading(90)
player.speed('slowest')
player.showturtle()
cactusspeed = 4
cactus = Turtle("square", visible=False)
cactus.speed('fastest')
cactus.penup()
cactus.setpos(370, 14)
cactus.setheading(180)
cactus.showturtle()
screen.onkey(jump, "space")
screen.listen()
move()
screen.mainloop()

Turtle onscreenclick not behaving as expected

I am trying to create a basic Turtle Race. My only requirement is that the turtles must move with each click on the screen. I am trying to use onscreenclick to call a function that moves the turtles forward a random amount and then checks their x-coordinates to determine if someone has won.
import turtle
import random
import time
def raceRound():
firstRacer.forward(random.randint(1, 10))
secondRacer.forward(random.randint(1, 10))
checkWinner()
def firstRacerSetup():
# setup turtle
def secondRacerSetup():
# set up second turtle
def screenSetup():
# create screen
def checkWinner():
if firstRacer.xcor() >= 80:
announcer.write("Congratualtions! You won!")
if secondRacer.xcor() >= 80:
announcer.write("Sorry... You lost")
wn = turtle.Screen()
racerName = wn.textinput("Name Entry", "What would you like your turtle's name to be?")
screenSetup()
announcer = turtle.Turtle()
announcer.hideturtle()
announcer.penup()
announcer.goto(0, -140)
announcer.write("Welcome to the race!", align='center')
time.sleep(3)
firstRacerSetup()
secondRacerSetup()
announcer.write("Click to start the race!", align='center')
wn.onscreenclick(raceRound)
turtle.done()
I'm just not sure where I am going wrong and some assistance would be greatly appreciated

Categories

Resources