我找不到如何构建良好的 pygame 碰撞系统
I cant find how to build a good pygame collision system
所以我的碰撞有问题。我的代码有点古怪,因为它用于 2 天的 gamejam,我还没有对它进行排序。所以我希望代码在蜂蜜接触播放器时打印一些东西。我可以从那里开始工作。这是代码
我会附上图片enter image description here
import pygame
from pygame.locals import *
from random import randint
pygame.init()
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
#game variables
screen_width = 720
screen_height = 484
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
honeySpeed = 6
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.img = beeImg
self.rect = self.img.get_rect()
self.rect.center = [x, y]
self.x = x
self.y = y
def draw(self):
#DRAWING
screen.blit(self.img, (self.x, self.y))
# MOVEMENT
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
player.x -= player.speed
elif key_input[pygame.K_RIGHT]:
player.x += player.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect()
self.rect.center = [x,y]
def update(self):
screen.blit(self.image, (self.x,self.y))
self.y += 5
if self.y > screen_height:
self.kill()
player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)
running = True
run = True
while run:
clock.tick(fps)
time_now = pygame.time.get_ticks()
if time_now - last_hun > hun_frequency:
newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
honeyGroup.add(newHoney)
last_hun = time_now
#draw pics
screen.blit(bgImg,(0,0))
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
if hits:
print("touched")
player.draw()
#newHoney.draw()
honeyGroup.draw(screen)
honeyGroup.update()
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
if hits:
print("touched")
#event controll
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
我推荐使用 (see also ). All you need to do is to use pygame.sprite.collide_mask()
:
Tests for collision between two sprites, by testing if their bitmasks overlap (uses pygame.mask.Mask.overlap()
). If the sprites have a mask
attribute, it is used as the mask, otherwise a mask is created from the sprite's image
.
代码更改:
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
但是,参见 How do I detect collision in pygame? and Making and using pygame sprites。 'rect' 和 image
(不是 img
)属性用于碰撞检测。您需要更新矩形的位置。您根本不需要 x
和 y
属性。使用 rect.x
和 rect.y
:
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.image = beeImg
self.rect = self.image.get_rect(center = (x, y))
def draw(self):
screen.blit(self.image, self.rect)
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
self.rect.x -= self.speed
elif key_input[pygame.K_RIGHT]:
self.rect.x += self.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect(center = (x, y))
def update(self):
screen.blit(self.image, self.rect)
self.rect.y += 5
if self.rect.y > screen_height:
self.kill()
完整示例:
import pygame
from pygame.locals import *
from random import randint
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.image = beeImg
self.rect = self.image.get_rect(center = (x, y))
def update(self):
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
self.rect.x -= self.speed
elif key_input[pygame.K_RIGHT]:
self.rect.x += self.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect(center = (x, y))
def update(self):
self.rect.y += 5
if self.rect.y > screen_height:
self.kill()
pygame.init()
#game variables
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
honeySpeed = 6
screen_width = 720
screen_height = 484
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
time_now = pygame.time.get_ticks()
if time_now - last_hun > hun_frequency:
newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
honeyGroup.add(newHoney)
last_hun = time_now
#draw pics
honeyGroup.update()
player.update()
hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
if hits:
print(f"touched")
hits[0].kill()
screen.blit(bgImg,(0,0))
honeyGroup.draw(screen)
playerGroup.draw(screen)
pygame.display.update()
pygame.quit()
所以我的碰撞有问题。我的代码有点古怪,因为它用于 2 天的 gamejam,我还没有对它进行排序。所以我希望代码在蜂蜜接触播放器时打印一些东西。我可以从那里开始工作。这是代码
我会附上图片
import pygame
from pygame.locals import *
from random import randint
pygame.init()
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
#game variables
screen_width = 720
screen_height = 484
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
honeySpeed = 6
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.img = beeImg
self.rect = self.img.get_rect()
self.rect.center = [x, y]
self.x = x
self.y = y
def draw(self):
#DRAWING
screen.blit(self.img, (self.x, self.y))
# MOVEMENT
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
player.x -= player.speed
elif key_input[pygame.K_RIGHT]:
player.x += player.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect()
self.rect.center = [x,y]
def update(self):
screen.blit(self.image, (self.x,self.y))
self.y += 5
if self.y > screen_height:
self.kill()
player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)
running = True
run = True
while run:
clock.tick(fps)
time_now = pygame.time.get_ticks()
if time_now - last_hun > hun_frequency:
newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
honeyGroup.add(newHoney)
last_hun = time_now
#draw pics
screen.blit(bgImg,(0,0))
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
if hits:
print("touched")
player.draw()
#newHoney.draw()
honeyGroup.draw(screen)
honeyGroup.update()
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
if hits:
print("touched")
#event controll
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
我推荐使用pygame.sprite.collide_mask()
:
Tests for collision between two sprites, by testing if their bitmasks overlap (uses
pygame.mask.Mask.overlap()
). If the sprites have amask
attribute, it is used as the mask, otherwise a mask is created from the sprite'simage
.
代码更改:
hits = pygame.sprite.spritecollide(player, honeyGroup, False)
hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
但是,参见 How do I detect collision in pygame? and Making and using pygame sprites。 'rect' 和 image
(不是 img
)属性用于碰撞检测。您需要更新矩形的位置。您根本不需要 x
和 y
属性。使用 rect.x
和 rect.y
:
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.image = beeImg
self.rect = self.image.get_rect(center = (x, y))
def draw(self):
screen.blit(self.image, self.rect)
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
self.rect.x -= self.speed
elif key_input[pygame.K_RIGHT]:
self.rect.x += self.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect(center = (x, y))
def update(self):
screen.blit(self.image, self.rect)
self.rect.y += 5
if self.rect.y > screen_height:
self.kill()
完整示例:
import pygame
from pygame.locals import *
from random import randint
class Bee(pygame.sprite.Sprite):
def __init__(self, x, y, alive, speed, score):
pygame.sprite.Sprite.__init__(self)
self.alive = alive
self.speed = speed
self.score = score
self.image = beeImg
self.rect = self.image.get_rect(center = (x, y))
def update(self):
key_input = pygame.key.get_pressed()
if key_input[pygame.K_LEFT]:
self.rect.x -= self.speed
elif key_input[pygame.K_RIGHT]:
self.rect.x += self.speed
class Honey(pygame.sprite.Sprite):
def __init__(self, x, y,speed):
pygame.sprite.Sprite.__init__(self)
self.speed = speed
self.image = honeyImg
self.image = pygame.transform.scale(honeyImg, (60,60))
self.rect = self.image.get_rect(center = (x, y))
def update(self):
self.rect.y += 5
if self.rect.y > screen_height:
self.kill()
pygame.init()
#game variables
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
honeySpeed = 6
screen_width = 720
screen_height = 484
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
time_now = pygame.time.get_ticks()
if time_now - last_hun > hun_frequency:
newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
honeyGroup.add(newHoney)
last_hun = time_now
#draw pics
honeyGroup.update()
player.update()
hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
if hits:
print(f"touched")
hits[0].kill()
screen.blit(bgImg,(0,0))
honeyGroup.draw(screen)
playerGroup.draw(screen)
pygame.display.update()
pygame.quit()