0

I've just started coding a little game using turtle, but my very first prototype is already very laggy.

import turtle
import keyboard

# Player 1 x and y cords
p1x = -350
p1y = 250

wn = turtle.Screen()
wn.title("Actua")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)

# Player 1 Setup
player_1 = turtle.Turtle()
player_1.speed(0)
player_1.shape("square")
player_1.color("red")
player_1.penup()
player_1.goto(p1x, p1y)
player_1.shapesize(1, 1)

win = turtle.Screen()

while True:
  win.update()

  # Controlls
  if keyboard.read_key:
    if keyboard.read_key() == "esc":
      quit()
    
    if keyboard.read_key() == "d" or keyboard.read_key() == "D":
      p1x = p1x+10
    
    if keyboard.read_key() == "a" or keyboard.read_key() == "A":
      p1x = p1x-10
    
    if keyboard.read_key() == "w" or keyboard.read_key() == "W":
      p1y = p1y+10
    
    if keyboard.read_key() == "s" or keyboard.read_key() == "S":
      p1y = p1y-10
    player_1.goto(p1x, p1y)

It's probably lagging because of the "while True:" but I don't know how to improve it. Are there just too many if-statements or do I first have to set specific FPS?

Further information: I'm using VSCode, my operating system is Windows 10, my PC should normally be able to handle such a short code.

Oh, and please go easy on me with the technical terms, I'm kinda new to coding.

Edit: I just tested it again, it's definitely due to the if-statements themselves. However I still don't know how I could fix it.

Rektic
  • 13
  • 2
  • From the docs (https://github.com/boppreh/keyboard#keyboardread_keysuppressfalse) `read_key()` blocks until there is keyboard input. `if keyboard.read_key` will always evaluate to `True` (try printing `bool(keyboard.readkey)`) – BHC May 17 '22 at 15:45
  • It still doesn't change anything :/ – Rektic May 17 '22 at 16:34

3 Answers3

0

Your code doesn't run at all on my system. My recommendation is to toss the keyboard module and use turtle's own built-in key event handler, as we should never have while True: in an event-driven world like turtle:

from turtle import Screen, Turtle
from functools import partial

# Players X and Y coordinates
p1x, p1y = -350, 250
p2x, p2y = 350, -250

def right(player):
    player.setx(player.xcor() + 10)
    screen.update()

def left(player):
    player.setx(player.xcor() - 10)
    screen.update()

def up(player):
    player.sety(player.ycor() + 10)
    screen.update()

def down(player):
    player.sety(player.ycor() - 10)
    screen.update()

screen = Screen()
screen.setup(width=800, height=600)
screen.bgcolor('black')
screen.tracer(False)

player_1 = Turtle()
player_1.shape('square')
player_1.color('red')
player_1.penup()
player_1.goto(p1x, p1y)

player_2 = player_1.clone()
player_2.color('green')
player_2.goto(p2x, p2y)

screen.onkey(partial(left, player_1), 'a')
screen.onkey(partial(right, player_1), 'd')
screen.onkey(partial(up, player_1), 'w')
screen.onkey(partial(down, player_1), 's')

screen.onkey(partial(left, player_2), 'Left')
screen.onkey(partial(right, player_2), 'Right')
screen.onkey(partial(up, player_2), 'Up')
screen.onkey(partial(down, player_2), 'Down')

screen.onkey(screen.bye, 'Escape')

screen.listen()
screen.update()
screen.mainloop()

I've added a second player on the arrow keys to make sure my code is compatible with two players.

cdlane
  • 40,441
  • 5
  • 32
  • 81
0

hi you are using too many keyboard.read_kry() fun: means every if statment the program should call the fun again and again:

i think now its not laggy:

import turtle
import keyboard

# Player 1 x and y cords
p1x = -350
p1y = 250

wn = turtle.Screen()
wn.title("Actua")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)

# Player 1 Setup
player_1 = turtle.Turtle()
player_1.speed(0)
player_1.shape("square")
player_1.color("red")
player_1.penup()
player_1.goto(p1x, p1y)
player_1.shapesize(1, 1)

win = turtle.Screen()
win.update()

while True:
    key = keyboard.read_key()

    if key == "esc":
        quit()

    elif key == "d" or key == "D":
        p1x = p1x + 10
        win.update()

    elif key == "a" or key == "A":
        p1x = p1x - 10
        win.update()

    elif key == "w" or key == "W":
        p1y = p1y + 10
        win.update()

    elif key == "s" or key == "S":
        p1y = p1y - 10
        win.update()

    player_1.goto(p1x, p1y)
Dizaster
  • 19
  • 5
0

Not quite sure if that would help, but try changing wn.tracer(0) parameter to something bigger (ex.10/20). The number inside means (if I understand correctly) the amount of milliseconds before another refresh takes place. I had the same problem just today, as I tried to make a simple "pong" game and it seemed to help.

Ps. on my machine it wouldn't even work with 0 as an argument PPs. - I was wrong - see the comment below

  • You don't understand correctly. The first parameter to `tracer()` isn't a time value. Setting the first parameter larger is a guessing game at best. The second parameter *is* a time value, already initially 10 and setting it to something bigger, e.g. 20, will slow things down. See the turtle documentation or [this earlier post](https://stackoverflow.com/a/48569576/5771269) – cdlane May 27 '22 at 21:25
  • Oh, thakns. Now I understand. I must have not found this post before – Bauero_320 May 28 '22 at 22:44