2016-08-08 46 views
0

Ich erstelle ein sehr einfaches Spiel mit der Pygame-Bibliothek, in der der Spieler mit den Pfeiltasten ein Quadrat um den Bildschirm bewegt. Leider erweist sich die Reaktion der Kontrollen als Problem.Optimierung der Tastatureingabe in Pygame

Die Kontrollen funktionieren gut, bis Sie Richtung z. links nach rechts. Wenn der Spieler die Richtung wechselt, hält der Spieler die Gläser zum Stillstand.

Der Code für die Kontrollen wie dies in meinem Spiel aussieht:

def move(self, event): 
    speed = 6 
    if event.type == pygame.KEYDOWN: 
     if event.key == pygame.K_LEFT: 
      self.rect.x -= speed 
     if event.key == pygame.K_RIGHT: 
      self.rect.x += speed 
     if event.key == pygame.K_DOWN: 
      self.rect.y += speed 
     if event.key == pygame.K_UP: 
      self.rect.y -= speed 

Diese Methode in einer Klasse befindet genannt-Block (Ich habe Block von der pygame docs), die für den Spieler einen Sprit neben macht einfach Bereitstellung von Bewegung.

while going: 
    clock.tick(60) 

    # event handling 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      going = False 

    # controller input 
    player.move(event) 

Wo Spieler ist eine Instanz der Block-Klasse und Event ist nur ein Element aus der Ereigniswarteschlange meines Spiels:

Die Funktion move() wird tatsächlich in der main.py Datei wie folgt aufgerufen .

Ich versuchte mit der pygame.key.get_pressed -Funktion (die funktioniert besser), aber ich würde lieber die Ortsnamen pygame.KEYDOWN alternativ, weil es die Taste drücken als Ereignisse in der Ereigniswarteschlange zurückgegeben, anstatt Booleans von einer Liste zurückgegeben .

Wenn Sie mehr investigative als ein durchschnittlicher joe sind, können Sie einen Blick auf das „voll“ Spiel nehmen hier: https://github.com/catmes/Project_React

Sie werden 2.7 pygame 1.9.2 und Python benötigen. Denken Sie daran, dass das Spiel selbst eher eine Lernübung ist, also wundern Sie sich nicht, wenn Sie schlechten Code sehen (der später natürlich behoben wird;)).

Vielen Dank für Ihren Besuch und geben Sie dieser Frage einen Blick, ich schätze Ihre Zeit.

Antwort

0

Ich habe einen glatten Weg ausprobiert, um einen Spieler zu bewegen, der ziemlich gut funktioniert. Es verfolgt im Wesentlichen die Tastenbetätigungen in einer Liste und verschiebt den Spieler basierend auf der zuletzt gedrückten Taste. Wenn Sie eine Taste drücken, wird eine Geschwindigkeit Variable an der ersten Position in der Liste hinzugefügt, und wenn Sie den Schlüssel loslassen, wird diese Variable entfernt. In der update Methode fügen Sie die erste Geschwindigkeitsvariable der Liste zum entsprechenden x- und y-Wert hinzu.

import pygame 
pygame.init() 

screen = pygame.display.set_mode((720, 480)) 

class Player(pygame.sprite.Sprite): 

    def __init__(self): 
     super(Player, self).__init__() 
     self.rect = pygame.Rect((0, 0), (32, 32)) 
     self.image = pygame.Surface((32, 32)) 
     self.image.fill((255, 255, 255)) 
     self.velocity = [0, 0] # It's current velocity. 
     self.speed = 4 # The speed the player will move. 
     self.dx = [] # Keeps track of the horizontal movement. 
     self.dy = [] # Keeps track of the vertical movement. 

    def update(self): 
     try: 
      self.rect.x += self.dx[0] # Index error if the list is empty. 
     except IndexError: 
      self.rect.x += 0 
     try: 
      self.rect.y += self.dy[0] # Index error if the list is empty. 
     except IndexError: 
      self.rect.y += 0 

player = Player() 
while True: 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      raise SystemExit 
     elif event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_a: 
       player.dx.insert(0, -player.speed) 
      elif event.key == pygame.K_d: 
       player.dx.insert(0, player.speed) 
      elif event.key == pygame.K_w: 
       player.dy.insert(0, -player.speed) 
      elif event.key == pygame.K_s: 
       player.dy.insert(0, player.speed) 
     elif event.type == pygame.KEYUP: 
      if event.key == pygame.K_a: 
       player.dx.remove(-player.speed) 
      elif event.key == pygame.K_d: 
       player.dx.remove(player.speed) 
      elif event.key == pygame.K_w: 
       player.dy.remove(-player.speed) 
      elif event.key == pygame.K_s: 
       player.dy.remove(player.speed) 

    player.update() 
    screen.fill((0, 0, 0)) 
    screen.blit(player.image, player.rect) 
    pygame.display.update() 

    # print player.dx, player.dy # Uncomment to see what's happening in action! 
+0

Das funktioniert wunderbar! Ich danke dir sehr. Ich wurde versucht, den Zustand der Schlüssel zu halten, die freigegeben wurden, um zu sehen, ob das die Kontrollen optimieren würde, aber nichts in dem Maße, wie Sie es getan haben. Prost! – kitofkat

+0

Ich war eigentlich neugierig, wie Sie Ihre __init__ Funktion in der Player-Klasse definiert haben; Gibt es einen bestimmten Grund, warum Sie super() zu inhärent verwenden, wenn Sie zuvor eine __init__ Funktion in der Player-Klasse definiert haben? – kitofkat

+0

Ich verstehe deine Frage nicht ganz. Ich habe 'super (Player, self) .__ init __() 'benutzt, um die * superclass *' pygame.sprite.Sprite' zu ​​initialisieren. Dazu ist es nicht notwendig, aber es ist eine gute Übung, alle sichtbaren Klassen zu einer Unterklasse der Sprite-Klasse zu machen, sodass Sie Ihre Spielobjekte zu "pygame.sprite.Group" hinzufügen und einige nützliche Methoden nutzen können. (http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group) –