I created a code to make my game character jump. I want to input this jump function into my game.
For the code to not be limited to a particular coordinate, I defined o
as a variable to hold the original y
coordinate before jumping. In my game, I will be at multiple different y
coordinates, but if I define it outside I will only be able to jump at a fixed place again. How do I fix this?
import turtle
dx = 1
dy = 1.8
mdy = -1.6
img = r"C:\Users\user\Desktop\python\pg\dragon.gif"
turtle.register_shape(img)
scrn = turtle.Screen()
scrn.tracer(0)
player = turtle.Turtle()
player.penup()
player.shape(img)
player.speed(10)
player.goto(100,-142)
scrn.update()
o=player.ycor() #original y coordinate
def jump():
global dy
ycor = player.ycor()
if ycor > o:
player.sety(ycor + dy)
if ycor > o+100:
dy = mdy
else:
pass
def jump_handler():
if player.ycor() <= o+0.1:
global dy
dy = 1.8
player.sety(o+0.1)
else:
pass
# Set up the event handler for the jump
scrn.listen()
scrn.onkey(jump_handler, "space")
while True:
scrn.update()
jump()
I tried putting it in the function but that wouldn't work, nor does it work in a while loop. I'm unsure as to how to keep it as the original y
coordinate without it getting changed during the function.
I'm not sure if your design will work. There's no need to keep track of the original position. Jumping is usually implemented as follows:
vy
but dy
"direction y" works too).Generally, in most real-time applications, changes to entity positions should never be done outside of the main update loop. This avoids strange OS-specific retrigger behavior.
Make sure to use ontimer
rather than while True:
to run your loop so that it's stable from one machine to the next. (It'd probably be best to integrate a delta time, but for simplicity, I've omitted it).
Here's a quick proof of concept:
from turtle import Screen, Turtle
def on_space_pressed():
global space_pressed
space_pressed = True
def on_space_released():
global space_pressed
space_pressed = False
def tick():
global vy
if space_pressed and player.ycor() <= ground:
vy = jump_velocity
player.sety(player.ycor() + 1)
vy -= gravity
vy = max(min_velocity, vy)
player.sety(player.ycor() + vy)
if player.ycor() <= ground:
player.sety(ground)
vy = 0
screen.update()
screen.ontimer(tick, 1000 // 60)
vx = 0
vy = 0
ground = -100
min_velocity = -25
jump_velocity = 25
gravity = 1
screen = Screen()
screen.tracer(0)
space_pressed = False
screen.onkeypress(on_space_pressed, "space")
screen.onkeyrelease(on_space_released, "space")
screen.listen()
player = Turtle()
player.penup()
player.turtlesize(2, 2)
player.shape("square")
tick()
screen.exitonclick()
Going a step further and adding horizontal movement might look like:
import time
from turtle import Screen, Turtle
last_time = time.perf_counter()
def tick():
global vx, vy, last_time
curr_time = time.perf_counter()
delta = curr_time - last_time
last_time = curr_time
if "space" in keys_pressed and player.ycor() <= ground:
vy = jump_velocity
player.sety(player.ycor() + 1)
vy -= gravity * delta
vy = max(min_velocity, vy)
player.sety(player.ycor() + vy)
if player.ycor() <= ground:
player.sety(ground)
vy = 0
if "Left" in keys_pressed:
vx -= movement_velocity * delta
if "Right" in keys_pressed:
vx += movement_velocity * delta
player.setx(player.xcor() + vx)
vx *= friction
screen.update()
screen.ontimer(tick, 1000 // 60)
vx = 0
vy = 0
ground = -100
friction = 0.8
min_velocity = -25
movement_velocity = 150
jump_velocity = 25
gravity = 50
screen = Screen()
screen.tracer(0)
screen.listen()
def bind(key):
screen.onkeypress(lambda: keys_pressed.add(key), key)
screen.onkeyrelease(lambda: keys_pressed.remove(key), key)
keys = "space", "Left", "Right"
keys_pressed = set()
for key in keys:
bind(key)
player = Turtle()
player.penup()
player.turtlesize(2, 2)
player.shape("square")
tick()
screen.exitonclick()
There are plenty of improvements to make when the program grows, like avoiding loose global variables (move them into a Player
class and drop the global
keyword) and adding functions, left as an exercise to keep the post reasonably scoped.