Reputation: 25
I do not have much experience in coding, and I have been stuck on trying to make my character accelerate to a constant speed when key is held and decelerate when key is let go of. I found some code online on it but I cannot seem to properly implement it into mine. If you don't mind it would be helpful if you thoroughly explained the answer so I can properly understand what I am doing wrong.
here is my code
"""Dot Game"""
#Imports
import pygame, sys
#Constants
WIDTH, HEIGHT = 1000, 1000
TITLE = "Dot."
#pygame initialization
pygame.init()
win = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
#fps
FPS = 60
fpsclock = pygame.time.Clock()
#colors
bgc = (247, 226, 222)
pc = (152, 193, 217)
pc2 = (61, 90, 128)
ec = (119, 2, 26)
ec2 = (220, 66, 73)
#accel
x_change = 0
y_change = 0
accel_x = 0
accel_y = 0
max_speed = 6
display_width, display_height = pygame.display.get_surface().get_size()
x = display_width * 0.45
y = display_height * 0.8
#Player Class
class Player:
def __init__(self, x, y):
self.x = int(x)
self.y = int(y)
self.radius = 32
self.width = 2
self.color = pc
self.color2 = pc2
self.velX = 0
self.velY = 0
self.left_pressed = False
self.right_pressed = False
self.up_pressed = False
self.down_pressed = False
self.speed = 3
self.hitbox = (self.x -20, self.y -20, 40, 40)
def draw(self, win):
pygame.draw.circle(win, self.color2, (self.x,self.y), 20)
pygame.draw.circle(win, self.color, (self.x,self.y), 14)
self.hitbox = (self.x -20, self.y -20, 40, 40)
#pygame.draw.rect(win,(255,0,0), self.hitbox,2)
def update(self):
self.velX = 0
self.velY = 0
if self.left_pressed:
self.velX = -self.speed
if self.right_pressed:
self.velX = self.speed
if self.up_pressed:
self.velY = -self.speed
if self.down_pressed :
self.velY = self.speed
self.x += self.velX
self.y += self.velY
self.rect = pygame.Rect(int(self.x), int(self.y), 32, 32)
def collide(self):
print('hit')
pass
#Player Initialization
player = Player(WIDTH/2, HEIGHT/2)
#Main Loop
collide = False
while not collide:
for event in pygame.event.get():
if event.type == pygame.QUIT:
collide == True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
accel_x = -.2
player.left_pressed = True
elif event.key == pygame.K_RIGHT:
accel_x = .2
player.right_pressed = True
elif event.key == pygame.K_UP:
accel_y = -.2
player.up_pressed = True
elif event.key == pygame.K_DOWN:
accel_y = .2
player.down_pressed = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
accel_x = 0
accel_y = 0
player.left_pressed = False
elif event.key == pygame.K_RIGHT:
accel_x = 0
accel_y = 0
player.right_pressed = False
elif event.key == pygame.K_UP:
accel_x = 0
accel_y = 0
player.up_pressed = False
elif event.key == pygame.K_DOWN:
accel_x = 0
accel_y = 0
player.down_pressed = False
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
y_change += accel_y # Accelerate.
if abs(y_change) >= max_speed: # If max_speed is exceeded.
# Normalize the x_change and multiply it with the max_speed.
y_change = y_change/abs(y_change) * max_speed
# Decelerate if no key is pressed.
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
if accel_y == 0:
if y_change > 0:
y_change -= 0.2
if y_change < 0.2:
y_change = 0
elif y_change < 0:
y_change += 0.2
if y_change > -0.2:
y_change = 0
x += x_change # Move the object.
y += y_change
#Draw
win.fill((bgc))
player.draw(win)
#update
player.update()
pygame.display.update()
fpsclock.tick(FPS)
The movement itself works, however there is no acceleration and deceleration
Upvotes: 1
Views: 1282
Reputation: 210909
In your code the speed is always constant because you set self.velX = 0
and self.velY = 0
at the beginning of update
. Therefore the amount of the speed is always 0 or 3.
Do not reset self.velX
and self.velY
. Change the speed with the acceleration, but limit it at the maximum speed. The acceleration must be a small value. As long as a key is pressed, this small value is added to the speed once per frame. This slowly increases the speed to the maximum.
Improve physics by multiplying speed by friction. The value for the friction must be less than 1, or 1 for no friction:
class Player:
def __init__(self, x, y):
# [...]
self.acceleration = 0.1
self.friction = 0.99 # = 1 if you don't want any friction
def update(self):
if self.left_pressed:
if self.velX > -max_speed:
self.velX -= self.acceleration
if self.right_pressed:
if self.velX < max_speed:
self.velX += self.acceleration
if self.up_pressed:
if self.velY > -max_speed:
self.velY -= self.acceleration
if self.down_pressed :
if self.velY < max_speed:
self.velY += self.acceleration
self.x += self.velX
self.y += self.velY
self.velX *= self.friction
self.velY *= self.friction
self.rect = pygame.Rect(int(self.x), int(self.y), 32, 32)
Upvotes: 3