I want to make a Space Invaders game but my enemies don't disappear if they get hit. Does anyone know how to fix it?
I already tried a for loop (as you will see) but it doesnt work:
import turtle as tr
wn = tr.Screen()
wn.tracer(0)
bullet = tr.Turtle()
player = tr.Turtle()
enimis = []
y = -250
def shoot():
player.direction = "up"
wn.onkey(shoot,"space")
while True:
if len(enimis) == 0:
for u in range(-210,210,60):
for o in range(100,260,60):
enimi = tr.Turtle()
enimi.setpos(u,o)
enimis.append(enimi)
if player.direction == "up":
bullet.penup()
x = player.xcor()
bullet.setpos(x,y)
bullet.pendown()
for p in range(550):
bullet.setpos(x,y+p)
for k in enimis:
if bullet.distance(k) < 25:
score += 10
if score > highscore:
highscored = True
else:
highscored = False
del k
hit = True
break
else:
hit = False
wn.update()
There aren't any error messages, the enemies just don't disappear.
I don't see why you're stuck on making dead enemies disappear when the code doesn't run at all due to this error:
if player.direction == "up":
AttributeError: 'Turtle' object has no attribute 'direction'
Nor could you hit an enemy since your player and enemies can't move and the player isn't pointing at an enemy to start with. Too much magical thinking and not enough code.
To answer your question, this can't work:
for k in enimis:
if bullet.distance(k) < 25:
# ...
del k
# ...
break
It either needs to be:
for k in enimis:
if bullet.distance(k) < 25:
# ...
enimis.remove(k) # remove by value
# ...
break
or:
for k in range(len(enimis)):
if bullet.distance(enimis[k]) < 25:
# ...
del enimis[k] # remove by index
# ...
break
Below is my complete rewrite of your code to get it to basically play: player can move left and right; bullets fire, hit enemies, score points, and enemies disappear; the score is shown on the screen; etc.
from turtle import Screen, Turtle
BASELINE = -250
FONT = ('Arial', 18, 'bold')
def left():
player.setx(player.xcor() - 5)
def right():
player.setx(player.xcor() + 5)
def shoot():
global firing
firing = True
firing = False
enemies = []
score = 0
bullet = Turtle('triangle')
bullet.hideturtle()
bullet.speed('fastest')
bullet.shapesize(0.5)
bullet.setheading(90)
bullet.penup()
player = Turtle('turtle')
player.hideturtle()
player.speed('fastest')
player.color('green')
player.setheading(90)
player.penup()
player.sety(BASELINE)
player.showturtle()
marker = Turtle()
marker.hideturtle()
marker.penup()
marker.goto(-300, 300)
marker.write("Score: {}".format(score), align='center', font=FONT)
def play():
global firing, score
if not enemies:
screen.tracer(False)
for x in range(-210, 210, 60):
for y in range(100, 260, 60):
enemy = Turtle('turtle')
enemy.color('red')
enemy.setheading(270)
enemy.penup()
enemy.setpos(x, y)
enemies.append(enemy)
screen.tracer(True)
if firing:
bullet.setx(player.xcor())
bullet.sety(BASELINE)
bullet.showturtle()
for p in range(0, 550, 5):
bullet.sety(BASELINE + p)
for enemy in enemies:
if bullet.distance(enemy) < 20:
score += 10
marker.undo()
marker.write("Score: {}".format(score), align='center', font=FONT)
enemy.clear()
enemy.hideturtle()
enemies.remove(enemy)
break
else: # no break
continue
break
bullet.clear()
bullet.hideturtle()
firing = False
screen.ontimer(play, 100)
screen = Screen()
screen.onkey(shoot, 'space')
screen.onkey(left, 'Left')
screen.onkey(right, 'Right')
screen.listen()
play()
screen.mainloop()
Still needed: moving enemies left, right and down; making bullet firing and player/enemy movement happen at the same time; add back highscore; etc.
Related
In python
import time
from turtle import Turtle, Screen
# screen height and width
height = 600
width = 600
# snake initial positinn
x_coordinate = 0
y_coordinate = 0
game_on = True
screen = Screen()
screen.bgcolor("black")
screen.setup(height=height, width=width)
screen.title("Snake Game")
full_snake = []
screen.tracer(0)
# create a snake 3X3
for _ in range(3):
snake = Turtle("square")
snake.color("white")
snake.penup()
snake.goto(x_coordinate, y_coordinate)
x_coordinate -= 20
full_snake.append(snake)
snake_head = full_snake[0]
# function to operate the snake
def up():
if snake_head.heading() != 270:
snake_head.setheading(90)
def down():
if snake_head.heading() != 90:
snake_head.setheading(270)
def right():
if snake_head.heading() != 180:
snake_head.setheading(0)
def left():
if snake_head.heading() != 0:
snake_head.setheading(180)
screen.listen()
screen.onkey(up, "w")
screen.onkey(down, "s")
screen.onkey(right, "d")
screen.onkey(left, "a")
# function for snakes part to attached
def attached():
for i in range(len(full_snake) - 1, 0, -1):
new_x = full_snake[i - 1].xcor()
new_y = full_snake[i - 1].ycor()
full_snake[i].goto(new_x, new_y)
snake_head.fd(20)
# to move the snake
while game_on:
snake_head.speed(1)
screen.update()
time.sleep(0.1)
for snake in full_snake:
attached()
screen.exitonclick()
in this code snake speed is fast, I want to slow down to normal where I can placed speed() method or any method
Turtle module from python
expected output : speed of snake to be normal without detaching other two blocks
.................................................................................................................................................................................................................................................................................................................................
You can try the ontimer() method instead to control the snake movement. I modified your code a bit. You can check if the snake hits the wall too and set game_on to false in the move_snake function.
import time
from turtle import Turtle, Screen
# screen height and width
height = 600
width = 600
# snake initial position
x_coordinate = 0
y_coordinate = 0
game_on = True
screen = Screen()
screen.bgcolor("black")
screen.setup(height=height, width=width)
screen.title("Snake Game")
full_snake = []
screen.tracer(0)
# create a snake 3X3
for _ in range(3):
snake = Turtle("square")
snake.color("white")
snake.penup()
snake.goto(x_coordinate, y_coordinate)
x_coordinate -= 20
full_snake.append(snake)
snake_head = full_snake[0]
# function to operate the snake
def up():
if snake_head.heading() != 270:
snake_head.setheading(90)
def down():
if snake_head.heading() != 90:
snake_head.setheading(270)
def right():
if snake_head.heading() != 180:
snake_head.setheading(0)
def left():
if snake_head.heading() != 0:
snake_head.setheading(180)
screen.listen()
screen.onkey(up, "w")
screen.onkey(down, "s")
screen.onkey(right, "d")
screen.onkey(left, "a")
# function for snake parts to attached
def attached():
for i in range(len(full_snake) - 1, 0, -1):
new_x = full_snake[i - 1].xcor()
new_y = full_snake[i - 1].ycor()
full_snake[i].goto(new_x, new_y)
snake_head.fd(20)
# New function to move the snake
def move_snake():
attached()
screen.update()
# updated the height and width variables to fit the actual screen size (useful when screen is resized)
height = screen.window_height()
width = screen.window_width()
# check if the snake head hits the wall (19 or 20 pixels away looks fine but can be ajusted) then set game_on to false and stop the function execution
if snake_head.xcor() >= width/2 - 20 or snake_head.xcor() <= -width/2 + 19 or snake_head.ycor() >= height/2 - 19 or snake_head.ycor() <= -height/2 + 20:
game_on = False
return
# timer to recursively call the move_snake function every 500 milliseconds
screen.ontimer(move_snake, 500) # adapt to your desired speed (the lower the faster)
# start moving the snake
move_snake()
screen.exitonclick()
When I try to run my code, my python turtle window just hangs; I can't move also. I've tried removing the win_pen and it worked, but I don't know what inside the win_pen is making it hang.
It also gives me the spinning wheel since I am on Mac, and I am not sure if that is the problem for this. I'm on Big Sur 11.1 by the way.
edit: The indents are right on my screen, just a copy and paste problem
Code:
import turtle
import os
import math
import random
from random import randint
score = 0
# Set Up Screen
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("test")
# Draw border
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-300,-300)
border_pen.pendown()
border_pen.hideturtle()
border_pen.pensize(3)
for side in range(4):
border_pen.fd(600)
border_pen.lt(90)
# Draw Winning Area
win_pen = turtle.Turtle()
win_pen.hideturtle()
win_pen.shape("square")
win_pen.penup()
win_pen.setposition(0,267.7)
win_pen.shapesize(3,29.8)
# Show Score on Screen
score_pen = turtle.Turtle()
score_pen.speed(0)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 303)
scorestring = "Score: %s" %score
score_pen.write(scorestring, False, align="left", font=("Ubuntu", 14, "normal"))
score_pen.hideturtle()
# Set up Player 1
player1 = turtle.Turtle()
player1.color("blue")
player1.shape("triangle")
player1.penup()
player1.speed(0)
player1.setposition(0, -250)
player1.setheading(90)
player1speed = 15
# Set Up Enemies
en = 8
enemies = []
for i in range(en):
enemies.append(turtle.Turtle())
for enemy in enemies:
enemy.color("red")
enemy.shape("square")
enemy.penup()
enemy.speed(0)
enemy.goto(randint(-280,280),randint(-280,280))
enemy.shapesize(2,2)
enemyspeed = 2
# Draw Winning Area
win_pen = turtle.Turtle()
win_pen.hideturtle()
win_pen.shape("square")
win_pen.penup()
win_pen.setposition(0,267.7)
win_pen.shapesize(3,29.8)
#Define bullet state
#ready - ready to fire
#fire - bullet is firing
bulletstate = "ready"
def left():
x = player1.xcor()
player1.setheading(180)
player1.forward(player1speed)
if x < -280:
x = - 280
player1.setx(x)
def right():
x = player1.xcor()
player1.setheading(0)
player1.forward(player1speed)
if x > 280:
x = 280
player1.setx(x)
def up():
y = player1.ycor()
player1.setheading(90)
player1.forward(player1speed)
if y > 280:
y = 280
player1.sety(y)
def down():
y = player1.ycor()
player1.setheading(270)
player1.forward(player1speed)
if y < -280:
y = 280
player1.sety(y)
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 15:
return True
else:
return False
turtle.listen()
turtle.onkey(left, "a")
turtle.onkey(right, "d")
turtle.onkey(up, "w")
turtle.onkey(down, "s")
# Main Game Loop
while True:
if isCollision(player1, win_pen):
player1.setposition(0, -250)
player1.setheading(90)
There are several problems with your code: don't use while True: in an event-driven world like turtle -- let the event handler do its job; your collision logic is incorrect as it measures from the center of the turtles whereas we're really only concerned with the y position of the two turtles; you seem to be resetting the player in the wrong direction; you implement the winning area twice.
I've rewritten, and simplified, your code below incorporating the above changes and some other tweaks:
from turtle import Screen, Turtle
from random import randint
ENEMY_COUNT = 8
PLAYER_SPEED = 15
def left():
player.setheading(180)
player.setx(max(-280, player.xcor() - PLAYER_SPEED))
check_collision(player, win_pen)
def right():
player.setheading(0)
player.setx(min(280, player.xcor() + PLAYER_SPEED))
check_collision(player, win_pen)
def up():
player.setheading(90)
player.sety(min(280, player.ycor() + PLAYER_SPEED))
check_collision(player, win_pen)
def down():
player.setheading(270)
player.sety(max(-280, player.ycor() - PLAYER_SPEED))
check_collision(player, win_pen)
def check_collision(player, win_pen):
if abs(player.ycor() - win_pen.ycor()) < 15:
player.sety(-250)
player.setheading(90)
score = 0
# Set Up Screen
screen = Screen()
screen.bgcolor('black')
# Draw border
border_pen = Turtle()
border_pen.hideturtle()
border_pen.pensize(3)
border_pen.color('white')
border_pen.speed('fastest')
border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()
for _ in range(4):
border_pen.forward(600)
border_pen.left(90)
# Draw Winning Area
win_pen = Turtle()
win_pen.shape('square')
win_pen.shapesize(3, 29.8)
win_pen.color('gray')
win_pen.penup()
win_pen.sety(267.7)
# Show Score on Screen
score_pen = Turtle()
score_pen.hideturtle()
score_pen.color('white')
score_pen.penup()
score_pen.setposition(-290, 303)
scorestring = "Score: %s" %score
score_pen.write(scorestring, False, align='left', font=('Ubuntu', 14, 'normal'))
# Set up Player
player = Turtle()
player.shape('triangle')
player.color('blue')
player.speed('fastest')
player.setheading(90)
player.penup()
player.setx(-250)
# Set Up Enemies
enemies = []
for _ in range(ENEMY_COUNT):
enemy = Turtle()
enemy.color('red')
enemy.shape('square')
enemy.shapesize(2)
enemy.speed('fastest')
enemy.penup()
enemy.goto(randint(-280, 280), randint(-280, 280))
enemies.append(enemy)
screen.onkey(left, 'a')
screen.onkey(right, 'd')
screen.onkey(up, 'w')
screen.onkey(down, 's')
screen.listen()
screen.mainloop()
I can not get the right speed for bad and good players in this Minigame off YouTube called 'Falling Skies": GitHub Gist which uses the Python turtle module. How do I fix this? (I got stuck on Part 6 of the Minigame tutorial.)
import turtle # Our module's
import random
# Screen
ms = turtle.Screen()
ms.title("Falling Piece's mini_game by Rafa94")
ms.bgcolor("purple")
ms.setup(width=800, height=600)
ms.tracer(0)
#player
player = turtle.Turtle()
player.speed(0)
player.shape("turtle")
player.color("blue")
player.penup()
player.goto(0, -250) # y is postive in the up direction y is negative in the down direction
player.direction = "stop"
# create a list of good players # good represents good_player
goods =[]#Empty list
#Addgood players
for _ in range(20): # we are making a set of 20 players
good = turtle.Turtle() # we want the other player basically across from each other thats we copyed the code one on -y and one on +y (first player in the bottom, second player on top of Screen)
good.speed(0)
good.shape("circle")
good.color("red")
good.penup()
good.goto(0, 250) # y is postive in the up direction y is negative in the down direction
good.speed = random.randint(5,8)
goods.append(good)
# create a list of bad players # bad represents bad_players
bads = [] # Empty list
# Addbad players
for _ in range(20): # we are making a set of 20 players
bad = turtle.Turtle() # we want the other player basically across from each other thats we copyed the code one on -y and one on +y (first player in the bottom, second player on top of Screen)
bad.speed(10)
bad.shape("circle")
bad.color("yellow")
bad.penup()
bad.goto(0, 250) # y is postive in the up direction y is negative in the down direction
bad.speed = random.randint(5, 8)
bads.append(bad)
#Functions
def go_left():
player.direction = "left"
def go_right():
player.direction = "right"
#keyboard Binding
ms.listen() # it is bascally saying listen for keyboard input < ^ >
ms.onkeypress(go_left, "Left")
ms.onkeypress(go_right, "Right")
#Main game loop # while something is true it will repeat
while True:
# update screen
ms.update()
#Move player
if player.direction == "left":
x = player.xcor()
x -= + 3
player.setx(x)
if player.direction == "right":
x = player.xcor()
x += + 3
player.setx(x)
# Move Good Player
for good in goods:
y = good.ycor()
y -= good.speed # We want the ball to be falling at a smooth speed
good.sety(y)
# Check it off the Screen
if y < -300:
x = random.randint(-380, 380)
y = random.randint(300, 400)
good.goto(x, y)
# check for collision with player
if good.distance(player) < 20:
x = random.randint(-380, 380)
y = random.randint(300, 400)
good.goto(x, y)
# Move bad Player
for bad in bads:
y = bad.ycor()
y -= bad.speed # We want the ball to be falling at a slow speed
bad.sety(y)
# Check it off the Screen
if y < -300:
x = random.randint(-380, 380)
y = random.randint(300, 400)
bad.goto(x, y)
# check for collision with player
if bad.distance(player) < 20:
x = random.randint(-380, 380)
y = random.randint(300, 400)
bad.goto(x, y)
ms.mainloop()
If I understand your need, you want good guys and bad guys to move at different speeds. A key to this is understanding there are two concepts of speed at work in the program: turtle's speed() method:
player.speed(0)
good.speed(0)
bad.speed(10)
This one has to do with how fast the graphics are drawn, and not what we're interested in. And the game's own instance variable speed that the author hangs off of turtle instances:
good.speed = randint(5, 8)
bad.speed = randint(5, 8)
y -= good.speed
y -= bad.speed
Which probably shouldn't be called .speed since the turtle already has a .speed method. So we'll rename this to .velocity. This speed is how fast the object moves on the screen, and what we're interested in.
You changed the wrong one by setting good.speed(0) and bad.speed(10) which since they are not drawing, just moving turtle cursors, has little effect. What we want to do instead is change:
good.velocity = randint(1, 4) # was .speed
bad.velocity = randint(5, 8) # was .speed
And fix all our other uses of the .speed instance variable to be .velocity:
y -= good.velocity # was .speed
y -= bad.velocity # was .speed
I've made this change, among others, to the code below. You'll see that the good guys move about 2.5X faster than the bad guys:
# Our module's
from turtle import Screen, Turtle
from random import randint
# Functions
def go_left():
player.direction = 'left'
def go_right():
player.direction = 'right'
# Screen
screen = Screen()
screen.setup(width=800, height=600)
screen.title("Falling Piece's mini_game by Rafa94")
screen.bgcolor('purple')
screen.tracer(0)
# player
player = Turtle()
player.shape('turtle')
player.speed('fastest')
player.color('blue')
player.penup()
player.sety(-250) # y is positive in the up direction; negative in the down direction
player.direction = 'stop'
# Create a list of good players
# Good represents good_player
goods = [] # Empty list
# Add good players
for _ in range(20): # We are making a set of 20 players
# We want the other players basically across from each other
# thats we copyied the code one on -y and one on +y (first
# player in the bottom, second player on top of Screen)
good = Turtle()
good.shape('circle')
good.speed('fastest')
good.color('red')
good.penup()
good.goto(-100, 250) # y is positive in the up direction; negative in the down direction
good.velocity = randint(1, 4)
goods.append(good)
# Create a list of bad players
# Bad represents bad_players
bads = [] # Empty list
# Add bad players
for _ in range(20): # we are making a set of 20 players
# We want the other player basically across from each other
# thats we copyied the code one on -y and one on +y (first
# player in the bottom, second player on top of Screen)
bad = Turtle()
bad.shape('circle')
bad.speed('fastest')
bad.color('yellow')
bad.penup()
bad.goto(100, 250) # y is positive in the up direction; negative in the down direction
bad.velocity = randint(5, 8)
bads.append(bad)
# Keyboard Binding
screen.onkeypress(go_left, 'Left')
screen.onkeypress(go_right, 'Right')
screen.listen() # Basically saying listen for keyboard input
# Main game loop
# While something is true it will repeat
while True:
# Move player
x = player.xcor()
if player.direction == 'left':
x -= 3
elif player.direction == 'right':
x += 3
player.setx(x)
# Move Good Player
for good in goods:
y = good.ycor() - good.velocity # We want the ball to be falling at a smooth speed
good.sety(y)
if y < -300:
# Check if it's off the Screen
x = randint(-380, 380)
y = randint(300, 400)
good.goto(x, y)
elif good.distance(player) < 20:
# Check for collision with player
x = randint(-380, 380)
y = randint(300, 400)
good.goto(x, y)
# Move bad Player
for bad in bads:
y = bad.ycor() - bad.velocity # We want the ball to be falling at a slow speed
bad.sety(y)
if y < -300:
# Check if it's off the Screen
x = randint(-380, 380)
y = randint(300, 400)
bad.goto(x, y)
elif bad.distance(player) < 20:
# Check for collision with player
x = randint(-380, 380)
y = randint(300, 400)
bad.goto(x, y)
# Update screen
screen.update()
screen.mainloop()
I have gotten an issue where an enemy turtle stops when I shoot. I am relatively new to python so I know that my code is pretty bad. I cant seem to spot why this happens but I'm assuming its got something to do with the while loop.
here is the code:
(i have added notes so it is easy to skip to important parts of it)
import turtle
import os
#wn is window
#bp = border
bullet = 'ready'
#screen setup
wn = turtle.Screen()
wn.bgcolor('black')
wn.title('SPACE.INVADERS')
#border
bp = turtle.Turtle()
bp.speed(0)
bp.color('green')
bp.penup()
bp.setposition(-300,-300)
bp.pendown()
count=0
while count != 5:
count= (count+1)
bp.fd(600)
bp.lt(90)
bp.hideturtle()
#player
p = turtle.Turtle()
p.color('red')
p.shape('triangle')
p.penup()
p.speed(0)
p.setposition(0,-250)
p.setheading(90)
#enemy
e = turtle.Turtle()
e.penup()
e.speed(0)
e.shape('square')
e.shapesize(1.25,1.25)
e.color('orange')
e.setpos(-250,250)
e.speed(1)
#p = player
#ps = player speed
ps = 15
#moving left and right
def left_mov():
x = p.xcor()
x -= ps
p.setx(x)
def right_mov():
x = p.xcor()
x += ps
p.setx(x)
#shooting
def shoot():
global bullet
if bullet == 'ready':
bullet = 'fire'
shot= turtle.Turtle()
shot.penup()
shot.speed(0)
shot.goto(p.pos())
shot.color('white')
shot.shape('triangle')
shot.shapesize(0.5)
shot.lt(90)
shot.speed(1)
shot.fd(550)
bullet = 'ready'
#bindings
turtle.listen()
turtle.onkey(left_mov, 'Left')
turtle.onkey(right_mov, 'Right')
turtle.onkey(shoot, 'space')
#enemy movement
while True:
e.fd(500)
e.rt(90)
e.fd(25)
e.rt(90)
e.fd(500)
e.lt(90)
e.fd(25)
e.lt(90)
I'm assuming its got something to do with the while loop
Yes, it shouldn't be there! In an event-driven world like turtle, there should never be a while True: loop. Instead, we need a timer event that fires off on regular intervals that does incremental updates of the objects in motion (enemy and bullet) so they appear to move at the same time. Below is my rework of your code using a timer event:
from turtle import Screen, Turtle
# moving left and right
def left_move():
player.setx(player.xcor() - player_speed)
def right_move():
player.setx(player.xcor() + player_speed)
# screen setup
screen = Screen()
screen.bgcolor('black')
screen.title('SPACE.INVADERS')
# border
border = Turtle(visible=False)
border.speed('fastest')
border.color('green')
border.penup()
border.setposition(-300, -300)
border.pendown()
for _ in range(4):
border.forward(600)
border.left(90)
# player
player = Turtle('triangle')
player.speed('fastest')
player.color('red')
player.penup()
player.setposition(0, -250)
player.setheading(90)
player_speed = 15
# enemy
enemy = Turtle('square')
enemy.speed('fast')
enemy.shapesize(1.25)
enemy.color('orange')
enemy.penup()
enemy.setpos(-250, 250)
enemy_speed = 6 # enemy speed
enemy_direction = 1 # enemy direction
# bullet
bullet = Turtle('triangle', visible=False)
bullet.speed('fastest')
bullet.color('white')
bullet.shapesize(0.5)
bullet.penup()
bullet.left(90)
bullet_speed = 9 # bullet speed
# shooting
def shoot():
if not bullet.isvisible():
bullet.goto(player.position())
bullet.showturtle()
def move():
global enemy_direction
if bullet.isvisible():
if bullet.ycor() > 275:
bullet.hideturtle()
else:
bullet.forward(bullet_speed)
# enemy movement
enemy.forward(enemy_direction * enemy_speed)
enemy.settiltangle(enemy.tiltangle() + 3) # just for fun
x, y = enemy.position()
if x > 250 or x < -250:
enemy_direction *= -1
enemy.sety(y - 25)
screen.ontimer(move, 50)
# bindings
screen.onkey(left_move, 'Left')
screen.onkey(right_move, 'Right')
screen.onkey(shoot, 'space')
screen.listen()
move()
screen.mainloop()
This should give you the basic functionality you need to move forward and add collision detection (bullet to enemy, enemy to player, player to wall) and scoring.
Also note that turtles are global entities so creating a new bullet every time you need one is a bad idea. Even if you evenually allow overlapping bullets, keep a reusable set of bullets for that purpose.
I wanted to make a snake game in turtle but I can't seem to get the tail segments to follow the leader. As if to say I can't get the first body part to follow the head, and then the second body part to follow the first body, etc.
I tried using what maths I have but I can't seem to get it to calculate where the head just was or where the body in front of it just was.
here is my code:
#libraries
import turtle
import random
import math
#screen
the_screen = turtle.Screen()
the_screen.bgcolor("lightgreen")
the_screen.title("Catapillar")
#border
border_writer = turtle.Turtle()
border_writer.speed(0)
border_writer.color("green")
border_writer.penup()
border_writer.setposition(-275, -275)
border_writer.pendown()
border_writer.pensize(7)
for side in range(4):
border_writer.fd(550)
border_writer.lt(90)
border_writer.hideturtle()
#player
player = turtle.Turtle()
player.color("yellow")
player.shape("circle")
player.penup()
player.speed(0)
player.setposition(0,0)
player.setheading(0)
playerspeed = 2
#fruit
fruit = 1
fruit = turtle.Turtle()
fruit.color("red")
fruit.shape("circle")
fruit.penup()
fruit.speed(0)
fruit.shapesize(0.6, 0.6)
x = random.randint(-200, 200)
y = random.randint(100, 250)
fruit.setposition(x, y)
#moving and collision checker
def turnleft():
player.left(24.5)
def turnright():
player.right(24.5)
def increasespeed():
global playerspeed
playerspeed += 1
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(), 2) + math.pow(t1.ycor()-t2.ycor(), 2))
if distance < 24:
return True
else:
return False
#making the tail(s) and hiding them
tail1 = turtle.Turtle()
tail1.hideturtle()
tail1.color("yellow")
tail1.shape("circle")
tail1.penup()
tail1.speed(0)
tail1.setposition(+700,700)
tail1.shapesize(0.6, 0.6)
tail1state = 'off'
#key presses
turtle.listen()
turtle.onkeypress(turnleft, "Left")
turtle.onkeypress(turnright, "Right")
turtle.onkeypress(increasespeed, "Up")
#main loop player always moves forward, out of bound set, reset fruit
#randomly when collided, create tail1...
while True:
player.forward(playerspeed)
#gameovers'
if (player.xcor() > 275) or (player.xcor() < -275):
playerspeed += 7
print("GAME OVER")
if (player.ycor() > 275) or (player.ycor() < -275):
playerspeed += 7
print("GAME OVER")
#collision check between fruit and head
if isCollision(player, fruit):
#resets the fruit, moves it randomly
fruit.hideturtle()
if tail1state == 'off':
uuu = player.xcor()
vvv = player.ycor()
tail1.setposition(uuu,vvv)
tail1.showturtle()
tail1state = 'on'
#reset the fruit
x = random.randint(-200, 200)
y = random.randint(-100, 250)
fruit.setposition(x, y)
fruit.showturtle()
#playerspeed +=1
If you have any idea on how you think I should approach it, please let me know what you think.
Thank you.
Since this comes up over and over (but effort to effect it is rarely shown) here's my minimal, generic, slithering around a screen effect that you should be able to adapt for your own purposes:
from turtle import Turtle, Screen
SNAKE_LENGTH = 10
SNAKE_SIZE = 15
WIDTH, HEIGHT = 375, 375
CURSOR_SIZE = 20
def slither():
segment = snake[-1].clone() if len(snake) < SNAKE_LENGTH else snake.pop(0)
screen.tracer(False) # segment.hideturtle()
segment.setposition(snake[-1].position())
segment.setheading(snake[-1].heading())
segment.forward(SNAKE_SIZE)
while not -WIDTH/2 < segment.xcor() < WIDTH/2 or not -HEIGHT/2 < segment.ycor() < HEIGHT/2:
segment.undo()
segment.right(95)
segment.forward(SNAKE_SIZE)
screen.tracer(True) # segment.showturtle()
snake.append(segment)
screen.ontimer(slither, 100)
boundary = Turtle(shape='square', visible=False)
boundary.shapesize(HEIGHT / CURSOR_SIZE, WIDTH / CURSOR_SIZE)
boundary.fillcolor("white")
boundary.stamp()
head = Turtle("circle")
head.shapesize(SNAKE_SIZE / CURSOR_SIZE)
head.penup()
snake = [head]
screen = Screen()
slither()
screen.exitonclick()