Python turtle module - python

I'm currently new to python programming. Nowadays I'm building a snake game using the turtle module. I want to refresh the screen after every piece of snake object parts has moved. So I turned off the tracer and use the update function after the for loop.
But to do that I must import the time module and use the time.sleep() function.If I don't use it the python turtle module begins to not respond. I want to know what is the reason why I must use the time function and why I can't simply use sc.update directly without time function.
here is my code
from turtle import *
from snake import *
import time
sc = Screen()
sc.bgcolor('black')
sc.setup(width=600, height=600)
sc.tracer(0)
# diyego is our snake name
diyego = Snake(10)
run = 1
while run:
#here is the problem
sc.update()
time.sleep(1) #used time.sleep
for i in range(len(diyego.snake_object_list)-1, 0, -1):
infront_item_position = diyego.snake_object_list[i - 1].pos()
diyego.snake_object_list[i].goto(infront_item_position)
diyego.snake_head.forward(10)
sc.exitonclick()
#Snake module
from turtle import *
class Snake():
def __init__(self, number_of_parts):
"""Should pass the lenght of snake"""
self.snake_object_list = []
self.create_snake_parts(number_of_parts)
self.snake_head = self.snake_object_list[0]
def create_snake_parts(self, number_of_parts):
""" Get number of parts which snake shuld have and create snake it"""
x_cor = 0
for i in range(number_of_parts):
snake = Turtle()
snake.speed(0)
snake.shape("circle")
snake.color('white')
snake.penup()
snake.setx(x=x_cor)
self.snake_object_list.append(snake)
x_cor += -20
I just want to know why the turtle gets not respond when I remove the time.sleep()

What you describe is possible, but the problem isn't lack of use of the sleep() function but rather your use of (effectively) while True: which has no place in an event-driven world like turtle. Let's rework your code using ontimer() events and make the snake's basic movement a method of the snake itself:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
class Snake():
def __init__(self, number_of_parts):
""" Should pass the length of snake """
self.snake_parts = []
self.create_snake_parts(number_of_parts)
self.snake_head = self.snake_parts[0]
def create_snake_parts(self, number_of_parts):
""" Get number of parts which snake should have and create snake """
x_coordinate = 0
for _ in range(number_of_parts):
part = Turtle()
part.shape('circle')
part.color('white')
part.penup()
part.setx(x_coordinate)
self.snake_parts.append(part)
x_coordinate -= CURSOR_SIZE
def move(self):
for i in range(len(self.snake_parts) - 1, 0, -1):
infront_item_position = self.snake_parts[i - 1].position()
self.snake_parts[i].setposition(infront_item_position)
self.snake_head.forward(CURSOR_SIZE)
def slither():
diyego.move()
screen.update()
screen.ontimer(slither, 100) # milliseconds
screen = Screen()
screen.bgcolor('black')
screen.setup(width=600, height=600)
screen.tracer(0)
diyego = Snake(10)
slither()
screen.exitonclick()

Related

Trying to create two objects at the same time but it creates one

