碰撞检测不适用于pygame
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了碰撞检测不适用于pygame相关的知识,希望对你有一定的参考价值。
我正在制作游戏,我遇到了碰撞检测问题。我正在结束等级块,但它无法检测到玩家是否站在它上面以更改为等级2.该块的碰撞检测在player.updater()中找到。除此之外,该块是一个类,并且在一个名为endPlatform的组中,以允许冲突检测工作。游戏运行完全正常,但它无法检测播放器何时触及Endplatform。我没有出现任何错误。
EndPlatform:
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
玩家:
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
所有代码:
import pygame
import random
pygame.font.init()
# Colours + Global constants
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RANDOM = (12, 211, 123)
WIDTH = 800
HEIGHT = 600
SIZE = (WIDTH, HEIGHT)
AGENT = pygame.font.SysFont("Agent Orange", 30)
# CLASSES
# Block is the common platform
class EndPlatform(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("endPlatform.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Coins(pygame.sprite.Sprite):
def __init__(self, display):
super().__init__()
self.image = pygame.image.load("hud_coins.png")
self.rect = self.image.get_rect()
display.blit(self.image, self.rect)
class Score:
def __init__(self):
self.score = 0
def msgs(self, msg, colour, display):
screen_text = AGENT.render(msg, True, colour)
display.blit(screen_text, [0, 0])
def add(self):
self.score += 1
class Monster(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = HEIGHT - 80
def jump(self):
self.rect.y = -10
class Block(pygame.sprite.Sprite):
def __init__(self, length, height, colour):
super().__init__()
# Making image
self.image = pygame.Surface([length, height])
self.image.fill(colour)
self.rect = self.image.get_rect()
# Setting Y coordinates
self.rect.y = 468
class Platform(pygame.sprite.Sprite):
def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
super().__init__()
self.tiles = pygame.image.load("tiles_spritesheet.png")
self.image = self.tiles.subsurface(pygame.Rect(x_sheet, y_sheet, height, length))
self.rect = self.image.get_rect(x=x_screen, y=y_screen)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Is it touching the floor?
self.standing = True
# Rendering image and creating some variables
self.image = pygame.image.load("Slime.png")
self.sprite_x_change = 0
self.sprite_y_change = 0
self.rect = self.image.get_rect()
self.rect.y = 460
self.rect.x = 120
# Mobility: Left, right, up and stop
def move_right(self):
self.sprite_x_change = 8
def move_left(self):
self.sprite_x_change = -8
def move_up(self, platform):
if self.standing == True:
self.sprite_y_change = -25
self.standing = False
def stop(self):
self.sprite_x_change = 0
def sprint(self):
self.sprite_x_change += 10
def updater(self, platforms, powerups, score, endPlatform):
self.gravity()
self.rect.x += self.sprite_x_change
self.standing = False
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
if self.sprite_x_change > 0:
self.rect.right = blocks.rect.left
elif self.sprite_x_change < 0:
self.rect.left = blocks.rect.right
self.rect.y += self.sprite_y_change
platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
for blocks in platforms_hit:
# Going down
if self.sprite_y_change > 0:
self.rect.bottom = blocks.rect.top - 1
self.standing = True
# Going up
elif self.sprite_y_change < 0:
self.rect.top = blocks.rect.bottom
self.standing = False
self.sprite_y_change = 0
coins_hit = pygame.sprite.spritecollide(self, powerups, True)
if len(coins_hit) > 0:
score.add()
endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
if len(endLevel) > 0:
score.add()
def gravity(self):
self.sprite_y_change += 3
class Level:
def __init__(self):
# Creating groups
self.endPlatform = pygame.sprite.Group()
self.powerups = pygame.sprite.Group()
self.sprites = pygame.sprite.Group()
self.all_things = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
self.entities = pygame.sprite.Group()
self.shift_x = 0
self.shift_y = 0
def updater(self, display, score):
self.all_things.draw(display)
score.msgs("Score: " + str(score.score), RED, display)
def scroll_x(self, shift_x_change):
self.shift_x += shift_x_change
for platform in self.entities:
platform.rect.x += shift_x_change
def scroll_y(self, shift_y_change):
self.shift_y += shift_y_change
for platform in self.entities:
platform.rect.y += shift_y_change
class Level01(Level):
def __init__(self, player1, monster, display):
# Initialise level1
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
self.entities.add(block)
theLevel = []
level = [[600, 400, 648, 0, 70, 70],
[740, 320, 648, 0, 70, 70],
[380, 400, 648, 0, 70, 70],
[900, 280, 648, 0, 70, 70],
[1200, 530, 648, 0, 70, 70],
[1350, 450, 648, 0, 70, 70],
[1500, 550, 648, 0, 70, 70],
[1680, 500, 648, 0, 70, 70],
]
for platform in theLevel:
block = Block(platform[0], platform[1], RED)
block.rect.x = platform[2]
block.rect.y = platform[3]
self.platforms.add(block)
self.all_things.add(block)
self.entities.add(block)
for goodPlatform in level:
platform = Platform(display, goodPlatform[0], goodPlatform[1], goodPlatform[2], goodPlatform[3], goodPlatform[4], goodPlatform[5])
self.platforms.add(platform)
self.all_things.add(platform)
self.entities.add(platform)
for n in range(1):
coin = Coins(display)
coin.rect.x = random.randint(0, WIDTH*3)
coin.rect.y = 400
self.all_things.add(coin)
self.entities.add(coin)
self.powerups.add(coin)
platforms_hit = pygame.sprite.spritecollide(coin, self.entities, False)
for hit in platforms_hit:
coin.rect.x = random.randrange(0, WIDTH*3)
finalPlatform = EndPlatform(display)
finalPlatform.rect.x = 1900
finalPlatform.rect.y = 420
self.all_things.add(finalPlatform)
self.entities.add(finalPlatform)
self.platforms.add(finalPlatform)
self.endPlatform.add(finalPlatform)
class Level02(Level):
def __init__(self, player1, monster):
super().__init__()
# Level01 things
block = Block(245, 3, BLACK)
Level.all_things = self.all_things
self.sprites.add(player1, monster)
self.platforms.add(block)
self.all_things.add(player1, block, monster)
def main():
# Init pygame
pygame.init()
# Set screen
backgrounds = ["background2.jpg", "background.jpg"]
background = pygame.image.load(backgrounds[0])
backgroundRect = background.get_rect()
display = pygame.display.set_mode(background.get_size())
# Creating FPS thingy
clock = pygame.time.Clock()
# Making levels + Player
score = Score()
monster = Monster(30, 30, RANDOM)
player = Player()
level_1 = Level01(player, monster, display)
level_2 = Level02(player, monster)
# Choosing level
levelList = []
levelList.append(level_1)
levelList.append(level_2)
currentLevelNumber = 0
# Game loop
loop = True
while loop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.move_right()
if event.key == pygame.K_LEFT:
player.move_left()
if event.key == pygame.K_UP:
player.move_up(currentLevel.platforms)
if event.key == pygame.KMOD_LSHIFT and event.key == pygame.K_RIGHT:
player.sprint()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
player.stop()
if event.key == pygame.KMOD_LSHIFT:
player.sprite_x_change -= 10
# Update things
#monster.jump()
if player.rect.x > 400:
player.rect.x = 400
currentLevel.scroll_x(-10)
if player.rect.x >= WIDTH:
player.rect.x = WIDTH
currentLevel.scroll(0)
if player.rect.y >= HEIGHT:
main()
if player.sprite_x_change < 0 and player.rect.x >= 120:
currentLevel.scroll_x(0)
if player.rect.left <= 120 and player.sprite_x_change < 0:
player.rect.x = 120
player.rect.left = 120
currentLevel.scroll_x(10)
'''
if player.rect.y <= 300:
if player.standing == False and player.sprite_y_change < 0:
currentLevel.scroll_y(10)
if currentLevel.shift_y > 0:
y_speed = -4
if player.standing == True and player.rect.y < 300:
y_speed = 4
print(currentLevel.shift_y)
currentLevel.scroll_y(y_speed)
'''
currentLevel = levelList[currentLevelNumber]
if currentLevel.shift_x > 0:
currentLevel.scroll_x(currentLevel.shift_x * -1)
display.blit(background, backgroundRect)
player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
currentLevel.updater(display, score)
# Refresh screen
clock.tick(30)
pygame.display.update()
pygame.quit()
loop = False
if __name__ == "__main__":
main()
我似乎发现了这个问题,因为一些愚蠢的原因你不能在同一个对象上使用两次碰撞检测。我曾经使用过一次,所以玩家可以站在街区和另一个时间,这样你就可以进入下一个级别了!
它没有切换到下一个级别的原因是当你与平台碰撞时你改变了矩形的位置,所以player.rect
被移出blocks.rect
,因此当你用spritecollide
调用endPlatform
时它不能再碰撞for blocks in platforms_hit:
集团。
一个快速而肮脏的修复方法是检查True
循环,如果该块在endPlatform组中,然后返回for blocks in platforms_hit:
if blocks in endPlatform:
score.add()
return True
:
currentLevelNumber
如果返回main
,则增加True
函数中的change_level = player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
if change_level:
currentLevelNumber += 1
:
qazxswpoi
以上是关于碰撞检测不适用于pygame的主要内容,如果未能解决你的问题,请参考以下文章
pygame游戏检测矩形是否碰撞指定颜色的自定义函数(仅5行代码)