2012-04-07 2 views
2

Я полностью готов представить идею о том, что мое оборудование является причиной проблемы здесь, однако я честно не думаю, потому что я определенно видел компьютер обрабатывать оба типа ввода одновременно с помощью другого программного обеспечения/игр/и т. д., поэтому я предполагаю, что причиной этого является мой подход к обработчику событий PyGame.Python + PyGame - обработка одновременных событий мыши и клавиатуры

Я случайно обманываю Python и PyGame и просто пытаюсь построить свое знание за один раз и выразить это знание, создав «игру», когда я учусь. Я считаю, что это не так, как если бы вы столкнулись с проблемой обнаружения конфликтов или подсчета очков, я полагаю, что это может произойти позже.

Соответствующая головоломка здесь заключается в том, что в игре будут выполняться события MOUSEMOTION и события KEYDOWN, они просто не хотят обрабатывать их одновременно. Пока объект «игрок» движется, он не может стрелять, а во время съемки он не может двигаться. Поскольку большинство игроков наслаждаются роскошью во время съемок, я вижу это как что-то вроде промаха.

import pygame, random, sys 
from pygame.locals import * 

pygame.init() 

width = 640 
height = 480 


DISPLAYSURF = pygame.display.set_mode((width, height)) 
pygame.display.set_caption('It moves!') 
pygame.mouse.set_visible(0) 



class Player(pygame.sprite.Sprite): 

    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 

     self.x = x 
     self.y = y 
     self.width = 50 
     self.height = 25 
     self.playerRect = None 



    def update(self, event): 
     if event.type == MOUSEMOTION: 
      self.x, self.y = event.pos 


     #get a new playerRect and draw it 
     self.playerRect = pygame.Rect(self.x, self.y, self.width, self.height) 
     pygame.draw.ellipse(DISPLAYSURF, RED, (self.playerRect), 3) 


    def shotcheck(self, event): 
     if event.type == KEYDOWN: 
      if event.key == K_KP8: 
       return (True, 'up') 
      elif event.key == K_KP2: 
       return (True, 'down') 
      elif event.key == K_KP4: 
       return (True, 'left') 
      elif event.key == K_KP6: 
       return (True, 'right') 
      elif event.key == K_KP7: 
       return (True, 'upleft') 
      elif event.key == K_KP1: 
       return (True, 'downleft') 
      elif event.key == K_KP9: 
       return (True, 'upright') 
      elif event.key == K_KP3: 
       return (True, 'downright') 
      else: 
       return (0, 0) 



class Enemy(pygame.sprite.Sprite): 
    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 
     self.x = x 
     self.y = y 
     #self.body = pygame.rect.Rect(self.x, self.y, 15, 15) 
     self.speed = 5 
     self.xmove = 0 
     self.ymove = 0 



    def update(self, event): 
     self.x += self.speed 
     if self.x > 350: 
      self.speed *= -1 
     elif self.x < 25: 
      self.speed *= -1 

     pygame.draw.rect(DISPLAYSURF, BLUE, (self.x, self.y, 15, 15), 4) 



#pass it a directional value when fired based on the key 
#may have to divide speed/2 if moving diagonally 
class Bullet(pygame.sprite.Sprite): 
    def __init__(self, x, y, direction): 
     pygame.sprite.Sprite.__init__(self) 
     self.x = x 
     self.y = y 
     self.direction = direction 
     self.width = 4 
     self.height = 4 
     self.bulletRect = None 
     self.speed = 8 



    def update(self, event): 

     if self.direction == 'up': 
      self.y -= self.speed 

     elif self.direction == 'down': 
      self.y += self.speed 

     elif self.direction == 'left': 
      self.x -= self.speed 

     elif self.direction == 'right': 
      self.x += self.speed 

     elif self.direction == 'upleft': 
      self.x -= (self.speed/2) 
      self.y -= (self.speed/2) 

     elif self.direction == 'downleft': 
      self.x -= (self.speed/2) 
      self.y += (self.speed/2) 

     elif self.direction == 'upright': 
      self.x += (self.speed/2) 
       self.y -= (self.speed/2) 

     elif self.direction == 'downright': 
      self.x += (self.speed/2) 
      self.y += (self.speed/2) 


     self.bulletRect = pygame.Rect(self.x, self.y, 4, 4) 
     pygame.draw.ellipse(DISPLAYSURF, GREEN, (self.bulletRect), 2) 





