Prevent a player from moving faster than usual by moving in two directions

Question:

I’m messing a bit with pygame, a player can freely move around the screen with WASD and change the direction they are facing with and , the problem is that they can move faster than usual if they hold two keys at once (e.g. W + D, W + A) and I was wondering what should I change to fix this.

import math
import sys

import pygame as pg


class Player:
    def __init__(self):
        self.x, self.y = 400, 300
        self.speed = 7.5
        self.rot_speed = 0.05
        self.angle = math.pi * 1.5

    def movement(self):
        cos = math.cos(self.angle)
        sin = math.sin(self.angle)
        speed_cos = self.speed * cos
        speed_sin = self.speed * sin
        dx, dy = 0, 0

        keys = pg.key.get_pressed()
        if keys[pg.K_w]:
            dx += speed_cos
            dy += speed_sin
        elif keys[pg.K_s]:
            dx -= speed_cos
            dy -= speed_sin
        if keys[pg.K_a]:
            dx += speed_sin
            dy -= speed_cos
        elif keys[pg.K_d]:
            dx -= speed_sin
            dy += speed_cos

        self.x += dx
        self.y += dy

        if keys[pg.K_LEFT]:
            self.angle -= self.rot_speed
        if keys[pg.K_RIGHT]:
            self.angle += self.rot_speed
        self.angle %= math.tau


    def draw(self):
        pg.draw.line(
            screen,
            "yellow",
            (self.x, self.y),
            (
                self.x + 100 * math.cos(self.angle),
                self.y + 100 * math.sin(self.angle),
            ),
            1,
        )
        pg.draw.circle(screen, "green", (self.x, self.y), 15)

pg.init()
screen = pg.display.set_mode((800, 600))
clock = pg.time.Clock()
player = Player()

while True:
    for event in pg.event.get():
        if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
            pg.quit()
            sys.exit()

    screen.fill("black")
    player.movement()
    player.draw()
    pg.display.flip()
    clock.tick(60)
Asked By: qwerty_url

||

Answers:

You need to normalize the movement vector, it will fix the problem of a player moving faster diagonaly, here is the updated code:

def movement(self):
    cos = math.cos(self.angle)
    sin = math.sin(self.angle)
    speed_cos = self.speed * cos
    speed_sin = self.speed * sin
    dx, dy = 0, 0

    keys = pg.key.get_pressed()
    if keys[pg.K_w]:
        dx += speed_cos
        dy += speed_sin
    if keys[pg.K_s]:
        dx -= speed_cos
        dy -= speed_sin
    if keys[pg.K_a]:
        dx += speed_sin
        dy -= speed_cos
    if keys[pg.K_d]:
        dx -= speed_sin
        dy += speed_cos

    magnitude = math.sqrt(dx * dx + dy * dy)
    if magnitude > 0:
        dx /= magnitude
        dy /= magnitude
        self.x += dx * self.speed
        self.y += dy * self.speed

    if keys[pg.K_LEFT]:
        self.angle -= self.rot_speed
    if keys[pg.K_RIGHT]:
        self.angle += self.rot_speed
    self.angle %= math.tau
Answered By: Saxtheowl
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.