简体   繁体   English

如何检测玩家和方块之间的碰撞? Pygame

[英]How can I detect a collision between the player and a block? Pygame

I'm struggling with collisions in Pygame.我正在努力解决 Pygame 中的碰撞问题。 I want that when the player (Tom) touches a FireBlock, a message is printed on the console.我希望当玩家(Tom)触摸 FireBlock 时,控制台上会打印一条消息。

In the class Level is where I create my map and add the corresponding blocks.在 class 级别中,我创建了 map 并添加了相应的块。 Tom is the main player.汤姆是主要球员。

I also have another file where my level is displayed and created: [enter image description here][1]我还有另一个文件显示并创建了我的关卡:[在此处输入图像描述][1]

Could you help me please?请问你能帮帮我吗? I can't seem to make the collisions work properly.我似乎无法使碰撞正常工作。 Thank you for your help!谢谢您的帮助! I'll really appreciate it!我会很感激的!

from pygame.locals import *
import sys

SCREEN_SIZE = (960, 720) #resolution of the game
global HORIZ_MOV_INCR
HORIZ_MOV_INCR = 10 #speed of movement
global FPS
global clock
global time_spent

def RelRect(actor, camera):
    return pygame.Rect(actor.rect.x-camera.rect.x, actor.rect.y-camera.rect.y, actor.rect.w, actor.rect.h)

# Clase para tener la pantalla en el centro del jugador
class Camera(object):
    def __init__(self, screen, player, level_width, level_height):
        self.player = player
        self.rect = screen.get_rect()
        self.rect.center = self.player.center
        self.world_rect = Rect(0, 0, level_width, level_height)

    def update(self):
      if self.player.centerx > self.rect.centerx + 100:
          self.rect.centerx = self.player.centerx - 100
      if self.player.centerx < self.rect.centerx - 100:
          self.rect.centerx = self.player.centerx + 100
      if self.player.centery > self.rect.centery + 100:
          self.rect.centery = self.player.centery - 100
      if self.player.centery < self.rect.centery - 100:
          self.rect.centery = self.player.centery + 100
      self.rect.clamp_ip(self.world_rect)

    def draw_sprites(self, surf, sprites):
        for s in sprites:
            if s.rect.colliderect(self.rect):
                surf.blit(s.image, RelRect(s, self))

# Clase para crear los obstáculos
class BlockMedieval(pygame.sprite.Sprite):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/BlockMedieval.png").convert()
        self.rect = self.image.get_rect()
        self.rect.topleft = [self.x, self.y]

class FireBlock(pygame.sprite.Sprite):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/Fire.png").convert()
        self.rect = self.image.get_rect()
        self.rect.topleft = [self.x, self.y]

# Clase para el jugador y sus colisiones
class Tom(pygame.sprite.Sprite):    
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.movy = 0
        self.movx = 0
        self.x = x
        self.y = y
        self.contact = False
        self.jump = False
        self.image = pygame.image.load('images/Right00.png').convert()
        self.rect = self.image.get_rect()
        self.run_left = ["images/Left00.png","images/Left01.png",
                         "images/Left02.png", "images/Left03.png",
                         "images/Left00.png", "images/Left01.png",
                         "images/Left02.png", "images/Left03.png"]
        self.run_right = ["images/Right00.png","images/Right01.png",
                         "images/Right02.png", "images/Right03.png",
                         "images/Right00.png","images/Right01.png",
                         "images/Right02.png", "images/Right03.png"]
        self.direction = "right"
        self.rect.topleft = [x, y]
        self.frame = 0
        self.score = 0

    def update(self, up, down, left, right):
        if up:
            if self.contact:
                if self.direction == "right":
                    self.image = pygame.image.load("images/Right03.png")
                self.jump = True
                self.movy -= 20
        if down:
            if self.contact and self.direction == "right":
                self.image = pygame.image.load('images/Right00.png').convert_alpha()
            if self.contact and self.direction == "left":
                self.image = pygame.image.load('images/Left00.png').convert_alpha()

        if not down and self.direction == "right":
                self.image = pygame.image.load('images/Right00.png').convert_alpha()

        if not down and self.direction == "left":
            self.image = pygame.image.load('images/Left00.png').convert_alpha()

        if left:
            self.direction = "left"
            self.movx = -HORIZ_MOV_INCR
            if self.contact:
                self.frame += 1
                self.image = pygame.image.load(self.run_left[self.frame]).convert_alpha()
                if self.frame == 6: self.frame = 0
            else:
                self.image = self.image = pygame.image.load("images/Left03.png").convert_alpha()

        if right:
            self.direction = "right"
            self.movx = +HORIZ_MOV_INCR
            if self.contact:
                self.frame += 1
                self.image = pygame.image.load(self.run_right[self.frame]).convert_alpha()
                if self.frame == 6: self.frame = 0
            else:
                self.image = self.image = pygame.image.load("images/Right03.png").convert_alpha()

        if not (left or right):
            self.movx = 0
        self.rect.right += self.movx

        self.collide(self.movx, 0, world)


        if not self.contact:
            self.movy += 0.3
            if self.movy > 10:
                self.movy = 10
            self.rect.top += self.movy

        if self.jump:
            self.movy += 2
            self.rect.top += self.movy
            if self.contact == True:
                self.jump = False

        self.contact = False
        self.collide(0, self.movy, world)


    # Colisiones
    def collide(self, movx, movy, world):
        self.contact = False        
        for o in world:
            if self.rect.colliderect(o):
                self.score += 1
                print("Score: " + str(self.score))
                if movx > 0:
                    self.rect.right = o.rect.left
                if movx < 0:
                    self.rect.left = o.rect.right
                if movy > 0:
                    self.rect.bottom = o.rect.top
                    self.movy = 0
                    self.contact = True
                if movy < 0:
                    self.rect.top = o.rect.bottom
                    self.movy = 0

