So I'm making a game where the two turtles race each other, but I want them to wait a bit before they start (to display a 3,2,1) screen. But I can't figure it out! I used time.sleep, and turtle.delay, but both did not work. What can I do? Here is the code :)
import turtle
import random
import time
turt = turtle.Turtle()
turt2 = turtle.Turtle()
turtle.Screen() .bgcolor("green")
turt.speed(10)
turt.penup()
turt.goto(200,100)
turt.pendown()
turt.right(90)
turt.width(10)
turt.forward(450)
turt.right(180)
turt.forward(800)
#position 1
turt.penup()
turt.goto(-400,200)
turt.pendown()
turt.right(90)
turt.forward(100)
#position 2
turt2.width(10)
turt2.penup()
turt2.goto(-400,-200)
turt2.pendown()
turt2.forward(100)
Contrary to the advice so far, I'd avoid sleep() in my turtle program and use ontimer() instead to countdown the start of the race:
from turtle import Screen, Turtle
from random import choice
FONT = ('Arial', 36, 'bold')
def race():
while turtle_1.xcor() < 200 > turtle_2.xcor():
choice([turtle_1, turtle_2]).forward(10)
def countdown(seconds=3):
pen.clear()
if seconds < 1:
screen.ontimer(race)
else:
pen.write(seconds, align='center', font=FONT)
screen.ontimer(lambda: countdown(seconds - 1), 1000)
screen = Screen()
screen.bgcolor('green')
marker = Turtle()
marker.hideturtle()
marker.speed('fastest')
marker.color('white')
marker.width(5)
marker.penup()
marker.goto(200, 300)
marker.pendown()
marker.right(90)
marker.forward(600)
pen = Turtle()
pen.hideturtle()
turtle_1 = Turtle()
turtle_1.shape('turtle')
turtle_1.color('red')
turtle_1.penup()
turtle_1.goto(-400, 200)
turtle_2 = turtle_1.clone()
turtle_1.color('blue')
turtle_2.goto(-400, -200)
countdown()
screen.exitonclick()
Related
My goal is to be able to make a snake(three turtles next to each other) move at the same time and also make the snake turn using arrow keys. I have tried the ontimer method/function but it does not work as expected. Here is my code:
import make_snake
from turtle import Turtle, Screen
game_is_on = True
screen = Screen()
screen.setup(600, 600)
screen.bgcolor("black")
screen.title("Snake Game")
snake_seg1 = make_snake.snake_segments[0]
snake_seg2 = make_snake.snake_segments[1]
snake_seg2.setheading(snake_seg1.heading())
snake_seg3 = make_snake.snake_segments[2]
snake_seg3.setheading(snake_seg2.heading())
def move_forward():
snake_seg1.forward(20)
def move_backward():
snake_seg1.backward(20)
def turn_left():
snake_seg1.left(90)
def turn_right():
snake_seg1.right(90)
screen.onkey(move_forward, "Up")
screen.onkey(move_backward, "Down")
screen.onkey(turn_left, "Left")
screen.onkey(turn_right, "Right")
while game_is_on:
for seg in make_snake.snake_segments:
seg.forward(20)
# def follow_head():
# snake_seg1.forward(20)
# snake_seg2.setheading(snake_seg1.heading())
# snake_seg2.forward(20)
# snake_seg3.setheading(snake_seg2.heading())
# snake_seg3.forward(20)
# screen.ontimer(follow_head, 0)
screen.exitonclick()
File make_snake:
from turtle import Turtle
start_positions = [0, 20, 40]
snake_segments = []
for position in start_positions:
snake_part = Turtle(shape="square")
snake_part.color("white")
snake_part.penup()
snake_part.backward(position)
snake_segments.append(snake_part)
What can I fix in my code to make it stop moving one turtle at a time?
Your program has at least one problem: you use onkey() but forgot to call listen() to allow key events.
Here's a minimalist rework of your code to get basic snake movement working, it just supports right and left turns:
from turtle import Turtle, Screen
SEGMENT_SIZE = 20
START_COORDINATES = [-SEGMENT_SIZE * count for count in range(5)]
def turn_left():
snake_segments[0].left(90)
screen.update()
def turn_right():
snake_segments[0].right(90)
screen.update()
def move_forward():
for index in range(len(snake_segments) - 1, 0, -1):
snake_segments[index].goto(snake_segments[index - 1].position())
snake_segments[0].forward(SEGMENT_SIZE)
screen.update()
screen.ontimer(move_forward, 250)
screen = Screen()
screen.setup(600, 600)
screen.title("Snake Game")
screen.tracer(False)
snake_segments = []
for position in START_COORDINATES:
snake_segment = Turtle(shape='circle', visible=False)
snake_segment.penup()
snake_segment.setx(position)
snake_segment.showturtle()
snake_segments.append(snake_segment)
snake_segments[0].color('red')
screen.onkey(turn_left, 'Left')
screen.onkey(turn_right, 'Right')
screen.listen()
screen.update()
move_forward()
screen.exitonclick()
Be careful, it's easy to lose the snake off the edge of the window and not be able to get it back again!
The thing you might be looking for here is called multiprocessing. There is an eponymous library to execute lines of code simultaneously in Python. For reference look at the following thread:
Python: Executing multiple functions simultaneously
I'm working on a python project for my intro class where I want to make a blizzard with the turtle module. So far, I've been able to make a "snowflake" appear on each keypress but I'm not sure how to make it into a conditional loop where when I click, it becomes true and keeps looping without me having to click again.
Here's the code I have right now:
def snowing(x, y):
w.speed(0)
flake_size = randint(1, 5)
rx = randint(-250, 250)
ry = randint(-300, 300)
w.color(colours[5])
w.setposition(rx, ry)
w.pendown()
w.begin_fill()
w.circle(flake_size)
w.end_fill()
w.penup()
listen()
onscreenclick(snowing, add=None)
when I click, it becomes true and keeps looping without me having to
click again.
We can make a separate event handler that is a toggle, using a global to switch between on and off on subsequent clicks. We'll combine that with a timer event to keeps the flakes coming:
from turtle import Screen, Turtle
from random import randint, choice
COLOURS = ['light gray', 'white', 'pink', 'light blue']
is_snowing = False
def toggle_snowing(x, y):
global is_snowing
if is_snowing := not is_snowing:
screen.ontimer(drop_flake)
def drop_flake():
flake_radius = randint(1, 5)
x = randint(-250, 250)
y = randint(-300, 300)
turtle.setposition(x, y)
turtle.color(choice(COLOURS))
turtle.begin_fill()
turtle.circle(flake_radius)
turtle.end_fill()
if is_snowing:
screen.ontimer(drop_flake)
turtle = Turtle()
turtle.hideturtle()
turtle.speed('fastest')
turtle.penup()
screen = Screen()
screen.setup(500, 600)
screen.bgcolor('dark blue')
screen.onclick(toggle_snowing)
screen.listen()
screen.mainloop()
When you click on the screen, the flakes will start appearing. When you click again, they will stop.
I'm doing an assignment where I have to write a small game. When a turtle collides with a dot (bug) on the screen, it will add one point to the score value in the top left and teleport the bug to another random spot. I'm having trouble getting the score to update when they collide.
I tried to put the score update within the game loop but that did not work as it kept telling me that the value is not defined. I tried solving that with a global value, but that didn't do anything:
import turtle
import math
import random
#Set up the constants for the game.
WINDOW_HEIGHT = 300
WINDOW_WIDTH = 300
FORWARD_STEP = 10 #how much does the turtle move forward
TURN_STEP = 30 #how much does the turtle turn (in degrees)
SHRINK_FACTOR = 0.95 #how much does the turtle shrink when it moves
DEATH_WIDTH = 0.05 #the size at which you stop the game because the user lost
COLLISION_THRESHOLD = 10;#we say that two turtles collided if they are this much away
#from each other
#Define functions
def game_setup():
'''set up the window for the game, a bug and the player turtle '''
#create the screen
wn = turtle.Screen()
wn.screensize(WINDOW_HEIGHT,WINDOW_WIDTH)
wn.bgcolor("light green")
#Create player turtle
player = turtle.Turtle()
player.color("blue")
player.shape("turtle")
player.penup()
player.setpos (random.randrange(1,301), random.randrange(1,301))
#create a bug
bug1 = turtle.Turtle()
bug1.color("black")
bug1.shape("circle")
bug1.shapesize(stretch_wid=0.2, stretch_len=0.2)
bug1.penup()
bug1.speed(0) #the bug is not moving
bug1.setposition(-200, 200)
#create score turtle
score_keeper = turtle.Turtle()
score_keeper.hideturtle()
score_keeper.penup()
score_keeper.setposition (-400,360)
score = 0
scorestring = "Score: %s" %score
score_keeper.write(scorestring, False, align="left", font=("Arial",14, "normal"))
return (wn,player,bug1,score_keeper)
def is_collision (player, bug1):
distance = (math.sqrt((player.xcor()-bug1.xcor())**2 + (player.ycor() - bug1.ycor())**2))
if distance < COLLISION_THRESHOLD:
return True
else:
return False
def main():
#set up the window, player turtle and the bug
(wn,player,bug1,score_keeper) = game_setup()
#make the arrow keys move the player turtle
bindKeyboard(player)
#Set this veriableto True inside the loop below if you want the game to end.
game_over = False
player_width = get_width(player)
#This is the main game loop - while the game is not over and the turtle is large enough print the width of the turtle
#on the screen.
while not game_over and player_width > DEATH_WIDTH:
#your collision detection should go here
if is_collision (player, bug1):
bug1.setpos (random.randrange(1,301), random.randrange(1,301))
player.shapesize(stretch_wid=1, stretch_len=1)
player_width = get_width(player)
player.showturtle()
print(player_width)
print("Done")
wn.exitonclick()
main()
This is most of the code. All I want it to do is when the is_collision() function happens, it adds 1 to the value of score and the score_keeper turtle then prints that value in the window.
Im havign trouble getting the score to update when they collide.
I've done a stripped down rework of your code below (substuting for methods you left out) to show how to update the score on the screen. Code like this shouldn't have an explicit main loop as it's all event driven and should instead call turtle's main event loop:
from turtle import Screen, Turtle
from random import randrange
from functools import partial
# Set up the constants for the game.
WINDOW_WIDTH, WINDOW_HEIGHT = 500, 500
FORWARD_STEP = 10 # how much does the turtle move forward
TURN_STEP = 30 # how much does the turtle turn (in degrees)
COLLISION_THRESHOLD = 10 # we say that two turtles collided if they are this much away from each other
CURSOR_SIZE = 20
FONT = ('Arial', 14, 'normal')
# Define functions
def is_collision(player, bug):
return player.distance(bug) < COLLISION_THRESHOLD
def random_position(turtle):
scale, _, _ = turtle.shapesize()
radius = CURSOR_SIZE * scale
return randrange(radius - WINDOW_WIDTH/2, WINDOW_WIDTH/2 - radius), randrange(radius - WINDOW_HEIGHT/2, WINDOW_HEIGHT/2 - radius)
def forward():
global score
player.forward(FORWARD_STEP)
if is_collision(player, bug):
bug.setposition(random_position(bug))
score += 1
score_keeper.clear()
score_keeper.write(f"Score: {score}", font=FONT)
# Set up the window for the game, a bug and the player turtle.
# Create the screen
screen = Screen()
screen.setup(WINDOW_WIDTH, WINDOW_HEIGHT)
screen.bgcolor('light green')
# Create score turtle
score_keeper = Turtle(visible=False)
score_keeper.penup()
score_keeper.setposition(-230, 230)
score = 0
score_keeper.write(f"Score: {score}", font=FONT)
# Create a bug
bug = Turtle('circle', visible=False)
bug.shapesize(4 / CURSOR_SIZE)
bug.penup()
bug.setposition(random_position(bug))
bug.showturtle()
# Create player turtle
player = Turtle('turtle', visible=False)
player.color('blue')
player.speed('fastest')
player.penup()
player.setposition(random_position(player))
player.showturtle()
# make the arrow keys move the player turtle
screen.onkey(partial(player.left, TURN_STEP), 'Left')
screen.onkey(partial(player.right, TURN_STEP), 'Right')
screen.onkey(forward, 'Up')
screen.listen()
screen.mainloop()
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()
I am new to Python 3 and I am currently making a turtle game where if you hit a red turtle, you go to the start. I do not know how to make the player move to make them collide. My code:
from turtle import Turtle, Screen
wn = Screen()
wn.bgcolor("black")
artist = Turtle()
artist.color('white')
artist.speed(0)
artist.penup()
artist.setposition(-300, -300)
artist.pendown()
artist.pensize(4)
for side in range(4):
artist.fd(600)
artist.lt(90)
artist.hideturtle()
player = Turtle()
player.color("white")
player.penup()
player.setposition(260, 260)
player.speed(10)
enemy = Turtle('circle')
enemy.color('red')
enemy.penup()
enemy.speed(9)
if player.distance(enemy) < 5:
player.hideturtle()
player.setposition(260, 260)
player.showturtle()
I do not know how to make them collide and move the player, it won't
move.
Since the OP used a proper turtle import (for turtle's Object-Oriented API) and used the distance() method instead of reimplementing one like many folks, +1!
Below I've reworked the code to provide player movement, so that it can finally collide with the enemy. To keep this example minimalist, I've made the boundary circular instead of rectangular as in the original:
from turtle import Screen, Turtle
RADIUS = 300
CURSOR_RADIUS = 10
CURSOR_DIAMETER = CURSOR_RADIUS * 2
START = RADIUS / 2 ** 0.5 - CURSOR_DIAMETER
def move_forward():
screen.onkey(None, 'Up') # disable handler inside handler
player.forward(CURSOR_RADIUS)
if player.distance(0, 0) >= RADIUS:
player.undo()
if player.distance(enemy) < CURSOR_RADIUS:
player.hideturtle()
player.setposition(START, START)
player.showturtle()
screen.onkey(move_forward, 'Up') # reenable handler
screen = Screen()
screen.bgcolor('black')
artist = Turtle(visible=False)
artist.color('white')
artist.speed('fastest')
artist.pensize(4)
artist.penup()
artist.sety(-RADIUS)
artist.pendown()
artist.circle(RADIUS)
artist.penup()
artist.setposition(START, START)
artist.pendown()
artist.dot(CURSOR_DIAMETER, 'green')
enemy = Turtle('circle')
enemy.color('red')
enemy.penup()
player = Turtle()
player.speed('fastest')
player.color('white')
player.penup()
player.setposition(START, START)
player.setheading(player.towards(enemy))
screen.onkey(lambda: player.right(45), 'Right')
screen.onkey(lambda: player.left(45), 'Left')
screen.onkey(move_forward, 'Up')
screen.listen()
screen.mainloop()
You can control the player with the arrow keys. Now the enemy needs to be made to do something other than just sit in the middle.