0

I'm trying to make a game and I have a lot of if statements that use keys, and if I want to add or change a key I have to find all of the if statements and change the key variable there, so does Pygame have a keymap/input map like Godot or unity where I can add name and then add keys to that name?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174

2 Answers2

1

For performance reasons make sure that pygame.key.get_pressed() is called only one per frame. e.g.: get the list of keys in the constructor of the class:

class KeyMap():
    def __init__(self):
        self.keys = pygame.key.get_pressed()
    def left(self):
        return self.keys[pygame.K_LEFT] or self.keys[pygame.K_a]
    def right(self):
        return self.keys[pygame.K_RIGHT] or self.keys[pygame.K_d]
    def down(self):
        return self.keys[pygame.K_DOWN] or self.keys[pygame.K_s]
    def up(self):
        return self.keys[pygame.K_UP] or self.keys[pygame.K_w]

Instantiate the object in the application loop. See How can I make a sprite move when key is held down how to effectivel move the object:

while run:
    # [...]

    key_map = KeyMap()
    rect.x += (key_map.right() - key_map.left()) * vel
    rect.y += (key_map.down() - key_map.up()) * vel

    # [...]

Minimal example:

import pygame

pygame.init()
win = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 40, 60)
rect.center = win.get_rect().center
vel = 5

class KeyMap():
    def __init__(self):
        self.keys = pygame.key.get_pressed()
    def left(self):
        return self.keys[pygame.K_LEFT] or self.keys[pygame.K_a]
    def right(self):
        return self.keys[pygame.K_RIGHT] or self.keys[pygame.K_d]
    def down(self):
        return self.keys[pygame.K_DOWN] or self.keys[pygame.K_s]
    def up(self):
        return self.keys[pygame.K_UP] or self.keys[pygame.K_w]

run = True
while run:
    clock.tick(20)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    key_map = KeyMap()
    rect.x += (key_map.right() - key_map.left()) * vel
    rect.y += (key_map.down() - key_map.up()) * vel

    win.fill((0, 0, 0)) 
    pygame.draw.rect(win, (255, 0, 0), rect)
    pygame.display.update()

pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
0

No there is no built-in keymap like Godot/unity. however you can make one, this is how I did it

class KeyMap():
    def __init__(self):
        self.keys = pygame.key.get_pressed()
    def Left(self):
        return self.keys[pygame.K_LEFT] or self.keys[pygame.K_a]
    def Right(self):
        return self.keys[pygame.K_RIGHT] or self.keys[pygame.K_d]
    def Down(self):
        return self.keys[pygame.K_DOWN] or self.keys[pygame.K_s]
    def Up(self):
        return self.keys[pygame.K_UP] or self.keys[pygame.K_d]

this code snippet was from Rabbid76
example code

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • It is a very very bad idea to call `pygame.key.get_pressed()` for each key check separately. – Rabbid76 Sep 24 '22 at 12:46
  • how else would you do it? –  Sep 24 '22 at 13:08
  • I updated my code to match yours –  Sep 24 '22 at 14:09
  • No You instantiate `KeyMap()` 4 times. So `pygame.key.get_pressed()` is called 4 times in every frame. The point is to call `pygame.key.get_pressed()` only once per frame. Saving 1 line of conde does not always make the code better. – Rabbid76 Sep 24 '22 at 14:11
  • You simply copied the code from my answer. What is the point of copying my answer and making your own answer out of it? – Rabbid76 Oct 02 '22 at 07:01