Hoe krijg je toetsenbordinvoer in Pygame?

Ik maak een spel in Pygame 1.9.2.
Het is een faily simpele game waarin een schip tussen vijf kolommen van slechteriken beweegt die aanvallen door langzaam naar beneden te bewegen. Ik probeer het te maken, zodat het schip naar links en rechts gaat met de linker- en rechterpijltoetsen. Hier is mijn code:

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
    location-=1
    if location==-1:
        location=0
if keys[K_RIGHT]:
    location+=1
    if location==5:
        location=4

Het werkt te goed. Het schip beweegt te snel. Het is bijna onmogelijk om het slechts één locatie, links of rechts te laten bewegen. Hoe kan ik het maken, zodat het schip slechts één keer verplaatst wanneer de sleutel wordt ingedrukt?


Antwoord 1, Autoriteit 100%

U kunt de gebeurtenissen van Pygame krijgen en dan opzoeken voor de KEYDOWNEvenement, in plaats van naar de sleutels te kijken die zijn geretourneerd door get_pressed()(wat u sleutels geeft zijn momenteel ingedrukt, terwijl de KEYDOWN-evenement u laat zien welke toetsen op die frame zijn ingedrukt.

Wat gebeurt er met uw code nu, is dat als uw spel wordt weergegeven op 30 fps, en u de linker pijltoets gedurende een halve seconde ingedrukt houdt, u de locatie 15 keer bijwerkt.

events = pygame.event.get()
for event in events:
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            location -= 1
        if event.key == pygame.K_RIGHT:
            location += 1

Om continue beweging te ondersteunen terwijl een toets wordt ingedrukt, zou je een soort beperking moeten instellen, ofwel op basis van een geforceerde maximale framesnelheid van de spellus of door een teller waarmee je slechts om de zoveel tijd kunt bewegen tikken van de lus.

move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
    if move_ticker == 0:
        move_ticker = 10
        location -= 1
        if location == -1:
            location = 0
if keys[K_RIGHT]:
    if move_ticker == 0:   
        move_ticker = 10     
        location+=1
        if location == 5:
            location = 4

Dan zou je ergens tijdens de spellus zoiets als dit doen:

if move_ticker > 0:
    move_ticker -= 1

Hiermee kun je maar één keer per 10 frames bewegen (dus als je beweegt, wordt de ticker ingesteld op 10, en na 10 frames kun je weer bewegen)


Antwoord 2, autoriteit 11%

import pygame
pygame.init()
pygame.display.set_mode()
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit(); #sys.exit() if sys is imported
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_0:
                print("Hey, you pressed the key, '0'!")
            if event.key == pygame.K_1:
                print("Doing whatever")

Houd er rekening mee dat K_0 en K_1 niet de enige sleutels zijn, om ze allemaal te zien, zie pygame-documentatie, anders druk je op tabna het intypen

pygame.

(let op de . na pygame) in een inactief programma. Merk op dat de K hoofdletter moet zijn. Merk ook op dat als je pygame geen weergavegrootte geeft (geen argumenten doorgeeft), het automatisch de grootte van het computerscherm/monitor zal gebruiken. Veel plezier met coderen!


Antwoord 3, autoriteit 11%

pygame.key.get_pressed()retourneert een lijst met de status van elke sleutel. Als een toets wordt ingedrukt, is de status van de toets True, anders False. Gebruik pygame.key.get_pressed()om de huidige status van een knop te evalueren en continue beweging te krijgen:

while True:
    keys = pygame.key.get_pressed()
    x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
    y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed

De toetsenbordgebeurtenissen (zie de module pygame.event) komen slechts één keer voor wanneer de status van een sleutel verandert. De gebeurtenis KEYDOWNvindt één keer plaats telkens wanneer een toets wordt ingedrukt. KEYUPvindt één keer plaats telkens wanneer een toets wordt losgelaten. Gebruik de toetsenbordgebeurtenissen voor een enkele actie of beweging:

while True:
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x -= speed
            if event.key == pygame.K_RIGHT:
                x += speed
            if event.key == pygame.K_UP:
                y -= speed
            if event.key == pygame.K_DOWN:
                y += speed

Zie ook Toetsen- en toetsenbordgebeurtenis


Minimaal voorbeeld van continue beweging: replit.com/@Rabbid76/PyGame-ContinuousMovement

import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            print(pygame.key.name(event.key))
    keys = pygame.key.get_pressed()
    rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
    rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
    rect.centerx = rect.centerx % window.get_width()
    rect.centery = rect.centery % window.get_height()
    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), rect)
    pygame.display.flip()
pygame.quit()
exit()

Minimaal voorbeeld voor een enkele actie: replit.com/@Rabbid76/PyGame-ShootBullet

import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
    clock.tick(60)
    current_time = pygame.time.get_ticks()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            bullet_list.insert(0, tank_rect.midright)
    for i, bullet_pos in enumerate(bullet_list):
        bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
        if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
            del bullet_list[i:]
            break
    window.fill((224, 192, 160))
    window.blit(tank_surf, tank_rect)
    for bullet_pos in bullet_list:
        window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
    pygame.display.flip()
pygame.quit()
exit()

Antwoord 4, autoriteit 2%

Ik denk dat je het volgende kunt gebruiken:

pygame.time.delay(delayTime)

waarin delayTimein milliseconden is.

Zet het voor evenementen.


Antwoord 5

De reden hierachter is dat het pygame-venster werkt met 60 fps (frames per seconde) en wanneer je de toets ongeveer 1 seconde indrukt, worden 60 frames bijgewerkt volgens de lus van het gebeurtenisblok.

clock = pygame.time.Clock()
flag = true
while flag :
    clock.tick(60)

Merk op dat als je animatie in je project hebt, het aantal afbeeldingen het aantal waarden in tick()bepaalt. Laten we zeggen dat je een personage hebt en het vereist 20 sets afbeeldingen om te lopen en te springen, dan moet je tick(20)maken om het personage op de juiste manier te verplaatsen.


Antwoord 6

Probeer dit:

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
    if count == 10:
        location-=1
        count=0
    else:
        count +=1
    if location==-1:
        location=0
if keys[K_RIGHT]:
    if count == 10:
        location+=1
        count=0
    else:
        count +=1
    if location==5:
        location=4

Dit betekent dat je maar 1/10 van de tijd beweegt. Als het nog steeds te snel beweegt, kun je proberen de waarde die je instelt op “count” ook te verhogen.


Antwoord 7

Typisch, als je probeert ervoor te zorgen dat het schip niet van het scherm verdwijnt met

location-=1
if location==-1:
    location=0

die je waarschijnlijk beter kunt gebruiken

location -= 1
location = max(0, location)

Op deze manier gaat je programma niet kapot als het -1 overslaat


Antwoord 8

Je moet clock.tick(10)gebruiken zoals vermeld in de docs.


Antwoord 9

Alle antwoorden hierboven zijn te complexiceerd, ik zou de variabelen gewoon met 0,1 wijzigen in plaats van 1
Dit maakt het schip 10 keer langzamer
Als dat nog steeds te snel is, verander de variabelen met 0.01
Dit maakt het schip 100 keer langzamer
Probeer dit

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
    location -= 0.1 #or 0.01
    if location==-1:
    location=0
if keys[K_RIGHT]:
    location += 0.1 #or 0.01
    if location==5:
        location=4

Antwoord 10

Gebruik uw spel, gebruik pygame.clock.tick(10)

Other episodes