Problem moving snake in a snake game using Turtle - python

I'm trying to create an easier version of the snake game. Everything in the code looks ok for me but I can't make snake move as I want to. Can you help me why my code doesn't work? I don't understand why my code is not okay.
I searched for some similar games codes, but they all used time. and I couldn't understand the need for that.
Here is the code:
import turtle
import random
window = turtle.Screen()
window.screensize(600, 600)
window.title("Snake Eats Tomato Game")
window.bgcolor("skyblue")
window.tracer(0)
snake = turtle.Turtle()
snake.color("dark blue")
snake.shape("square")
snake.shapesize(1)
snake.speed(1)
snake.penup()
snake.goto(0, 100)
snake.direction = "stop"
def move():
if snake.direction == "up":
y = snake.ycor()
snake.sety(y + 20)
if snake.direction == "down":
y = snake.ycor()
snake.sety(y - 20)
if snake.direction == "left":
x = snake.xcor()
snake.setx(x + 20)
if snake.direction == "right":
x = snake.xcor()
snake.setx(x - 20)
point = 0
point_table = turtle.Turtle()
point_table.speed(0)
point_table.shape("square")
point_table.color("green")
point_table.penup()
point_table.hideturtle()
point_table.goto(-200, 200)
point_table.write(
"POİNT: {}".format(point), align="center", font=("Courier", 25, "normal")
)
def go_left():
if snake.direction != "right":
snake.direction = "left"
def go_right():
if snake.direction != "left":
snake.direction = "right"
def go_up():
if snake.direction != "down":
snake.direction = "up"
def go_down():
if snake.direction != "up":
snake.direction = "down"
window.listen()
window.onkey(go_left, "Left")
window.onkey(go_right, "Right")
window.onkey(go_up, "Up")
window.onkey(go_down, "Down")
tomato = turtle.Turtle()
tomato.penup()
tomato.color("tomato")
tomato.shape("circle")
tomato.speed(0)
tomato.setposition(random.randint(-300, 300), random.randint(-300, 300))
while True:
window.update()
snake.forward(3)
move()
if snake.xcor() < -330 or snake.xcor() > 330:
snake.right(90)
if snake.ycor() < -330 or snake.ycor() > 330:
snake.right(90)
if snake.distance(tomato) < 20:
point += 1
point_table.clear()
point_table.write(
"PUAN: {}".format(point), align="center", font=("Courier", 25, "normal")
)
tomato.setposition(random.randint(-300, 300), random.randint(-300, 300))

