1

I want to code my own Tetris. The goal is to get as close as possible to this game: https://jstris.jezevec10.com/?play=1&mode=1

I don't know if I google the wrong things but I couldn't find a satisfying answer.

The problem: the pieces can move left and right with the arrows. If the player presses the key once, the piece should move by 1 to the left or right. Now I want to implement that after a certain time (t > 133ms - default setting jstris) the piece should move directly to the side of the screen. It would be more of a keyhold than a keypress event.

1)

if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_LEFT:
        piece.x -= 1

If done like this the player is not able to hold the left arrow. He has to press it over and over again to get to the side of the screen.

2)

keys = pygame.key.get_pressed()
    
    if keys[pygame.K_LEFT]:
        piece.x -= 1

In this solution the goal to get a constantly moving piece to the side is achieved, BUT it is nearly impossible to only move the piece by 1. To handle this I would have to set a low fps to get control whether to move by 1 or more but that is a really bad solution. It slows down the game speed a lot and feels like lagging.

So here is the question: Is it possible to move the piece by 1 if the key is pressed but check live if it is pressed longer than t>133ms. If true the piece should move instantly to the wall. In tetris it is called Auto delayed shift (DAS). It would be a mix of 1) and 2) decided by a measured time.

Before posting here I read a lot about measuring time of the duration of a keypress or between events but here I don't have KEYDOWN and KEYUP to measure the time between them because the KEYUP event doesn't even exist when the game needs to decide what to do.

Do i maybe need to get out of pygame and search after other modules to get to my goal or am I missing something ?

Thanks for your help!

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Rabinzel
  • 7,757
  • 3
  • 10
  • 30

2 Answers2

1

You need to look for the button for a certain amount of time after you press it. Use pygame.time.get_ticks() to get the number of milliseconds since pygame.init() was called. Calculate the time at which the button can be pressed the next time after pressing. Discard pressing the key if the point in time has not yet been reached:

next_key_left_time = 0

# application loop
while True:
    current_time = pygame.time.get_ticks()

    # [...]

    keys = pygame.key.get_pressed()
    
    if keys[pygame.K_LEFT] and current_time >= next_key_left_time:
        piece.x -= 1
        next_key_left_time = current_time + 133 # 133 milliseconds

    # [...]

pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement. Therefore, you can hold the key down and the block will move one step every 0.133 seconds.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • @Rabinzel No. Why do you not try it? You can hold down the button. My solution uses `pygame.key.get_pressed()`, not `pygame.KEYDOWN`! – Rabbid76 Sep 27 '21 at 10:09
  • 1
    true true. You were right. It works. Thanks a lot! I think that will bring me to the goal! The only thing I need to change is, the block should only wait once for 0.133 seconds and then instantly jump to the side of the screen. But that shouldn't be a problem now. – Rabinzel Sep 27 '21 at 10:18
1

You can use pygame.key.set_repeat docs to make KEYDOWN events repeat while the key is held down.

Try putting the following at the beginning of your program:

KEY_DELAY = 100
KEY_INTERVAL = 50
pygame.key.set_repeat(KEY_DELAY, KEY_INTERVAL)

The tetris piece will move a second time if you keep a key pressed for 100 milliseconds, then again after 50. Adjust the values as needed.

mousetail
  • 7,009
  • 4
  • 25
  • 45
  • This is even a better solution for my purpose. Just implemented it and it is even more simple than with pygame.key.get_pressed() and I have two different parameters I can set instead of one. Thanks a lot ! – Rabinzel Oct 05 '21 at 21:59