碰撞不适用于游戏精灵

2024-09-25 02:39:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试为我的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()

我不明白为什么碰撞不起作用。在


Tags: keyrectimageselfeventgetifrandom
1条回答
网友
1楼 · 发布于 2024-09-25 02:39:43

您的问题是spaceshipasteroids类都没有修改它们在update上自己的rects(它们的hitbox),并且它们的x和{}属性与该矩形的位置没有直接或自动的连接。 如果在这两个类的self.rect.topleft = self.x, self.y函数的末尾添加类似update的内容,则它们各自的矩形(也就是说,hitbox)将移动到它们应该位于的位置,而不是停留在它们的初始化位置,在本例中,player和。。。每颗小行星的一些半随机偏移量(我不确定,确切地说,我只是草率地复制了你的代码,然后测试了一堆预感。我很抱歉没有找到问题的确切根源……)

无论如何,简短的回答是,尽管你有一个运行检查每个精灵的x和y位置,但你没有告诉pygame将这个位置应用到hitbox,和{}总是错误的,因为hitbox rect本身从未真正接触过。

self.rect.topleft = self.x, self.y放在每个sprite类的update函数的末尾可以修复它。(请确保此行位于函数的末尾,并且位于def update(self)内的最低缩进级别!)在

编辑

或者,不需要将上述代码添加到update中,您可以将主循环中的player.x = x_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

我会使用update改变的解决方案,因为当玩家接近游戏场的边缘时,这个解决方案很有可能会让你悲伤。还有另一个让你考虑的途径。在

作为建议,您可以将<Sprite>.x和{}重新定义为property,分别是{}和{},这样x和y值就固定在hitbox的左上角。一个二传手,甚至。在

我不确定您将来希望如何使用这些参数;如果您愿意的话,您可以完全消除它们,并使用它们的rect的定位器。值得深思!在

注意事项:

我还假设sprite的所有xy属性都指向其rect框的左上角。如果该点应该在其他地方(例如,中心),那么您可能需要对该代码进行调整,如果您决定使用它。在

相关问题 更多 >