I'm trying to develop a simple game while I'm learning python. Game is not complex, random cars (which are squares) are spawning at right of the screen and they are going to left. We are a turtle, trying to avoid them and make it to the top of the screen.
The problem is my code below doesn't spawn two objects at the same time, it spawns just one.
from turtle import Screen
from turt import Turt
from spawnpoint import SpawnPoint
from cars import Car
import random
screen = Screen()
screen.setup(1000, 700)
screen.title("Cars and Turtle")
screen.bgcolor("gray")
turt = Turt()
is_game_on = True
screen.listen()
screen.onkey(turt.move_up, "Up")
spawn_points_ycords = [300, 200, 100, 0, -100, -200]
spawn_1 = SpawnPoint(spawn_points_ycords[0])
spawn_2 = SpawnPoint(spawn_points_ycords[1])
spawn_3 = SpawnPoint(spawn_points_ycords[2])
spawn_4 = SpawnPoint(spawn_points_ycords[3])
spawn_5 = SpawnPoint(spawn_points_ycords[4])
spawn_6 = SpawnPoint(spawn_points_ycords[5])
spawn_points = [spawn_1, spawn_2, spawn_3, spawn_4, spawn_5, spawn_6]
while is_game_on:
for n in range(60):
if n == 59:
random_spawn = spawn_points[random.randint(0, len(spawn_points)-1)]
random_spawn_2 = spawn_points[random.randint(0, len(spawn_points)-1)]
while random_spawn_2 == random_spawn:
random_spawn_2 = spawn_points[random.randint(0, len(spawn_points) - 1)]
random_spawn_car = Car(random_spawn.spawn.ycor())
random_spawn_2_car = Car(random_spawn_2.spawn.ycor())
screen.exitonclick()
My spawn points class code:
from turtle import Turtle
class SpawnPoint:
def __init__(self, ycor):
self.spawn = Turtle()
self.spawn.hideturtle()
self.spawn.speed(0)
self.spawn.penup()
self.spawn.goto(600, ycor)
self.spawn.showturtle()
self.new_car = None
and my car class code:
from turtle import Turtle
import random
class Car:
def __init__(self, ycor):
self.body = Turtle()
self.body.hideturtle()
self.body.penup()
self.body.shape("square")
self.colors = ["black", "red", "orange", "blue", "green", "yellow"]
self.body.color(self.colors[random.randint(0, len(self.colors)-1)])
self.body.shapesize(1, 5, 0)
self.body.speed(2)
self.body.goto(700, ycor)
self.body.showturtle()
self.body.goto(-700, ycor)
I can't figure it out to solve this bug. I'm using Turtle module.
The two car objects are created, but the problem is that you haven't implemented real-time movement for multiple turtles, so the first turtle completes its 5-second journey across the screen before the second one is created or begins moving.
When you encounter problems like this, my suggestion is to strip the problem down to a minimal, reproducible example. This process makes the problem obvious by removing the noise. For example, if you move the spawn and destination points onto the visible screen, the problem becomes clear.
Here's an even more minimal demonstration:
from turtle import Turtle
t = Turtle()
tt = Turtle()
t.speed(2)
tt.speed(2)
t.goto(100, 100)
tt.goto(200, 100)
t.Screen().exitonclick()
When you run this, you'll see that t moves from 0, 0 to 100, 100 in about a second. Only once t arrives at the destination does tt even begin moving. Adding print statements on each line is another way to see that each goto blocks the script completely until the slow movement completes. The simultaneous movement you expect is not the default behavior of turtle.
The typical solution is to use tracer(0) to disable the internal update/rendering loop that turtle uses to smooth out gotos. Once you've done this, you can reposition turtles at will and call turtle.update() to render a frame. It's up to you to reimplement smooth movement, which is not difficult to do.
Also worth noting, your exitonclick call is never reached and the for loop with if n == 59: is pointless. Cars are never garbage collected, and probably shouldn't be doing so much work in the initializer. Kudos for using composition rather than inheritance for your classes, though.
I'd also caution against adding complexity like multiple classes and files before you've convinced yourself that the basics are operational. If something as simple as movement isn't working as you expect, all of that other stuff only gets in the way of debugging. Run your code often, building up guarantees about its behavior as you work.
Here's a quick sketch of how you might begin to redesign your project. It's based on my recommended real-time setup for turtle.
import turtle
class Car:
def __init__(self, x, y, speed):
self.x = x
self.y = y
self.speed = speed
self.body = turtle.Turtle()
self.body.shape("square")
self.body.penup()
self.body.goto(x, y)
def move(self):
self.x -= self.speed
w = turtle.screensize()[0]
if self.x < -w:
self.x = w
self.body.goto(self.x, self.y)
def tick():
for action in keys_pressed:
actions[action]()
for car in cars:
car.move()
turtle.update()
win.ontimer(tick, frame_delay_ms)
if __name__ == "__main__":
w, h = turtle.screensize()
turtle.tracer(0)
t = turtle.Turtle()
t.penup()
t.goto(0, -h + 50)
t.left(90)
cars = [
Car(w, -200, 3),
Car(w, -100, 5),
Car(w, 0, 4.5),
Car(w, 100, 4),
Car(w, 200, 6),
]
frame_delay_ms = 1000 // 30
step_speed = 10
actions = dict(
u=lambda: t.forward(step_speed),
)
win = turtle.Screen()
keys_pressed = set()
win.onkeypress(lambda: keys_pressed.add("u"), "Up")
win.onkeyrelease(lambda: keys_pressed.remove("u"), "Up")
win.listen()
tick()
win.exitonclick()

Turtle not displaying on screen - Python

