ハードウェアがここでの問題の原因であるという考えに完全に同意しますが、コンピューターが他のソフトウェア/ゲーム/などを使用して両方の種類の入力を同時に処理するのを確実に見たので、正直にそうは思いません、したがって、ここでの障害は、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 クローンを生成することは承知していますが、私が言ったように、これはオンラインのチュートリアルを実行しながらまとめている私の幼児プロジェクトです。はい、今のところ不必要な「ランダムなインポート」があります。後で問題になります。
いくつかのハングアップがあると思います。手始めに、弾丸の作成が処理される方法が好きではありません (プレイヤー オブジェクトは、True/False タプルを返すのではなく、弾丸をゲーム キュー自体に追加する必要がありますが、直感的ではないように思えました)。プレーヤー オブジェクトにキューを直接言及させて、try/except でそれを処理するのは怠惰に感じますが、私は批判的かもしれません)。ただし、この問題は、同時に移動 (MOUSEMOTION) と射撃 (KEYDOWN) のためにイベント ハンドラーを適切に thing.update() にする方法を理解することと同じだとも感じています。
また、これを「予想どおり」に動作させるには、KEYUPイベントも処理するように指示する必要があると推測しています。ただし、イベントハンドラーが 1 つの event.type を選択し、もう一方を無視するように見える理由については、まだ困惑しています (私の経験では、どちらが先に来ても)。