我完全愿意接受这样的想法,即我的硬件是这里问题的原因,但我并不是真的这么认为,因为我肯定看到计算机使用其他软件同时处理两种输入/游戏/等等,所以我猜这里的错误是我对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处理它感觉很懒,但也许我很关键)。但是我也觉得这个问题无异于弄清楚如何处理事件处理程序正确的thing.update()同时移动(MOUSEMOTION)和射击(KEYDOWN)。
而且我也在猜测,为了让这个行为更像“人们所期望的”,我需要告诉它处理KEYUP事件。但是,我仍然只是为什么事件处理程序似乎选择了一个event.type而忽略了另一个(根据我的经验,它是先出现的那个)。
答案 0 :(得分: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)
问题在于处理pull(从pygame中检索它们)的代码。你做了循环,获得了每一个事件。但是你会“更新”你的游戏状态而不是每个人,但是最后一个!我认为纠正缩进就足够了。