Reputation: 55
I want to make a script in python/pygame that will make a character speed up as you hold a movement button (so, when I hold the left key, the character will accelerate to a specific speed and then the speed will even out, when I release the key it will slowly decrease in speed until stopping fully.)
at the moment, my code will recognize that the character must speed up, however the changes in speed only occur every time I press down and release the key (e.g: first key press will have the speed at 1, second press will be two, all the way up to the fifth or sixth press where it's at max speed, before resetting.)
I want to write my code so it means the character will accelerate whilst the key is being held down and not require multiple presses.
here is the movement section (with a few more random bits that were around it) of my code so far:
x = (display_width * 0.45)
y = display_height * 0.8
x_change = 0
negx = 0
posx = 0
bun_speed = 0
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
posx = 0
if negx != -5:
negx = negx - 1
x_change = negx
elif negx == -5:
negx = 0
x_change = -5
elif event.key == pygame.K_RIGHT:
negx = 0
if posx != 5:
posx = posx + 1
x_change = posx
elif posx == 5:
posx = 0
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change = 0
elif event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
display.fill(white)
bunny(x,y)
pygame.display.update()
clock.tick(60)
the two variables negx and posx decrease and increase respectively depending on the key pressed. pressing the key assigned to one variable resets the other to zero, so when that variable is next called when the opposite button is pressed it will accelerate from zero. Once either variable reaches the max speed, it resets for when the button is released meaning the character can accelerate once more.
If there's any way to make this work (as well as neaten up the code, if you're able to) then guidance as to how to get it to function would be much appreciated.
Upvotes: 1
Views: 7135
Reputation: 1
Kevin, what you have mentioned is a key point, but it is a very easy fix, you just need to replace decelerating code with something that checks whether the x_change is positive or negative and then adding or subtracting once you have figured it out.
For example his code is:
if accel_x == 0:
x_change *= 0.92
replace this with something along the lines of:
if accel_x == 0:
if x_change > 0:
x_change -= 0.2
if x_change < 0.2:
x_change = 0
elif x_change < 0:
x_change += 0.2
if x_change > -0.2:
x_change = 0
Upvotes: 0
Reputation: 13
I found another way of accelerating the character. Instead of changing distance, change time. I defined a variable which goes inside pygame.time.delay() and the delay is something I change. This is better because the character does not look like glitching when moving from one place to another.
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("ACCELERATE")
def main():
k = True
thita = 40
x = 250
y = 400
while k:
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
thita = 40
if event.key == pygame.K_RIGHT:
thita = 40
if event.type == pygame.QUIT:
k = False
if keys[pygame.K_LEFT]:
x -= 4
pygame.time.delay(thita)
if thita > 12:
thita -= 1
if keys[pygame.K_RIGHT]:
x += 4
pygame.time.delay(thita)
if thita > 11:
thita -= 1
pygame.draw.rect(win, (255, 0, 0), (x, y, 10, 10))
pygame.display.update()
win.fill((0, 0, 0))
main()
You see the thita goes back to its original value as soon as we lift the key.
Upvotes: 0
Reputation: 20438
Define a variable for the acceleration (accel_x
in the example), set it to the desired value in the event loop and add it to the x_change
every frame to accelerate. To limit the x_change
to the maximum speed, you have to normalize it and multiply it by the max_speed
.
To decelerate the object, you can multiply x_change
with a value below 1 when no key is pressed.
import pygame
pygame.init()
display = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
GRAY = pygame.Color('gray12')
display_width, display_height = display.get_size()
x = display_width * 0.45
y = display_height * 0.8
x_change = 0
accel_x = 0
max_speed = 6
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
# Set the acceleration value.
if event.key == pygame.K_LEFT:
accel_x = -.2
elif event.key == pygame.K_RIGHT:
accel_x = .2
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
accel_x = 0
x_change += accel_x # Accelerate.
if abs(x_change) >= max_speed: # If max_speed is exceeded.
# Normalize the x_change and multiply it with the max_speed.
x_change = x_change/abs(x_change) * max_speed
# Decelerate if no key is pressed.
if accel_x == 0:
x_change *= 0.92
x += x_change # Move the object.
display.fill(GRAY)
pygame.draw.rect(display, (0, 120, 250), (x, y, 20, 40))
pygame.display.update()
clock.tick(60)
pygame.quit()
Upvotes: 3