There were some 'errors' in your code, I'll try to adres most of them, one by one:
Instead of always calling snake.forward(3) in the while True, change snake.direction = "stop" to snake.direction = "right" as the starting movement. This will keep the while loop clean
The go_left (etc) functions had an if to check the reversed way, I've removed those, just overwrite the direction
snake.xcor() < -330 these won't work, not every screen is 330 pixels. You'll need to use window.window_width() and window.window_height() to get the current window size, and use those values to detect the edges
WHen you detect an edge, don't do snake.right(90), as this will instant move the snake. Just change the direction, to bounce it:
if (curX < window_max_left):
snake.direction = 'left'
if (curX > window_max_right):
snake.direction = 'right'
if (curY > window_max_up):
snake.direction = 'down'
if (curY < window_max_down):
snake.direction = 'up'
Applying those points, fixes the movement, and let the snake bounce of walls
* Please see the example recording below the code
The final code looks like:
import turtle
import random
window = turtle.Screen()
window.screensize(600, 600)
window.title("Snake Eats Tomato Game")
window.bgcolor("skyblue")
window.tracer(0)
snake = turtle.Turtle()
snake.color("dark blue")
snake.shape("square")
snake.shapesize(1)
snake.speed(1)
snake.penup()
snake.goto(0, 100)
snake.direction = "right"
def move():
if snake.direction == "up":
y = snake.ycor()
snake.sety(y + 10)
if snake.direction == "down":
y = snake.ycor()
snake.sety(y - 10)
if snake.direction == "left":
x = snake.xcor()
snake.setx(x + 10)
if snake.direction == "right":
x = snake.xcor()
snake.setx(x - 10)
point = 0
point_table = turtle.Turtle()
point_table.speed(0)
point_table.shape("square")
point_table.color("green")
point_table.penup()
point_table.hideturtle()
point_table.goto(-200, 200)
point_table.write(
"POİNT: {}".format(point), align="center", font=("Courier", 25, "normal")
)
def go_left():
snake.direction = "left"
def go_right():
snake.direction = "right"
def go_up():
snake.direction = "up"
def go_down():
snake.direction = "down"
window.listen()
window.onkey(go_left, "Left")
window.onkey(go_right, "Right")
window.onkey(go_up, "Up")
window.onkey(go_down, "Down")
tomato = turtle.Turtle()
tomato.penup()
tomato.color("tomato")
tomato.shape("circle")
tomato.speed(0)
tomato.setposition(random.randint(-300, 300), random.randint(-300, 300))
window_width = window.window_width()
window_height = window.window_height()
window_max_left = -abs(window_width / 2)
window_max_right = window_width / 2
window_max_down = -abs(window_height / 2)
window_max_up = window_height / 2
while True:
curX = snake.xcor()
curY = snake.ycor()
if (curX < window_max_left):
snake.direction = 'left'
if (curX > window_max_right):
snake.direction = 'right'
if (curY > window_max_up):
snake.direction = 'down'
if (curY < window_max_down):
snake.direction = 'up'
if snake.distance(tomato) < 20:
point += 1
point_table.clear()
point_table.write(
"PUAN: {}".format(point), align="center", font=("Courier", 25, "normal")
)
tomato.setposition(random.randint(-300, 300), random.randint(-300, 300))
move()
window.update()
How it looked:

Related

I can't move turtle in python which for snake game

I'm trying to make a snake game just for fun and learning but I can't move my turtle. When I add the border lines and run it. My turtle can't move a bit. Problem pop up when I add the "if turtle.xcor()>290 or turtle.xcor()<-290 or turtle.ycor()>290 or turtle.ycor()<-290:" border lines
import turtle
import time
import random
delay = 0.1
wn = turtle.Screen()
wn.title("snake game")
wn.bgcolor("white")
wn.setup(width= 700, height= 700 )
wn.tracer(0)
turtle = turtle.Turtle()
turtle.speed(0)
turtle.shape("square")
turtle.color("black")
turtlepenup()
turtle.goto(0,0)
turtle.direction = "stop"
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("blue")
food.penup()
food.goto(0,100)
segments = []
def go_up():
turtle.direction = "up"
def go_down():
turtle.direction = "down"
def go_left():
turtle.direction = "left"
def go_right():
turtle.direction = "right"
def hareket():
if turtle.direction == "up":
y = turtle.ycor()
yilan.sety(y + 15)
if turtle.direction == "down":
y = turtle.ycor()
yilan.sety(y - 15)
if turtle.direction == "left":
x = turtle.xcor()
yilan.setx(x - 15)
if turtle.direction == "right":
x = turtle.xcor()
yilan.setx(x + 15)
wn.listen()
wn.onkeypress(go_up, "w")
wn.onkeypress(go_down, "s")
wn.onkeypress(go_left, "a")
wn.onkeypress(go_right, "d")
while True:
wn.update()
if turtle.xcor()>290 or turtle.xcor()<-290 or turtle.ycor()>290 or turtle.ycor()<-290:
time.sleep(1)
turtle.goto(0,0)
turtle.direction = "stop"
if turtle.distance(yemek) < 20:
x = random.randint(-290, 290)
y = random.randint(-290, 290)
food.goto(x, y)
#segment ekle
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("grey")
new_segment.penup()
segments.append(new_segment)
for index in range(len(segments)-1, 0, -1):
x = segments[index-1].xcor()
y = segments[index-1].ycor()
segments[index].goto(x, y)
if len(segments) > 0:
x = turtle.xcor()
y = turtle.ycor()
segments[0].goto(x,y)
move()
time.sleep(delay)
wn.mainloop()
I've checked the lines and searched on the internet but i couldn't find a solution. I'm new so the problem might be easy.