# Lee el mapa del nivel y crea el nivel
class Level(object):
    def __init__(self, open_level):
        self.level1 = []
        self.world = []
        self.all_sprite = pygame.sprite.Group()
        self.level = open(open_level, "r")

    def create_level(self, x, y):
        for l in self.level:
            self.level1.append(l)

        for row in self.level1:
            for col in row:
                # Donde Tom aparece por primera vez
                if col == "P":
                    self.tom = Tom(x,y)
                    self.all_sprite.add(self.tom)     
                # Medieval Block Obstacle
                if col == "X":
                    blockMedieval = BlockMedieval(x, y)
                    self.world.append(blockMedieval)
                    self.all_sprite.add(self.world)                                                  
                # Fire Block Obstacle
                if col == "F":
                    fireBlock = FireBlock(x, y)
                    self.world.append(fireBlock)
                    self.all_sprite.add(self.world) 

                x += 25   
            y += 25
            x = 0        

    def get_size(self):
        lines = self.level1
        #line = lines[0]
        line = max(lines, key=len)
        self.width = (len(line))*25
        self.height = (len(lines))*25
        return (self.width, self.height)

def tps(reloj, fps):
    temp = reloj.tick(fps)
    tps = temp / 1000.
    return tps


pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 32)
screen_rect = screen.get_rect()
background = pygame.image.load("world/background2.jpg").convert_alpha()
background_rect = background.get_rect()
level = Level("level/level1")
level.create_level(0, 0)
world = level.world
tom = level.tom
pygame.mouse.set_visible(0)

camera = Camera(screen, tom.rect, level.get_size()[0], level.get_size()[1])
all_sprite = level.all_sprite

FPS = 30
clock = pygame.time.Clock()


def startLevel1():
    up = down = left = right = False
    x, y = 0, 0
    while True:

        # if tom.rect.colliderect(blockMedieval.rect):
        #     print("YAY")

        for event in pygame.event.get():
            if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()

            if event.type == KEYDOWN and event.key == K_SPACE:
                up = True
            if event.type == KEYDOWN and event.key == K_DOWN:
                down = True
            if event.type == KEYDOWN and event.key == K_LEFT:
                left = True
            if event.type == KEYDOWN and event.key == K_RIGHT:
                right = True

            if event.type == KEYUP and event.key == K_SPACE:
                up = False
            if event.type == KEYUP and event.key == K_DOWN:
                down = False
            if event.type == KEYUP and event.key == K_LEFT:
                left = False
            if event.type == KEYUP and event.key == K_RIGHT:
                right = False

        asize = ((screen_rect.w // background_rect.w + 1) * background_rect.w, (screen_rect.h // background_rect.h + 1) * background_rect.h)
        bg = pygame.Surface(asize)

        for x in range(0, asize[0], background_rect.w):
            for y in range(0, asize[1], background_rect.h):
                screen.blit(background, (x, y))

        time_spent = tps(clock, FPS)
        camera.draw_sprites(screen, all_sprite)

        tom.update(up, down, left, right)
        camera.update()
        pygame.display.flip()


  [1]: https://i.stack.imgur.com/FZGKk.png

you could look into .spritecollideany() method.您可以查看.spritecollideany()方法。 This method takes a sprite and a sprite group as parameters.此方法将精灵和精灵组作为参数。 It looks at the .rect of the single sprite and checks it against all the .rect of the sprite group and returns True if there is any overlap/collision.它查看单个精灵的.rect并将其与精灵组的所有.rect进行检查,如果有任何重叠/碰撞,则返回 True。 This tutorial has a section on collision detection that might help: https://realpython.com/pygame-a-primer/#collision-detection本教程有一个关于碰撞检测的部分可能会有所帮助: https://realpython.com/pygame-a-primer/#collision-detection

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM