5 python pygame collision-detection sprite rect
我正在尝试为我的Python编程类制作一个太空飞船游戏,我想用来sprite.spritecollideany检查我的玩家精灵spaceship是否与该spriteGroup组中的任何小行星精灵发生碰撞,但无论我做什么,它似乎都不会上班.
这是代码:
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Asteroids and Spaceships")
background = pygame.image.load("background.png")
background = background.convert()
white = 255,255,255
#first I make the asteroids with this class.
class asteroids(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.width = 30
self.height = 30
self.i1 = pygame.image.load("smallasteroid.png")
self.i1 = self.i1.convert()
self.i1.set_colorkey(white)
self.rect = self.i1.get_rect()
self.rect.left = x
self.rect.top = y
self.i2 = pygame.image.load("smallasteroid2.png")
self.i2 = self.i2.convert()
self.i2.set_colorkey(white)
self.rect = self.i2.get_rect()
self.rect.left = x
self.rect.top = y
self.i3 = pygame.image.load("mediumasteroid.png")
self.i3 = self.i3.convert()
self.i3.set_colorkey(white)
self.rect = self.i3.get_rect()
self.rect.left = x
self.rect.top = y
self.current = 0
def render(self, image_num):
if image_num == 1:
self.current = 1
if image_num == 2:
self.current = 2
if image_num == 3:
self.current = 3
def update(self):
if self.current == 1:
screen.blit(self.i1, (self.x,self.y))
self.y += random.randint(7,11)
if self.y > screen.get_height():
self.y = 0
if self.current == 2:
screen.blit(self.i2, (self.x,self.y))
self.y += random.randint(5,9)
if self.y > screen.get_height():
self.y = 0
if self.current == 3:
screen.blit(self.i3, (self.x,self.y))
self.y += random.randint(3,6)
if self.y > screen.get_height():
self.y = 0
#and then this is the class for the spaceship
class spaceship(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.width = 40
self.height = 60
self.image = pygame.image.load("spaceship.png")
self.image = self.image.convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.left = x
self.rect.top = y
def update(self):
screen.blit(self.image,(self.x,self.y))
if self.y > screen.get_height():
self.y = 0
if self.y < screen.get_height()-610:
self.y = screen.get_height()
if self.x > screen.get_width():
self.x = 0
if self.x < screen.get_width()-610:
self.x = screen.get_width()
#main is where I have the game run
def main():
x_ship, y_ship = 0,0
player = spaceship(300,550)
spriteGroup = pygame.sprite.Group() #my asteroid sprites are grouped here
for i in range(25):
image_num = random.randint(0,3)
asteroid = asteroids(random.randint(0,500),random.randint(0, 200))
asteroid.render(image_num)
spriteGroup.add(asteroid)
clock = pygame.time.Clock()
keepGoing = True
while keepGoing:
#this is what I tried to use to check for collisions. I know it's not working but I don't know why.
if pygame.sprite.spritecollideany(player,spriteGroup):
#the program quits on collision.
pygame.quit()
for event in pygame.event.get():
if (event.type == pygame.QUIT):
keepGoing = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
keepGoing = False
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_LEFT):
x_ship = -4
if (event.key == pygame.K_RIGHT):
x_ship = 4
if (event.key == pygame.K_UP):
y_ship = -4
if (event.key == pygame.K_DOWN):
y_ship = 4
if (event.type==pygame.KEYUP):
if (event.key==pygame.K_LEFT):
x_ship = 0
if (event.key==pygame.K_RIGHT):
x_ship = 0
if (event.key==pygame.K_UP):
y_ship = 0
if (event.key==pygame.K_DOWN):
y_ship = 0
player.x += x_ship
player.y += y_ship
screen.blit(background, (0,0))
spriteGroup.clear(screen, background)
player.update()
spriteGroup.update()
clock.tick(50)
pygame.display.flip()
pygame.quit()
main()
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么碰撞不起作用.
你的问题是,并spaceship没有asteroids类修改他们自己rect的(他们的命中箱)update,他们x和y属性没有直接或自动连接到该矩阵的位置.如果你为这两个类添加类似于函数self.rect.topleft = self.x, self.y结尾的东西update,它们各自的rects - 也就是你的hitbox-将移动到它们应该的位置,而不是保留在它们的初始化位置,在这种情况下是( 300550)为player和......一些半随机为每个小行星偏移(我不知道在哪里,究竟,我所做的就是让你的代码的一个草率的再现,然后测试一堆预感我不寻找道歉.问题的确切根源......)
在任何情况下,简短的回答是,虽然你有一个运行检查每个精灵的x和y位置,你没有告诉pygame实际将该位置应用于hitbox,并且sprite.spritecollideany总是Falsey因为hitbox自己从来没有碰过.
将self.rect.topleft = self.x, self.y每个sprite类的update函数放在最后将修复它.(确保此行位于函数的末尾且处于最低的缩进级别def update(self)!)
编辑
或者,update您可以使用以下内容替换player.x = x_ship并player.y = y_ship在主循环中替换上述代码:
while keepGoing:
...
player.rect.move_ip(x_ship, y_ship) # move the ship's rect
player.x, player.y = player.rect.topleft # update it's x and y, if you use these elsewhere
for item in spriteGroup: # update the rects for your asteroid objects
item.rect.topleft = item.x, item.y
Run Code Online (Sandbox Code Playgroud)
我会使用update-altering解决方案,因为当玩家接近游戏区域的边缘时,这个解决方案很可能会让你感到悲伤.仍然是你要考虑的另一种途径.
作为一个建议,你可以重新定义<Sprite>.x,并<Sprite>.y为propertys表示return self.rect.left,并return self.rect.top分别使x和y的值都寄托于你的击中格的左上.也是一个二传手.
我不确定您将来如何使用这些参数; 如果你愿意的话,你可能完全消除它们,rect而是使用它们的定位器.值得深思!
一张纸条:
我还假设你的所有精灵x和y属性都指向它的rect方框的左上角.如果该点应该在其他地方(例如中心),那么如果您决定使用它,则可能需要对此代码进行调整.
| 归档时间: |
|
| 查看次数: |
1338 次 |
| 最近记录: |