Python Turtle Snake Game: Problems With Snake Segments

As you guessed from the title, I'm making a beginner form of a snake game using the turtle module in Python. So far, everything is running smoothly, except for one single detail; the segments are not attached to the head, but they are rather lying inside the head itself on top of each other (you get what I'm saying?).
Here is what I wrote:
os.system("pause")
import turtle
import random
#Game Screen Set Up
screenWidth = 600
screenHeight = 600
screencolor = "#221C35"
screentitle = "Snake Game for Beginners"
screen = turtle.Screen()
screen.setup(width=screenWidth, height=screenHeight)
screen.bgcolor(screencolor)
screen.title(screentitle)
screen.tracer(0)
#Game Objects
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("#FFFFFF")
head.penup()
head.goto(0, 0)
head.direction = "stop"
food = turtle.Turtle()
food.speed(0)
food.shape("square")
food.color("#888888")
food.penup()
food.goto(0, -40)
segments = []
#Game Functions
def upwards():
head.direction = "up"
y = head.ycor() + 20
head.sety(y)
def downwards():
head.direction = "down"
y = head.ycor() - 20
head.sety(y)
def right():
head.direction = "right"
x = head.xcor() + 20
head.setx(x)
def left():
head.direction = "left"
x = head.xcor() - 20
head.setx(x)
#Keyboard Bindings
screen.listen()
screen.onkeypress(upwards, "Up")
screen.onkeypress(downwards, "Down")
screen.onkeypress(right, "Right")
screen.onkeypress(left, "Left")
while True:
screen.update()
if head.distance(food) < 20:
food.goto(random.randint(-290, 290), random.randint(-290, 290))
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("white")
new_segment.penup()
segments.append(new_segment)
for index in range(len(segments)-1, 0, -1):
segments[index].goto(segments[index-1].xcor(), segments[index-1].ycor())
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x, y)
if (head.xcor() > 290) or (-290 > head.xcor()) or (head.ycor() > 290) or (-290 > head.ycor()):
head.goto(random.randint(-290, 290), random.randint(-290, 290))
head.direction = "stop"
for segment in segments:
segment.goto(100000, 100000)
segments.clear()
upwards()
downwards()
left()
right()````

Need a way to add teams and solo gameplay. Also any idea on making a main menu with tkinter for playing as team or solo