FPS = 30 
fpsClock = pygame.time.Clock() 


RED = (255, 0, 0) 
GREEN = (0, 255, 0) 
BLUE = (0, 0, 255) 
BLACK = (0, 0, 0) 



ship = Player(width/2, height/2) 
bads = Enemy(width/2, height/2) 



queue = pygame.sprite.Group() 
queue.add(ship) 
queue.add(bads) 


while True: 
    DISPLAYSURF.fill(BLACK) 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      sys.exit() 


     #passes 'event' to everything in the queue and calls 
     #their obj.update(). in this way the gameloop 
     #is a bit more readable 
    for thing in queue: 
     thing.update(event) 

    try: #i'm not married to this bit of code :/ 
     checkForShot, shotDirection = ship.shotcheck(event) 
     if checkForShot: 
      shotx, shoty = ship.playerRect.center 
      shot = Bullet(shotx, shoty, shotDirection) 
      queue.add(shot) 
    except TypeError: 
     pass 

    pygame.display.flip() 
    fpsClock.tick(FPS) 

Я понимаю, что это в основном производит действительно скучный клон Robotron, но, как я сказал, что это малыш проект мой, что я собираю во время работы через учебники в Интернете. Да, на данный момент нет необходимости «импортировать случайные», это будет иметь значение позже.

Я предполагаю, что есть пара зависаний; для начала мне не нравится, как обрабатывается создание пули (объект-плеер должен, на мой взгляд, добавить их в очередь игры, вместо того, чтобы возвращать верный/ложный кортеж, но это казалось неинтуитивным для если объект игрока упоминает о очереди напрямую и обрабатывает его с помощью try/except, чувствует себя ленивым, но, возможно, я критичен). Однако я также чувствую, что эта проблема равнозначна тому, как справляться с тем, как обработать обработчик события правильно. Update() для одновременного перемещения (MOUSEMOTION) и съемки (KEYDOWN).

И я также предполагаю, что для того, чтобы заставить это вести себя более «как можно было бы ожидать», мне нужно сказать, что он также обрабатывал события KEYUP. Тем не менее, я все еще просто заблуждаюсь, почему именно обработчик событий, кажется, выбирает один event.type и игнорирует другого (по моему опыту это было в любом случае на первом месте).

+0

Где код, связанный с событиями ??? Вы только проверяете, если он ВЫХОД, а затем ** игнорируйте ** других! –

+0

Каждый объект обрабатывает свои собственные события более или менее, помещая их в очередь, а затем передает событие «для вещи в очереди: thing.update (event)». может быть, это часть проблемы? Я готов принять это. Но он удерживает реальную игровую петлю, выглядящую красивой и аккуратной, вместо того, чтобы подвергать персональный ответ любому объекту событию в игровом цикле. –

ответ

1

Проверьте это!

import pygame, random, sys 
from pygame.locals import * 

pygame.init() 

width = 640 
height = 480 


DISPLAYSURF = pygame.display.set_mode((width, height)) 
pygame.display.set_caption('It moves!') 
pygame.mouse.set_visible(0) 



class Player(pygame.sprite.Sprite): 

    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 

     self.x = x 
     self.y = y 
     self.width = 50 
     self.height = 25 
     self.playerRect = None 



    def update(self, event): 
     if event.type == MOUSEMOTION: 
      self.x, self.y = event.pos 


     #get a new playerRect and draw it 
     self.playerRect = pygame.Rect(self.x, self.y, self.width, self.height) 
     pygame.draw.ellipse(DISPLAYSURF, RED, (self.playerRect), 3) 


    def shotcheck(self, event): 
     if event.type == KEYDOWN: 
      if event.key == K_KP8: 
       return (True, 'up') 
      elif event.key == K_KP2: 
       return (True, 'down') 
      elif event.key == K_KP4: 
       return (True, 'left') 
      elif event.key == K_KP6: 
       return (True, 'right') 
      elif event.key == K_KP7: 
       return (True, 'upleft') 
      elif event.key == K_KP1: 
       return (True, 'downleft') 
      elif event.key == K_KP9: 
       return (True, 'upright') 
      elif event.key == K_KP3: 
       return (True, 'downright') 
      else: 
       return (0, 0) 