I am trying to recreate the snake game, however when I call the function which is supposed to create the initial body of the snake nothing appears on the screen.
The same problem happens if I simply create a turtle object in the main file.
Snake:
from turtle import Turtle
STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]
class Snake:
def __init__(self):
self.segments = []
self.create_snake()
def create_snake (self):
for position in STARTING_POSITIONS:
n_segment = Turtle("square")
n_segment.color("white")
n_segment.penup()
print(position)
n_segment.goto(position)
self.segments.append(n_segment)
Main:
from turtle import Turtle, Screen
from snake import Snake
screen = Screen()
screen.setup(width = 600 , height= 600)
screen.bgcolor("black")
screen.title("SNAKE")
screen.tracer(0)
game_on = True
segments = []
snake = Snake()
turtle = Turtle()
In order to see the snake, I just added the following code snippet in main.py after the turtle definition to display a stationary snake with a pointer.
while game_on:
screen.update()
screen.exitonclick()
The result was this image.
Hope that helps.
Regards.
this is a minimum reproducible example of the above code which works and draws a square (segment of the snake body) in the snake class:
import turtle as ttl
class Snake:
def __init__(self):
self.segments = []
self.create_snake()
def create_snake (self):
ttl.shape('square')
ttl.color('white')
screen = ttl.Screen()
screen.setup(width=600, height=600)
screen.bgcolor('black')
snake = Snake()
ttl.done()
A lot of the code from the OP question is removed because there were numerous errors. Also, for the purpose of simplicity the class was added to the code, but the OP could break it into two separate files if desired.
I believe that there error in the question code was that the screen was drawing over itself which is why it was always black.
You can build from here.

Why my python kept crashing when it tried to run the turtle.tracer() method in turtle module?

I was coding a Snake Game using turtle module but when I add this line into my code the turtle screen and python crashed:
turtle.tracer(0)
can somebody help me so I can complete the game? Thanks a lot
my code:
from turtle import Turtle, Screen, colormode
screen = Screen()
screen.bgcolor("black")
screen.setup(width=600, height=600)
screen.title("My Snake Game")
screen.tracer(0)
x = 0
segments = []
for turtle in range(3):
turtle = Turtle("square")
turtle.color("white")
turtle.penup()
turtle.goto(0-x, 0)
x += 20
segments.append(turtle)
game_is_on = True
screen.update()
while game_is_on:
for segment in segments:
segment.forward(20)
screen.exitonclick()
I think we need to know more about what you mean by 'crashed'. If you mean everything froze, that's the code you wrote. Once you introduce tracer() you need to provide an update() for every change you want the user to see. But you don't have any update() calls in your loop so everything visually remains as it was before the loop. If you want to see the segments move, you need to do something like:
from turtle import Turtle, Screen
screen = Screen()
screen.bgcolor('black')
screen.setup(width=600, height=600)
screen.title("My Snake Game")
screen.tracer(0)
x = 0
segments = []
for turtle in range(3):
turtle = Turtle('square')
turtle.color('white')
turtle.penup()
turtle.setx(x)
x -= 20
segments.append(turtle)
screen.update()
game_is_on = True
while game_is_on:
for segment in segments:
segment.forward(20)
screen.update()
screen.exitonclick() # never reached
If you mean by 'crashed' that Python quit back to the operating system, then you need to describe the environment under which you're running this code.

Python (Turtle) Remove turtle / arrow

