Entire screen not moving with the turtle - python

I am making a game in python using the turtle module in python.
I want the screen to move with the turtle. Is there any way to do it? Thanks

The problem is that the screen isn't moving with the turtle ... Does
anyone know why?
I know why. First, #martineau is correct, as usual +1, about passing the wrong range of values to yview_moveto(). But there's another piece to this puzzle: tkinter and turtle do not use the same coordinate system! You need to correct for the coordinate system difference, then turn the value into a percentage.
Here's a stripped down example based on your code and desired behavior. It keeps the ball in the middle of the window but you can tell from the numbers, and the vertical scroll bar, it's falling. Tap the the up arrow to slow it down -- tap it again to stop the motion. Tap it once more to start rising. Or use the down arrow to reverse your movement again:
from turtle import Screen, Turtle
WIDTH, DEPTH = 300, 10_000
CURSOR_SIZE = 20
vy = -10
def rise():
global vy
vy += 5
def fall():
global vy
vy -= 5
def move():
global vy
if abs(ball.ycor()) < DEPTH/2:
ball.forward(vy)
canvas.yview_moveto((DEPTH/2 - ball.ycor() - WIDTH/2 + CURSOR_SIZE) / DEPTH)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.setup(WIDTH, WIDTH) # visible window
screen.screensize(WIDTH, DEPTH) # area window peeps into
screen.tracer(False)
canvas = screen.getcanvas()
marker = Turtle()
marker.hideturtle()
marker.penup()
marker.setx(-WIDTH/4) # so we can see we're moving
for y in range(-DEPTH//2, DEPTH//2, 100):
marker.sety(y)
marker.write(y, align='right')
ball = Turtle('circle')
ball.speed('fastest')
ball.setheading(90)
ball.penup()
screen.onkey(rise, 'Up')
screen.onkey(fall, 'Down')
screen.listen()
move()
screen.mainloop()

Related

Why is my Python turtle screen asymmetrical?

I created a pong game where I noticed the paddles are not placed equally at the screen edges.
I created an 800 pixel wide screen, and placed paddles at xcor = 380 and xcor = -380 but on the screen left paddle shows some gap but right paddle doesn't. Is my screen unsymmetrical? How do I fix it?
screen.setup(width=800, height=600)
screen.bgcolor("black")
screen.title("PONG")
screen.tracer(0)
l_paddle = Paddle()
l_paddle.create_paddle((-380, 0))
r_paddle = Paddle()
r_paddle.create_paddle((380, 0))
screenshot of screen
When we specify a window size to setup(), we're talking about total pixels used on the screen. Since there is chrome around the window (edges, title bar, etc.) the actual area we have to work with is slightly smaller. Trying to place two turtles at exactly the left and right edge, ignoring chrome:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
WIDTH, HEIGHT = 600, 400
screen = Screen()
screen.setup(WIDTH, HEIGHT)
l_paddle = Turtle('square')
l_paddle.fillcolor('white')
l_paddle.setx(CURSOR_SIZE/2 - WIDTH/2)
r_paddle = Turtle('square')
r_paddle.fillcolor('white')
r_paddle.setx(WIDTH/2 - CURSOR_SIZE/2)
screen.exitonclick()
We get a result similar to yours:
If we compensate for the internal and external chrome elements:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
BORDER_SIZE = 2 # inside the window
CHROME_SIZE = 9 # around the window
WIDTH, HEIGHT = 600, 400
screen = Screen()
screen.setup(WIDTH, HEIGHT)
l_paddle = Turtle('square')
l_paddle.fillcolor('white')
l_paddle.setx(CURSOR_SIZE/2 - WIDTH/2 + BORDER_SIZE)
r_paddle = Turtle('square')
r_paddle.fillcolor('white')
r_paddle.setx(WIDTH/2 - CURSOR_SIZE/2 - BORDER_SIZE - CHROME_SIZE)
screen.exitonclick()
We can get a more precise result:
The problem here is that the amount of chrome is system dependent but turtle doesn't tell us how much to compensate. You might be able to find out from the underlying tkinter code.
My recommendation is you estimate the best you can, assume it's not accurate on all systems, and stay away from the edges so it's less of an issue. The error can be greater in the Y dimension when the title bar is part of the chrome.

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.

Why does the turtle window stops responding?

I am trying to use the turtle module for a python, but it stops responding in further compilations after the first successful compilation. I have tried this both in Spyder and Jupyter but the result is the same.
Edit 1: This is the code I used, it is not self-made I learnt it from youtube.
Edit 2: The kernel keeps dying after I close the turtle window due to it not responding
import turtle
wn=turtle.Screen()
wn.title("Made by ")
wn.bgcolor("black")
wn.setup(width=800,height=600)
wn.tracer(0) #Keeps the screen up
#Paddle A
paddle_a=turtle.Turtle() #object of turtle
paddle_a.speed(0) #speed of animation
paddle_a.shape("square")
paddle_a.color("red")
paddle_a.shapesize(stretch_wid=5, stretch_len=1) #default size is 20*20
paddle_a.penup() #not to draw lines
paddle_a.goto(-350,0)
#Paddle B
paddle_b=turtle.Turtle() #object of turtle
paddle_b.speed(0) #speed of animation
paddle_b.shape("square")
paddle_b.color("blue")
paddle_b.shapesize(stretch_wid=5, stretch_len=1) #default size is 20*20
paddle_b.penup() #not to draw lines
paddle_b.goto(350,0)
#Ball
ball=turtle.Turtle() #object of turtle
ball.speed(0) #speed of animation
ball.shape("circle")
ball.color("white")
ball.penup() #not to draw lines
ball.goto(0,0)
ball.dx=0.09 #moves by 2 pixels
ball.dy=0.09
#Function
def paddle_a_up():
y=paddle_a.ycor() #mentions the y coordinate
y=y+20
paddle_a.sety(y) #set y coordinate to new y
def paddle_a_down():
y=paddle_a.ycor() #mentions the y coordinate
y=y-20
paddle_a.sety(y) #set y coordinate to new y
def paddle_b_up():
y=paddle_b.ycor() #mentions the y coordinate
y=y+20
paddle_b.sety(y) #set y coordinate to new y
def paddle_b_down():
y=paddle_b.ycor() #mentions the y coordinate
y=y-20
paddle_b.sety(y) #set y coordinate to new y
#Keyboard binding
wn.listen() #listen keyboard input
wn.onkeypress(paddle_a_up,'w')
wn.onkeypress(paddle_a_down,'s')
wn.onkeypress(paddle_b_up,"Up")
wn.onkeypress(paddle_b_down,"Down")
#Main loop
running=True
while running:
wn.update() #updates the screen
#movement the ball
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
This is the code I used, it is not self-made I learnt it from youtube.
It would have helped if the person who posted it on YouTube had learnt turtle properly. The main loop of this code is potentially blocking tkinter events. The code also does more work than necessary by not oriented the turtles to its advantage. See if my rewrite works better for you:
from turtle import Screen, Turtle
# Functions
def paddle_a_up():
paddle_a.forward(20)
def paddle_a_down():
paddle_a.backward(20)
def paddle_b_up():
paddle_b.forward(20)
def paddle_b_down():
paddle_b.backward(20)
# Main loop
def move():
x, y = ball.position()
ball.setposition(x + ball.dx, y + ball.dy)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.bgcolor('black')
screen.setup(width=800, height=600)
screen.tracer(False)
# Paddle A
paddle_a = Turtle()
paddle_a.shape('square')
paddle_a.shapesize(stretch_wid=1, stretch_len=5)
paddle_a.setheading(90)
paddle_a.penup()
paddle_a.color('red')
paddle_a.setx(-350)
# Paddle B
paddle_b = paddle_a.clone()
paddle_b.color('blue')
paddle_b.setx(350)
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.dx = 1 # user defined object properties
ball.dy = 1
# Keyboard binding
screen.onkeypress(paddle_a_up, 'w')
screen.onkeypress(paddle_a_down, 's')
screen.onkeypress(paddle_b_up, 'Up')
screen.onkeypress(paddle_b_down, 'Down')
screen.listen()
move()
screen.mainloop()
Running under Spyder and/or Jupyter adds further complications when you restart a turtle program. The above was only tested at the command line.

How to draw a filled rectangle in python turtle

import turtle
def penup():
for x in drawings:
x.penup()
penup()
def drawgrass():
for x in range(10):
grass.goto(300,300)
grass.color("green")
grass.begin_fill()
grass.forward(200)
grass.left(300)
grass.forward(200)
grass.left(300)
grass.end_fill()
penup()
drawgrass()
So I am creating this program that will make a landscape of some kind, and I am trying to make the grass. I was thinking of placing the cursor at 300,300, then drawing a huge rectange and then filling it making it green. So far I can not make the rectangle work, or make it cover the whole bottom half of the screen. Can someone help me please?
As in your other question, your penup() function makes no sense. Here's how I might go about filling half the screen with green:
from turtle import Screen, Turtle
def drawgrass():
grass.color("green")
width, height = screen.window_width(), screen.window_height()
grass.penup()
grass.goto(-width/2, 0)
grass.pendown()
grass.begin_fill()
for _ in range(2):
grass.forward(width)
grass.right(90)
grass.forward(height/2)
grass.right(90)
grass.end_fill()
screen = Screen()
grass = Turtle()
grass.speed('fastest') # because I have no patience
drawgrass()
grass.hideturtle()
screen.exitonclick()
But what I would really do is stamp it:
from turtle import Screen, Turtle
CURSOR_SIZE = 20
def drawgrass():
grass.color('green')
grass.shape('square')
width, height = screen.window_width(), screen.window_height()
grass.penup()
grass.goto(0, -height/4)
grass.shapesize(height/2 / CURSOR_SIZE, width / CURSOR_SIZE)
grass.stamp()
screen = Screen()
grass = Turtle()
grass.hideturtle()
drawgrass()
screen.exitonclick()

Keyboard input and score. Python turtle

I have found a "flappy game" project and I am modifying it to my liking.
I would like to know how I can control the definition "tap" with the keyboard and not with the mouse (I have tried the online code "onkey" and it did not work) and I would like to know if I can add a score.
Next I attach the code that I have in possession at the moment and I would appreciate some feedback.
from random import *
from turtle import *
from freegames import vector
bird = vector(0, 0)
balls = []
def tap(x, y):
"Move bird up in response to screen tap."
up = vector(0, 30)
bird.move(up)
def inside(point):
"Return True if point on screen."
return -200 < point.x < 200 and -200 < point.y < 200
def draw(alive):
"Draw screen objects."
clear()
goto(bird.x, bird.y)
if alive:
dot(10, 'green')
else:
dot(10, 'red')
for ball in balls:
goto(ball.x, ball.y)
dot(20, 'black')
update()
def move():
"Update object positions."
bird.y -= 5
for ball in balls:
ball.x -= 3
if randrange(10) == 0:
y = randrange(-199, 199)
ball = vector(199, y)
balls.append(ball)
while len(balls) > 0 and not inside(balls[0]):
balls.pop(0)
if not inside(bird):
draw(False)
return
for ball in balls:
if abs(ball - bird) < 15:
draw(False)
return
draw(True)
ontimer(move, 50)
setup(420, 420, 370, 0)
hideturtle()
up()
tracer(False)
onscreenclick(tap)
move()
done()
I've tried all kinds of functions and none has worked.
I would like to know how I can control the definition "tap" with the
keyboard and not with the mouse
That should be as simple as replacing:
onscreenclick(tap)
with
onkey(tap, "Up")
listen()
and dropping the x and y arguments to tap(). I've reworked your code below to make this change as well as eliminate:
from freegames import vector
and make it run just with what's available in turtle. I also changed the logic of keeping vectors and having the default turtle draw dots in their locations to instead making the balls and bird all turtles and just moving them as needed. Since turtles aren't garbage collected normally, I keep a list of balls that have gone off screen to reuse again:
from random import randrange
from turtle import Turtle, Screen
BIRD_RADIUS = 10
BALL_RADIUS = 20
CURSOR_SIZE = 20
WINDOW_WIDTH, WINDOW_HEIGHT = 420, 420
GALLERY_WIDTH, GALLERY_HEIGHT = WINDOW_WIDTH - BALL_RADIUS, WINDOW_HEIGHT - BIRD_RADIUS
def click():
"Move bird up in response to screen key click."
bird.forward(min(BIRD_RADIUS * 3, WINDOW_HEIGHT/2 - bird.ycor())) # flying higher
def is_ball_inside(turtle):
"Return True if point on screen."
x = turtle.xcor()
return -GALLERY_WIDTH/2 < x
def is_bird_inside(turtle):
"Return True if point on screen."
y = turtle.ycor()
return -GALLERY_HEIGHT/2 < y < GALLERY_HEIGHT/2
def draw(is_alive):
"Draw screen objects."
if not is_alive:
bird.color('red')
screen.update()
def move():
"Update object positions."
if not is_bird_inside(bird):
draw(False) # flew or fell out of gallery
return
bird.backward(BIRD_RADIUS/2) # falling to earth
for ball in balls:
ball.forward(3)
for ball in balls:
if ball.distance(bird) < (BIRD_RADIUS + BALL_RADIUS) / 2:
draw(False)
return
while balls and not is_ball_inside(balls[0]):
ball = balls.pop(0)
ball.hideturtle()
spare_balls.append(ball) # reduce, reuse, recycle
if randrange(10) == 0:
ball = spare_balls.pop() if spare_balls else Turtle("circle", visible=False)
ball.shapesize(BALL_RADIUS / CURSOR_SIZE)
ball.setheading(180)
ball.penup()
ball.goto(GALLERY_WIDTH/2, randrange(BALL_RADIUS - GALLERY_HEIGHT/2, GALLERY_HEIGHT/2 - BALL_RADIUS))
ball.showturtle()
balls.append(ball)
draw(True)
screen.ontimer(move, 50)
screen = Screen()
screen.setup(WINDOW_WIDTH, WINDOW_HEIGHT + 10) # little bit added for title bar
bird = Turtle("circle", visible=False)
bird.shapesize(BIRD_RADIUS / CURSOR_SIZE)
bird.color("green")
bird.setheading(90)
bird.penup()
bird.showturtle()
balls = []
spare_balls = []
screen.tracer(False)
screen.onkey(click, "Up")
screen.listen()
move()
screen.mainloop()
To make the turtle window the keyboard listener, you need to touch it with the mouse, to make it active, before hitting the up arrow key.
Before adding the current score to the window, you need to define how one scores. (Is it the number of ball successfully dodged?) Here I would use an additional, invisible turtle stationed in a fixed position that just does undo() and write() to update the scrore.

Categories