0

I'm making a game where you control a space ship, and currently, its movement is very hard to look at, because it's quite janky. Is there a command to make the movement smoother and more natural? I'm using python with turtle on repl.it, and onrelease doesn't seem to work. Any answer is appreciated!

import turtle
you = turtle.Turtle()
keycoms = turtle.Screen()

you.penup()

def w():
  you.fd(5)
def s():
  you.bk(3)
def a():
  you.lt(5)
def d():
  you.rt(5)

keycoms.onkey(w,"w")
keycoms.onkey(s,"s")
keycoms.onkey(a,"a")
keycoms.onkey(d,"d")
keycoms.listen()
martineau
  • 119,623
  • 25
  • 170
  • 301
Ruhtra37
  • 9
  • 1
  • I tried some things that smooth out standard Python turtle movement but they made no difference on Repl.it which seems reasonably smooth. However, it looks like you're relying on *key repeat* which is a feature of your computer operating system, not turtle, so the janky movement might derive from that. (See if you can adjust it.) I also recommend larger steps, e.g. `fd(10)` instead of `fd(5)`. – cdlane Feb 09 '20 at 02:37
  • Does this answer your question? [How to fix inconsistent frame rate (speed) in python turtle](https://stackoverflow.com/questions/55495581/how-to-fix-inconsistent-frame-rate-speed-in-python-turtle) – ggorlen Jan 20 '23 at 18:28
  • See also: [How to bind several key presses together in turtle graphics?](https://stackoverflow.com/questions/47879608/how-to-bind-several-key-presses-together-in-turtle-graphics/70979967?r=SearchResults&s=1|50.8985#70979967) – ggorlen Jan 20 '23 at 18:58

2 Answers2

0

One way this is often solved is to make more, smaller movements, with a slight time delay between each one. This gives the illusion of flowing movement rather than a jump - something like the following (there may be a better way to actually code it, but this gives you an idea):

def w():
  for _ in range(5):
    you.fd(1)
    sleep(0.1)
match
  • 10,388
  • 3
  • 23
  • 41
  • Thanks for the idea, but I was looking for a way for it to be a bit quicker than what your code would allow, and while your code is smoother, it's very slow. Thanks anyways though! – Ruhtra37 Feb 09 '20 at 01:17
  • The sleep interval was just an example - maybe try 0.01 or 0.005? – match Feb 09 '20 at 18:37
0

Simply change your onkey(...) to onkeypress(...):

import turtle
you = turtle.Turtle()
keycoms = turtle.Screen()

you.penup()

def w():
  you.fd(5)
def s():
  you.bk(3)
def a():
  you.lt(5)
def d():
  you.rt(5)

keycoms.onkeypress(w,"w")
keycoms.onkeypress(s,"s")
keycoms.onkeypress(a,"a")
keycoms.onkeypress(d,"d")
keycoms.listen()

keycoms.mainloop()

The Scrren.onkey() method will allow the user to press down on a specific key for as long as the user wants, and the function command to the assigned action will only execute once.

Screen.onkeypress(), on the other hand, will execute the command as many times as the user holds down the key.

Red
  • 26,798
  • 7
  • 36
  • 58
  • [onkey()](https://docs.python.org/3.1/library/turtle.html#turtle.onkey) is onkeyrelease(), while [onkeypress()](https://docs.python.org/3.1/library/turtle.html#turtle.onkeypress) doesn't require release. – Red Jul 05 '20 at 04:41
  • @cdlane I don't understand, I even tried the test you outlined. If I want to go further with `onkey()`, I need to constantly press a key, while `onkeypress()` will allow me to simply hold down a key. Is it not that way on your pc? – Red Jul 05 '20 at 12:15
  • You may be seeing different behavior on your system. The first step to understand press vs. release is turn off automatic key repeat at the operating system (e.g. keyboard control panel.) Unfortunately, on my Mac, some keys repeat regardless of turning it off (something to do with keys that have accented or other alternate forms, 'a', 'n', etc.) Once you've done that, my next comment has a program to reformat and run. – cdlane Jul 05 '20 at 16:57
  • import turtle as t def p(): print("pressed") def r(): print("released") t.onkeypress(p, '') t.onkeyrelease(r, '') t.listen() t.mainloop() – cdlane Jul 05 '20 at 16:58
  • import turtle as t def p(): t.forward(5) def r(): t.forward(5) t.onkeypress(p, 'p') t.onkeyrelease(r, 'r') t.listen() t.mainloop() – Red Jul 05 '20 at 17:00
  • @cdlane The example you gave me worked, but if i switched the prints to forwards, my case stands. – Red Jul 05 '20 at 17:01
  • Not so for me. I fear this may be one of those tkinter implementation differences between Windows and Unix, like the overlapping fill issue. I avoid press and release questions as everyone sees something different. Sigh. There's no "simply" about it. – cdlane Jul 05 '20 at 17:05
  • But for those who can't test, looking at the documentation seems like `onkey()` is the equivalent of `onkeyrelease`, because there's no documentation for `onkey()`. – Red Jul 05 '20 at 17:08
  • @cdlane Correction - the example you gave me only proved for me my case. I guess I was a bit confused at first. – Red Jul 05 '20 at 17:11
  • `onkeyrelease()` is an alias of `onkey()` as of Python 3 -- same function. Documentation doesn't imply anything about "holding". You can see other folks running into Windows vs. Unix issues in this [SO answer](https://stackoverflow.com/q/27215326/5771269) Did you disable auto repeat? – cdlane Jul 05 '20 at 17:15
  • @cdlane Sorry, things are the same either when I have `os.system('xset r on')` or `os.system('xset r off')`. – Red Jul 05 '20 at 18:32