微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试在pygame中实现碰撞时,pygame.sprite.groupcollide不起作用

如何解决尝试在pygame中实现碰撞时,pygame.sprite.groupcollide不起作用

我正在做一个蛇游戏项目,我不能使蛇和食物发生碰撞。阅读一些Pygame文档后,我决定使用pygame.sprite.groupcollide进行碰撞。我的游戏中有两种精灵:

  1. 食物

pygame.sprite.groupcollide在我以前的游戏(一本Python书中的Alien Invasion游戏)中工作过;但是,由于某种原因,它在我当前的游戏中不起作用。您认为可能是什么原因?这是碰撞部分(snake_game.py)的亮点:

def _check_snake_food_collisions(self):
        '''Check the collisions between the snake and foods.'''
        collisions = pygame.sprite.groupcollide(self.foods,self.snake_parts,True,False)

这是我的代码

snake_game.py

import pygame
import sys

from random import randint

from settings import Settings 
from snake import Snake
from food import Food 

class SnakeGame:
    '''The main class of the game.'''

    def __init__(self):
        '''Initialize the game assets,screen,etc.'''
        pygame.init()
        self.settings = Settings()
        
        self.screen = pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height))
        pygame.display.set_caption("Snake Game")

        self.snake_parts = pygame.sprite.Group() #Will do some refactoring here.
        self.snake_part = Snake(self)  # Will move this part elsewhere.
        self.snake_parts.add(self.snake_part)
        
        self.foods = pygame.sprite.Group()
        self.food = Food(self)          # Will do some refactoring here as well.
        self.foods.add(self.food)       # Will move this part elsewhere.
       
    def run_game(self):
        '''The main loop of the game.'''
        while True:
            self._check_events()
            self._update_snake_parts()
            self._update_screen()

    def _check_events(self):
        '''Check all the events.'''
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self,event):
        '''Check keydown events.'''
        if event.key == pygame.K_UP or event.key == pygame.K_w:
            self.snake_part.m_up = True
        elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
            self.snake_part.m_down = True
        elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
            self.snake_part.m_left = True
        elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
            self.snake_part.m_right = True
        elif event.key == pygame.K_q:
            sys.exit()

    def _check_keyup_events(self,event):
        '''Check keyup events.'''
        if event.key == pygame.K_UP or event.key == pygame.K_w:
            self.snake_part.m_up = False
        elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
            self.snake_part.m_down = False
        elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
            self.snake_part.m_left = False
        elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
            self.snake_part.m_right = False

    def _check_snake_food_collisions(self):
        '''Check the collisions between the snake and foods.'''
        collisions = pygame.sprite.groupcollide(self.foods,False)
      
    def _update_snake_parts(self):
        '''Update all the parts of the snake.'''
        self.snake_parts.update()
        
    def _update_screen(self):
        '''Update the screen.'''
        self.screen.fill(self.settings.bg_color)

        # Draw snake parts to the screen.
        for snake_part in self.snake_parts.sprites():
            snake_part.draw_part()

        # Draw foods to the screen.
        self.food.draw_food()

        pygame.display.flip()

if __name__ == '__main__':
    sg = SnakeGame()
    sg.run_game()

snake.py

import pygame
import sys

from pygame.sprite import Sprite 

class Snake(Sprite):
    '''A class to manage the snake.'''

    def __init__(self,sg):
        '''Initialize the snake's location,size,etc.'''
        super().__init__()
        self.screen = sg.screen
        self.settings = sg.settings
        self.color = self.settings.snake_color
        self.screen_rect = self.screen.get_rect()
        
        # Create the snake's rect object and position it.
        self.rect = pygame.Rect(0,self.settings.snake_width,self.settings.snake_height)
        self.rect.center = self.screen_rect.center

        # Get the precise coordinates of the snake.
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

        # Set movement flags.
        self.m_right = False
        self.m_left = False
        self.m_up = False
        self.m_down = False

    def update(self):
        '''Update the position of the snake.'''
        if self.m_right and self.rect.right < self.screen_rect.right:                    
            self.x += self.settings.snake_speed
        if self.m_left and self.rect.left > self.screen_rect.left:
            self.x -= self.settings.snake_speed
        if self.m_down and self.rect.bottom < self.screen_rect.bottom:
            self.y += self.settings.snake_speed
        if self.m_up and self.rect.top > self.screen_rect.top:
            self.y -= self.settings.snake_speed

        self.rect.x = self.x
        self.rect.y = self.y
        
    def draw_part(self):
        '''Draw the snake to the screen.'''
        pygame.draw.rect(self.screen,self.color,self.rect)

food.py

import pygame

from random import randint
from pygame.sprite import Sprite 

class Food(Sprite):
    '''A class to manage the foods.'''

    def __init__(self,sg):
        '''Initialize the food rect,food color,and other assets.'''
        super().__init__()
        self.screen = sg.screen
        self.settings = sg.settings
        self.color = self.settings.food_color
        
        self.rect = pygame.Rect(0,self.settings.food_width,self.settings.food_height)

        # Initialize the food at a random position.
        self.spawn_food()
    
    def spawn_food(self):
        '''Position the food at a random position.'''
        self.rect.x = randint(0,self.settings.screen_width - 
                        self.settings.food_width) 
        self.rect.y = randint(0,self.settings.screen_height - 
                        self.settings.food_height) 

    def draw_food(self):
        '''Draw the food to the screen.'''
        pygame.draw.rect(self.screen,self.rect)

settings.py

class Settings:
    '''Class for game settings.'''

    def __init__(self):
        '''Initialize the game settings.'''

        # Screen settings
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (119,181,254)  # Blue color

        # Snake settings
        self.snake_width = 20
        self.snake_height = 20
        self.snake_color = (255,255,0)  # Yellow color
        self.snake_speed = 1

        # Food settings
        self.food_width = 10
        self.food_height = 10
        self.food_color = (139,69,19)  # brown color

解决方法

阅读pygame.sprite.groupcollide的文档:

[...]如果任何一个dokill参数为True,则将碰撞的Sprite从其各自的组中删除。

这样做的时候

collisions = pygame.sprite.groupcollide(self.foods,self.snake_parts,True,False)

,检测到碰撞,并从Group self.foods中取出了食物。 但是,self.food属性仍然引用Food对象。

食物在 Group 中,直到检测到碰撞为止。因此,您必须在 Group self.foods中绘制对象,而不是Sprite对象self.food。您甚至不需要self.food属性。如果所有Food对象都包含在self.foods中,就足够了:

self.food.draw_food()

for food in self.foods.sprites():
    food.draw_food()

请注意,您的代码实际上并未调用_check_snake_food_collisions

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。