I am trying to make a basic Pong and I don't understand why the arrow/turtle in the middle of the screen displays.
The paddle on the screen consists of 6x turtle objects stored in self.paddle.
I know the problem has something to do with the p = Paddle() but I don't understand where the arrow-object is since it seems to not be in the list mentioned above (print(self.paddle)).
Can someone enlighten me?
from turtle import Turtle, Screen
screen = Screen()
screen.setup(width=1000, height=700)
class Paddle(Turtle):
def __init__(self):
super().__init__()
self.paddle = []
self.create_player_paddle()
def create_player_paddle(self):
for pad in range(0, 6):
x = -480
y = 30
p = Turtle(shape="square")
p.turtlesize(0.5)
p.penup()
p.goto(x, y)
self.paddle.append(p)
for part in range(len(self.paddle)):
self.paddle[part].goto(x, y)
y -= 10
p = Paddle()
screen.update()
screen.exitonclick()
I don't understand where the arrow-object is since it seems to not be
in the list mentioned above ... Can someone enlighten me?
Normally, a class like Paddle() either isa Turtle or contains one or more instances of Turtle. But you've done both, it is both a Turtle (the source of your mystery arrow) and it contains a list of turtles. The simple fix is to remove Turtle as its superclass and remove the super().__init__() code:
class Paddle():
def __init__(self):
self.paddle = []
self.create_player_paddle()
Below is my rework of your code addressing the above and other issues I saw:
from turtle import Turtle, Screen
class Paddle():
def __init__(self):
self.segments = []
self.create_player_paddle()
def create_player_paddle(self):
x = -480
y = 30
for _ in range(6):
segment = Turtle(shape='square')
segment.turtlesize(0.5)
segment.penup()
segment.goto(x, y)
self.segments.append(segment)
y -= 10
screen = Screen()
screen.setup(width=1000, height=700)
paddle = Paddle()
screen.exitonclick()
The usual approach to a Pong game in turtle is to make the paddle a subclass of Turtle and then use shapesize() to stretch the turtle to be the rectangle you desire. But this has issues with collision detection. Your approach makes the paddle somewhat more complicated, but might work better collision-detection-wise as you can test each segment.
if you need to hide the Turtle pointer, put Turtle.hideturtle(self) in your constructor init function

Why do I need the time.sleep(x) function in this code for it to work?

from turtle import Screen, Turtle
import time
import snake
MOVE_DISTANCE = 20
UP = 90
DOWN = 270
LEFT = 180
RIGHT = 0
class InitialSnake:
def __init__(self):
self.number_x = 0
self.snake_first = []
self.create_snake()
self.actual_snake = self.snake_first[0]
def create_snake(self):
for number in range(3):
snake = Turtle(shape="square")
snake.penup()
snake.color("white")
snake.goto(self.number_x, 0)
self.number_x -= 20
self.snake_first.append(snake)
def move(self):
for segments_num in range(len(self.snake_first) - 1, 0, -1):
self.snake_first[segments_num].goto(self.snake_first[segments_num - 1].xcor(),
self.snake_first[segments_num - 1].ycor())
self.snake_first[0].forward(MOVE_DISTANCE)
def up(self):
if self.actual_snake.heading() != DOWN:
self.snake_first[0].setheading(UP)
def down(self):
if self.actual_snake.heading() != UP:
self.snake_first[0].setheading(DOWN)
def left(self):
if self.actual_snake.heading() != RIGHT:
self.snake_first[0].setheading(LEFT)
def right(self):
if self.actual_snake.heading() != LEFT:
self.snake_first[0].setheading(RIGHT)
my_screen = Screen()
my_screen.setup(width=600, height=600)
my_screen.bgcolor("black")
my_screen.title("Snake Game")
my_screen.tracer(0)
snake_1 = snake.InitialSnake()
#snake_here.create_snake()
game_is_on = True
my_screen.listen()
my_screen.onkey(snake_1.up, "Up")
my_screen.onkey(snake_1.down,"Down")
my_screen.onkey(snake_1.left,"Left")
my_screen.onkey(snake_1.right,"Right")
while game_is_on:
my_screen.update()
time.sleep(0.1)
snake_1.move()
my_screen.exitonclick()
I did not really understand the concept of the tracer and the update and how this is linked to the sleep function. I understand that when the tracer is called and turned off, it will not refresh the screen until you call the update() function. But shouldn't it still work without time.sleep(0.1) since this is just creating a short delay before the next functions get called. Can someone help me please to understand this? Thanks in advance (:
If you use print() to see snake position
while game_is_on:
my_screen.update()
snake_1.move()
print(snake_1.snake_first[0].ycor(), snake_1.snake_first[0].xcor())
then you will see it moves very, very fast and it left screen - and you simply can't see it.
On my very old computer after few milliseconds its positon was (0, 125700). Probably on the newest computer it would be much bigger value.
So this code use sleep() to slow down snake and to move it with the same speed on all computers.
BTW:
I would use turtle method to repeate code
def game_loop():
snake_1.move()
my_screen.update()
my_screen.ontimer(game_loop, 100) # repeate after 100ms (0.1s)
# start loop
game_loop()
because sleep may blocks some code and ontimer was created for non-blocking delay.

Categories