1

Main.py:

from turtle import Screen
from Paddle import Paddle

#creating screen
screen = Screen()
screen.screensize(1000, 600)
screen.bgcolor('black')
screen.title('Pong')
screen.tracer(0)

#paddle objects: rPaddle is for the paddle in the right and lPaddle for the left one
rPaddle = Paddle((350, 0))     #the tuple is for the starting position of the paddle object
lPaddle = Paddle((-350, 0))

#screen listeners
screen.listen()
screen.onkey(lPaddle.up, 'w')
screen.onkey(lPaddle.down, 's')
screen.onkey(rPaddle.up, 'Up')
screen.onkey(rPaddle.down, 'Down')

game_on = True
while game_on:
    screen.update()


screen.exitonclick()

Paddle.py:

from turtle import Turtle


class Paddle(Turtle):

    def __init__(self, starting_coords): #creates the paddles
        super().__init__()
        self.paddle = Turtle("square")
        self.paddle.color('white')
        self.paddle.shapesize(5, 1)
        self.paddle.penup()
        self.paddle.goto(starting_coords)

    def up(self):
        new_y = self.paddle.ycor() + 40 #makes the paddle move 40 pixels up
        self.goto(self.xcor(), new_y)
        print("up")

    def down(self):
        new_y = self.paddle.ycor() - 40 # moves the paddle 40 pixels down
        self.goto(self.xcor(), new_y)
        print('down')

I left some print statements to make sure the key is being pressed, but still the paddle would not move even if it shows the print statements, so I am very confused about what to do as I am following a tutorial.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Juan-789
  • 11
  • 1

1 Answers1

0

It's strange that you're subclassing Turtle and also composing a Turtle instance as a field of the class. This seems to have created confusion: you're displaying self.paddle on the screen, then using self.goto() to move. self is a totally different, invisible turtle! You probably mean: self.paddle.goto(), which moves the composed turtle rather than the inherited turtle that's implicitly created when you subclass.

Remove Turtle from class Paddle(Turtle): and remove super().__init__() to get rid of the invisible turtle and display a clear error if you accidentally mix up calls.

A useful way to debug this is turtle.turtles() method, which returns a list of all turtles that have been created, from the perspective of the turtle module. After your Paddle instantiations, run:

rPaddle = Paddle((350, 0))  # creates 2 Turtles
lPaddle = Paddle((-350, 0))  # creates 2 more Turtles
import turtle
print(turtle.turtles())

You'll see:

[
  <__main__.Paddle object at 0x7f9da4803ac0>,
  <turtle.Turtle object at 0x7f9da4802590>,
  <__main__.Paddle object at 0x7f9da48039d0>,
  <turtle.Turtle object at 0x7f9da4801690>
]

4 turtles--what?!

See How to create a subclass in python that is inherited from turtle Module for more reasons why you shouldn't subclass turtle, if this isn't evidence enough.


As an aside, while game_on: slams the CPU as hard as possible, giving a non-portable framerate--fast machines run fast, slow machines run slow. It's better to use ontimer to run the event loop. Here's an example.

This is what the CPU looks like on my machine running your code (Xwayland is handling the Tkinter turtle window blasting away, causing my fan to turn on):

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
   3779 greg      20   0 1002612 113320  69604 R  90.0   0.3   3:48.13 Xwayland 
  15515 greg      20   0   41948  20736  11136 S  25.0   0.1   0:29.43 python3  
  11275 root      20   0       0      0      0 I   5.0   0.0   0:01.38 kworker+

Running the ontimer example from the link:

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
   2974 greg      20   0 6573268 327136 174848 S   7.0   1.0   2:52.85 gnome-s+ 
   5867 greg      20   0 2616860 164488  98768 S   4.3   0.5   1:34.06 Isolate+ 
   3779 greg      20   0  997208 113320  69604 S   3.3   0.3   4:15.45 Xwayland 
  15726 greg      20   0   41992  20604  11392 S   2.7   0.1   0:00.40 python3 

Less work, more stable framerate.

ggorlen
  • 44,755
  • 7
  • 76
  • 106