I'm new to programming and python. I somehow followed a guide and came up with a snake game. This game runs great. However, there are a few things that I need to add to make it much better.
First of all, I want to add some sort of start screen menu. Want it to have buttons. This start screen will tie into my next addition.
I am wanting to add a scoring system for teams or solo. I need it to selectable from the main screen. Like "play as a team" or "play on your own" buttons. If the team button is pressed then there will be 5 rounds, one round for each player. I have seen somewhat how to make the main menu screen using Tkinter. However, the other part about the teams and solo part seems to baffle me. Can't find a way to do it and can't find a guide online. I'm kinda stuck here.
Any help will be greatly needed and accepted. I will post the game code below so you guys can see it.
Thanks,
# import required modules
import turtle
import time
import random
import tkinter as tk
delay = 0.1
score = 0
high_score = 0
# Creating a window screen
wn = turtle.Screen()
wn.title("Snake Game made by name")
wn.bgcolor("coral")
# the width and height can be put as user's choice
wn.setup(width=600, height=600)
wn.tracer(0)
# head of the snake
head = turtle.Turtle()
head.shape("square")
head.color("black")
head.penup()
head.goto(0, 0)
head.direction = "Stop"
# food in the game
food = turtle.Turtle()
colors = random.choice(['red', 'yellow'])
shapes = random.choice(['square', 'triangle', 'circle'])
food.speed(0)
food.shape(shapes)
food.color(colors)
food.penup()
food.goto(0, 100)
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 250)
pen.write("My Score : 0 High Score : 0", align="center",
font=("segoe print", 24, "bold"))
# assigning key directions
def group():
if head.direction != "down":
head.direction = "up"
def godown():
if head.direction != "up":
head.direction = "down"
def goleft():
if head.direction != "right":
head.direction = "left"
def goright():
if head.direction != "left":
head.direction = "right"
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)
wn.listen()
wn.onkeypress(group, "w")
wn.onkeypress(godown, "s")
wn.onkeypress(goleft, "a")
wn.onkeypress(goright, "d")
segments = []
# Main Gameplay
while True:
wn.update()
if head.xcor() > 290 or head.xcor() < -290 or head.ycor() > 290 or head.ycor() < -290:
time.sleep(1)
head.goto(0, 0)
head.direction = "Stop"
colors = random.choice(['red', 'blue'])
shapes = random.choice(['square', 'circle'])
for segment in segments:
segment.goto(1000, 1000)
segments.clear()
score = 0
delay = 0.1
pen.clear()
pen.write("Score : {} High Score : {} ".format(
score, high_score), align="center", font=("segoe print", 24, "bold"))
if head.distance(food) < 20:
x = random.randint(-270, 270)
y = random.randint(-270, 270)
food.goto(x, y)
# Adding segment
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("lime") # tail colour
new_segment.penup()
segments.append(new_segment)
delay -= 0.00001
score += 1
if score > high_score:
high_score = score
pen.clear()
pen.write("Score : {} High Score : {} ".format(
score, high_score), align="center", font=("segoe print", 24, "bold"))
# Checking for head collisions with body segments
for index in range(len(segments)-1, 0, -1):
x = segments[index-1].xcor()
y = segments[index-1].ycor()
segments[index].goto(x, y)
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x, y)
move()
for segment in segments:
if segment.distance(head) < 20:
time.sleep(1)
head.goto(0, 0)
head.direction = "stop"
colors = random.choice(['red', 'blue', 'green'])
shapes = random.choice(['square', 'circle'])
for segment in segments:
segment.goto(1000, 1000)
segment.clear()
score = 0
delay = 0.1
pen.clear()
pen.write("Score : {} High Score : {} ".format(
score, high_score), align="center", font=("segoe print", 24, "bold"))
time.sleep(delay)
wn.mainloop()

how can i move my snake head with my arrow keys

what did I do wrong because I cant move the snakehead with my wasd key the error that I keep on getting is turtle.terminator, It also say the problem is at the wn update place can u please tell me the solution this move the sane head i tried every thing this always come up raise Terminator
turtle.Terminator
import turtle
import time
import random
delay = 0.1
# Set up the screen
wn = turtle.Screen()
wn.title("Snake")
wn.bgcolor("blue")
wn.setup(width=600, height=600)
wn.tracer(0)
# Snake head
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("red")
head.penup()
head.goto(0, 0)
head.direction = "stop"
# snake food
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("green")
food.penup()
food.goto(0, 100)
segments = []
# function
def go_up():
head.direction = "up"
def go_down():
head.direction = "down"
def go_left():
head.direction = "left"
def go_right():
head.direction = "right"
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)
# key board bindings
wn.listen()
wn.onkeypress(go_up, "w")
wn.onkeypress(go_down, "s")
wn.onkeypress(go_left, "a")
wn.onkeypress(go_right, "d")
# Main game loop
while True:
wn.update()
if head.distance(food) < 20:
# move the food to random spot
x = random.randint(-290, 290)
y = random.randint(-290, 290)
food.goto(x, y)
# add a segment
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("grey")
new_segment.penup()
segments.append(new_segment)
# move the end segments frist in revrves order
for index in range(len(segments) - 1, 0, -1):
x = segments[index - 1].xcor()
y = segments[index - 1].ycor()
segments[index].goto(x, y)
# segment 0 to where the is
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x, y)
move()
time.sleep(delay)
wn.mainloop()
This code works for moving. You have to call move() method after go_up etc.
import turtle
import time
import random
delay = 0.1
# Set up the screen
wn = turtle.Screen()
wn.title("Snake")
wn.bgcolor("blue")
wn.setup(width=600, height=600)
wn.tracer(0)
# Snake head
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("red")
head.penup()
head.goto(0, 0)
head.direction = "stop"
# snake food
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("green")
food.penup()
food.goto(0, 100)
segments = []
# function
def go_up():
head.direction = "up"
move()
def go_down():
head.direction = "down"
move()
def go_left():
head.direction = "left"
move()
def go_right():
head.direction = "right"
move()
def move():
print("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)
# key board bindings# key board bindings
wn.listen()
wn.onkeypress(go_up, "w")
wn.onkeypress(go_down, "s")
wn.onkeypress(go_left, "a")
wn.onkeypress(go_right, "d")
# Main game loop
while True:
wn.update()
if head.distance(food) < 20:
# move the food to random spot
x = random.randint(-290, 290)
y = random.randint(-290, 290)
food.goto(x, y)
# add a segment
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("grey")
new_segment.penup()
segments.append(new_segment)
# move the end segments frist in revrves order
for index in range(len(segments) - 1, 0, -1):
x = segments[index - 1].xcor()
y = segments[index - 1].ycor()
segments[index].goto(x, y)
# segment 0 to where the is
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x, y)
time.sleep(delay)
wn.mainloop()

isvisible() missing 1 required positional argument: 'self' Python Turtle Graphics Error

I've been working on this simple shooter game in python turtle for a few days and I've run into a error that I cannot find an answer to.
What I want to happen is every 5 kills the player gets, an extra enemy appears. But when I get 5 kills, infinite error messages start flooding in.
The error message is: isvisible() missing 1 required positional argument: 'self'
It points towards my enemy_attack function where I used the isvisible() command to test if the enemy had been shot or not in order to respawn it from another random position. Thanks for any help in advance.
I apologise for the lack of comments.
import turtle
import time
import random
from random import randint
game_over = False
kill_counter = 0
enemy_spawn_number = 5
def close():
turtle.bye()
speed = 10
enemy_speed = 0.5
lives = 3
wn = turtle.Screen()
wn.title("Defend.")
wn.bgcolor("black")
wn.setup(width=600, height=600)
wn.tracer(0)
player = turtle.Turtle()
player.speed(0)
player.shape("triangle")
player.color("white")
player.penup()
player.goto(0,0)
life1 = turtle.Turtle()
life1.speed(0)
life1.shape("triangle")
life1.color("yellow")
life1.penup()
life1.goto(265,-260)
life1.setheading(-90)
life2 = life1.clone()
life2.goto(240,-260)
life3 = life2.clone()
life3.goto(215,-260)
over_message = turtle.Turtle()
over_message.speed(0)
over_message.shape("square")
over_message.color("white")
over_message.penup()
over_message.goto(0,0)
over_message.ht()
killcount = over_message.clone()
killcount.goto(250,250)
killcount.ht()
killcount.write("Kill Count: 0", align="right", font=("Courier", 15, "normal"))
def go_up():
player.setheading(90)
player.forward(speed)
def go_right():
player.setheading(0)
player.forward(speed)
def go_left():
player.setheading(180)
player.forward(speed)
def go_down():
player.setheading(-90)
player.forward(speed)
wn.listen()
wn.onkeypress(go_up, "w")
wn.onkeypress(go_right, "d")
wn.onkeypress(go_left, "a")
wn.onkeypress(go_down, "s")
wn.onkeypress(close, "Escape")
collectible = turtle.Turtle()
collectible.speed(0)
collectible.shape("square")
collectible.color("blue")
collectible.penup()
collectible.goto(0,100)
bullet = turtle.Turtle()
bullet.shape("square")
bullet.color("grey")
bullet.shapesize(0.5,1)
bullet.hideturtle()
bullet.penup()
bullet.goto(500,500)
shooting = False
def shoot():
global shooting
if bullet.isvisible() == False:
player_x = player.xcor()
player_y = player.ycor()
player_facing = player.heading()
bullet.goto(player_x,player_y)
bullet.setheading(player_facing)
shooting = True
bullet.showturtle()
enemies = []
enemies.append(turtle.Turtle())
for enemy in enemies:
enemy.speed(0)
enemy.shape("circle")
enemy.color("red")
enemy.penup()
enemy.goto(0,350)
def enemy_attack():
global game_over
for enemy in enemies:
if enemy.isvisible() == True:
enemy.setheading(enemy.towards(player))
enemy.forward(enemy_speed)
wn.ontimer(enemy_attack, 10)
else:
if game_over == False:
rand_direction = randint(0,3)
if rand_direction == 0:
x = randint(-240, 200)
enemy.goto(x,450)
enemy.st()
enemy_attack()
elif rand_direction == 1:
x = randint(-240, 200)
enemy.goto(x,-450)
enemy.st()
enemy_attack()
elif rand_direction == 2:
y = randint(-210, 210)
enemy.goto(-450,y)
enemy.st()
enemy_attack()
elif rand_direction == 3:
y = randint(-210, 210)
enemy.goto(450,y)
enemy.st()
enemy_attack()
enemy_attack()
wn.onkey(shoot, "space")
while True:
wn.update()
if player.distance(collectible) < 20:
x = randint(-290, 290)
y = randint(-290, 290)
collectible.goto(x,y)
if bullet.xcor()>310 or bullet.xcor()<-310 or bullet.ycor()>310 or bullet.ycor()<-300:
shooting = False
bullet.hideturtle()
if shooting == True:
bullet.forward(0.2)
if player.xcor()>285:
playerX = player.xcor()
playerX = playerX-5
playerY = player.ycor()
player.goto(playerX,playerY)
elif player.xcor()<-285:
playerX = player.xcor()
playerX = playerX+5
playerY = player.ycor()
player.goto(playerX,playerY)
elif player.ycor()>285:
playerY = player.ycor()
playerY = playerY-5
playerX = player.xcor()
player.goto(playerX,playerY)
elif player.ycor()<-285:
playerY = player.ycor()
playerY = playerY+5
playerX = player.xcor()
player.goto(playerX,playerY)
for enemy in enemies:
if bullet.distance(enemy) < 20:
bullet.hideturtle()
enemy.hideturtle()
enemy.goto(0,350)
kill_counter = kill_counter+1
killcount.clear()
killcount.write("Kill Count: {}".format(kill_counter), align="right", font=("Courier", 15, "normal"))
if kill_counter == enemy_spawn_number:
enemies.append(turtle.Turtle)
for enemy in enemies:
enemy.speed(0)
enemy.shape("circle")
enemy.color("red")
enemy.penup()
enemy.goto(0,350)
enemy_spawn_number += 5
if enemy.distance(player) < 20:
enemy.ht()
player.goto(0,0)
lives = lives-1
if lives == 2:
life3.ht()
elif lives == 1:
life2.ht()
elif lives == 0:
life1.ht()
time.sleep(0.1)
if lives == 0:
game_over = True
collectible.ht()
player.ht()
for enemy in enemies:
enemy.ht()
over_message.write("Game Over! Press Esc to exit.", align="center", font=("Courier", 24, "normal"))```
The major problems I see are those that #furas refers to: enemy_attack() invokes itself both recursively and via a timer; turtle.Turtle is invoked without parentheses. I don't think invoking enemy_attack() either way is a good idea and instead it should be invoked in the main program loop.
One problem with using ontimer() is that you need to make sure the timeout you use is greater than the time it takes to execute the function. Unless it's designed to be running multiple instances of itself at the same time. Given it writes a global, then it probably should be only one at a time.
You shouldn't have while True: (nor time.sleep()) in an event-based environment like turtle. The ontimer() method should handle both.
Python-wise, you shouldn't do:
if bullet.isvisible() == False:
if enemy.isvisible() == True:
if game_over == False:
if shooting == True:
Instead do:
if not bullet.isvisible():
if enemy.isvisible():
if not game_over:
if shooting:
Below, I've taken apart your code and reassembled it the way I expect a turtle-based game to be designed. There may be bugs still, but it seems to be playable now:
from turtle import Screen, Turtle
from random import randint
ENEMY_SPEED = 1
PLAYER_SPEED = 4
BULLET_SPEED = 6
SMALL_FONT = ('Courier', 15, 'normal')
LARGE_FONT = ('Courier', 24, 'normal')
def go_up():
player.setheading(90)
player.forward(PLAYER_SPEED)
def go_right():
player.setheading(0)
player.forward(PLAYER_SPEED)
def go_left():
player.setheading(180)
player.forward(PLAYER_SPEED)
def go_down():
player.setheading(-90)
player.forward(PLAYER_SPEED)
def enemy_attack():
for enemy in enemies:
if enemy.isvisible():
enemy.setheading(enemy.towards(player))
enemy.forward(ENEMY_SPEED)
else:
rand_direction = randint(0, 3)
if rand_direction == 0:
x = randint(-240, 200)
enemy.goto(x, 325)
elif rand_direction == 1:
x = randint(-240, 200)
enemy.goto(x, -325)
elif rand_direction == 2:
y = randint(-210, 210)
enemy.goto(-325, y)
elif rand_direction == 3:
y = randint(-210, 210)
enemy.goto(325, y)
enemy.showturtle()
def shoot():
if not bullet.isvisible():
bullet.goto(player.position())
bullet.setheading(player.heading())
bullet.showturtle()
kill_counter = 0
enemy_spawn_number = 5
lives = 3
def move():
global kill_counter, enemy_spawn_number, lives
enemy_attack()
if player.distance(collectible) < 20:
collectible.goto(randint(-260, 260), randint(-260, 260))
if bullet.isvisible():
if not (-310 < bullet.xcor() < 310 and -310 < bullet.ycor() < 310):
bullet.hideturtle()
else:
bullet.forward(BULLET_SPEED)
playerX, playerY = player.position()
if playerX > 285:
player.setx(playerX - 5)
elif playerX < -285:
player.setx(playerX + 5)
elif playerY > 285:
player.sety(playerY - 5)
elif playerY < -285:
player.sety(playerY + 5)
for enemy in enemies:
if bullet.isvisible() and bullet.distance(enemy) < 15:
bullet.hideturtle()
enemy.hideturtle()
enemy.sety(325)
kill_counter += 1
killcount.clear()
killcount.write("Kill Count: {}".format(kill_counter), align='right', font=SMALL_FONT)
if kill_counter == enemy_spawn_number:
enemy = enemy_prototype.clone()
enemy.showturtle()
enemies.append(enemy)
for enemy in enemies:
enemy.sety(325)
enemy_spawn_number += 5
if enemy.distance(player) < 20:
enemy.hideturtle()
player.goto(0, 0)
lives -= 1
if lives == 2:
life3.hideturtle()
elif lives == 1:
life2.hideturtle()
elif lives == 0:
life1.hideturtle()
if lives == 0:
collectible.hideturtle()
player.hideturtle()
for enemy in enemies:
enemy.hideturtle()
over_message.write("Game Over! Press Esc to exit.", align='center', font=LARGE_FONT)
else:
screen.ontimer(move, 70)
screen.update()
screen = Screen()
screen.setup(width=600, height=600)
screen.title("Defend.")
screen.bgcolor('black')
screen.tracer(0)
player = Turtle()
player.shape('triangle')
player.color('white')
player.penup()
life1 = Turtle()
life1.shape('triangle')
life1.color('yellow')
life1.penup()
life1.goto(265, -260)
life1.setheading(-90)
life2 = life1.clone()
life2.goto(240, -260)
life3 = life2.clone()
life3.goto(215, -260)
over_message = Turtle()
over_message.hideturtle()
over_message.color('white')
over_message.penup()
killcount = over_message.clone()
killcount.goto(270, 270)
killcount.write("Kill Count: 0", align='right', font=SMALL_FONT)
collectible = Turtle()
collectible.shape('square')
collectible.color('blue')
collectible.penup()
collectible.goto(randint(-260, 260), randint(-260, 260))
bullet = Turtle()
bullet.hideturtle()
bullet.shape('square')
bullet.shapesize(0.5, 1)
bullet.color('grey')
bullet.penup()
bullet.goto(500, 500)
enemy_prototype = Turtle()
enemy_prototype.hideturtle()
enemy_prototype.shape('circle')
enemy_prototype.color('red')
enemy_prototype.penup()
enemy_prototype.sety(325)
enemy = enemy_prototype.clone()
enemy.showturtle()
enemies = [enemy]
screen.onkeypress(go_up, 'w')
screen.onkeypress(go_right, 'd')
screen.onkeypress(go_left, 'a')
screen.onkeypress(go_down, 's')
screen.onkeypress(screen.bye, 'Escape')
screen.onkeypress(shoot, 'space')
screen.listen()
move()
screen.mainloop()
The next issue I believe you should address are all the number constants in the code that prevent you from resizing the screen:
life1.goto(265,-260)
life2.goto(240,-260)
life3.goto(215,-260)
killcount.goto(250,250)
x = randint(-240, 200)
x = randint(-240, 200)
y = randint(-210, 210)
y = randint(-210, 210)
x = randint(-290, 290)
y = randint(-290, 290)
if bullet.xcor()>310 or bullet.xcor()<-310 or bullet.ycor()>310 or bullet.ycor()<-300:
if player.xcor()>285:
elif player.xcor()<-285:
elif player.ycor()>285:
elif player.ycor()<-285:
These should all be defined relative to the screen size:
screen.setup(width=600, height=600)
and the objects they manipulate. (I.e. no large numbers in the code!)
I run code and it worked most time without problem.
At some moment it got error
Traceback (most recent call last):
File "/home/furas/main.py", line 198, in <module>
enemy.speed(0)
File "/usr/lib/python3.7/turtle.py", line 2167, in speed
return self._speed
AttributeError: 'int' object has no attribute '_speed'
and I start thinking why enemy (which is turtle) doesn't have _speed ? Why it treats it as integer? All enemy are on list enemies so I start checking what you add to this list and I found that you forgot () in one of Turtle()
enemies.append(turtle.Turtle)
so it added class Turtle instead of instance of Turle.
After adding () I don't have this error but it seems there is other problem because after 5 killed enemies it freezes. It would need some debugging (or use of print()) to find what is a problem.
EDIT: I have the same problem if I add two enemies at start. Problem can be that it may run two times wn.ontimer which may run another two wn.ontimer so finally it may have no time to execute them.
EDIT: Code works better if I uses only wn.ontimer(enemy_attack, 10) at the end of function and remove other enemy_attack(). But this time enemies shows mostly at the same time and when I kill one of them then it remove all of them. It may need more changes.
def enemy_attack():
global game_over
for enemy in enemies:
if enemy.isvisible() == True:
enemy.setheading(enemy.towards(player))
enemy.forward(enemy_speed)
else:
if game_over == False:
rand_direction = randint(0,3)
if rand_direction == 0:
x = randint(-240, 200)
enemy.goto(x,450)
enemy.st()
#enemy_attack()
elif rand_direction == 1:
x = randint(-240, 200)
enemy.goto(x,-450)
enemy.st()
#enemy_attack()
elif rand_direction == 2:
y = randint(-210, 210)
enemy.goto(-450,y)
enemy.st()
#enemy_attack()
elif rand_direction == 3:
y = randint(-210, 210)
enemy.goto(450,y)
enemy.st()
#enemy_attack()
wn.ontimer(enemy_attack, 10)

Categories