class Enemy(pygame.sprite.Sprite): 
    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 
     self.x = x 
     self.y = y 
     #self.body = pygame.rect.Rect(self.x, self.y, 15, 15) 
     self.speed = 5 
     self.xmove = 0 
     self.ymove = 0 



    def update(self, event): 
     self.x += self.speed 
     if self.x > 350: 
      self.speed *= -1 
     elif self.x < 25: 
      self.speed *= -1 

     pygame.draw.rect(DISPLAYSURF, BLUE, (self.x, self.y, 15, 15), 4) 



#pass it a directional value when fired based on the key 
#may have to divide speed/2 if moving diagonally 
class Bullet(pygame.sprite.Sprite): 
    def __init__(self, x, y, direction): 
     pygame.sprite.Sprite.__init__(self) 
     self.x = x 
     self.y = y 
     self.direction = direction 
     self.width = 4 
     self.height = 4 
     self.bulletRect = None 
     self.speed = 8 



    def update(self, event): 

     if self.direction == 'up': 
      self.y -= self.speed 

     elif self.direction == 'down': 
      self.y += self.speed 

     elif self.direction == 'left': 
      self.x -= self.speed 

     elif self.direction == 'right': 
      self.x += self.speed 

     elif self.direction == 'upleft': 
      self.x -= (self.speed/2) 
      self.y -= (self.speed/2) 

     elif self.direction == 'downleft': 
      self.x -= (self.speed/2) 
      self.y += (self.speed/2) 

     elif self.direction == 'upright': 
      self.x += (self.speed/2) 
       self.y -= (self.speed/2) 

     elif self.direction == 'downright': 
      self.x += (self.speed/2) 
      self.y += (self.speed/2) 


     self.bulletRect = pygame.Rect(self.x, self.y, 4, 4) 
     pygame.draw.ellipse(DISPLAYSURF, GREEN, (self.bulletRect), 2) 





FPS = 30 
fpsClock = pygame.time.Clock() 


RED = (255, 0, 0) 
GREEN = (0, 255, 0) 
BLUE = (0, 0, 255) 
BLACK = (0, 0, 0) 



ship = Player(width/2, height/2) 
bads = Enemy(width/2, height/2) 



queue = pygame.sprite.Group() 
queue.add(ship) 
queue.add(bads) 


while True: 
    DISPLAYSURF.fill(BLACK) 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      sys.exit() 


       #passes 'event' to everything in the queue and calls 
       #their obj.update(). in this way the gameloop 
       #is a bit more readable 
      for thing in queue: 
       thing.update(event) 

    try: #i'm not married to this bit of code :/ 
     checkForShot, shotDirection = ship.shotcheck(event) 
     if checkForShot: 
      shotx, shoty = ship.playerRect.center 
      shot = Bullet(shotx, shoty, shotDirection) 
      queue.add(shot) 
    except TypeError: 
     pass 

    pygame.display.flip() 
    fpsClock.tick(FPS) 

Проблема была в коде, который обрабатывается вытягивать (извлечения их из Pygame). Вы создали цикл, который получает каждое событие. Но тогда вы «обновили» свою игру не со всеми, а с последним одним! Я думаю, что исправления отступов будет достаточно.

+0

Если я отступаю так, как вы предлагаете, я получаю хороший пустой экран, пока не покажусь мышью. :) –

+1

Отдельное обновление() и draw() в каждом объекте !! затем добавьте для вещи в очередь: thing.draw() вместо вашего оригинала. Итак, вы рисуете каждый кадр и обновляете объект на каждом событии! –

+0

И тогда вы поймете, что вы не обновляете движение своей пули! –

Смежные вопросы