碰撞检测在 pygame 中不起作用 [英] Collision detection not working in pygame
问题描述
我目前正在制作游戏,但遇到碰撞检测问题.我正在结束关卡块,但它无法检测到玩家是否站在它上面以更改为 2 级.块的碰撞检测在 player.updater() 中找到.除此之外,该块是一个类,并在一个名为 endPlatform 的组中,以允许碰撞检测工作.游戏运行良好,但无法检测到玩家何时点击 Endplatform.我没有收到任何显示的错误.
I am making a game at the moment and I am experiencing problems with collision detection. I am making an end of level block but it can not detect if the player is standing on it to change to level 2. The collision detection for the block is found in player.updater(). As well as this the block is a class and in a group called endPlatform to allow the collision detection to work. The game runs perfectly fine however it can not detect when the Player hits Endplatform. I get no errors which show up.
结束平台:
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()
推荐答案
看来我发现了问题,出于某种愚蠢的原因,您不能对同一个对象使用两次碰撞检测.我用过一次是为了让玩家可以站在方块上,另一次是为了你可以进入下一个关卡!
It seems I found the problem, for some daft reason you can't use collision detection twice on the same object. I used it once so that the player could stand on the block and another time so that you could go on to the next level!
这篇关于碰撞检测在 pygame 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!