python - Pygame - 与地板/墙壁的碰撞

标签 python pygame collision-detection collision

您好,我目前正在制作一款生存射击游戏,但找不到任何关于如何进行碰撞的方法!我试图让玩家与地板碰撞,但没有成功。这是 map 的图像(我想与月球 block 碰撞): /image/R2apz.jpg

这是一张没有背景的月球 block 图像: /image/W9H2m.png

最后这是我的代码:

    import pygame
import random

gravity = .5
jump_time = 2000
x = 0
y = 0

# Player
class Player(pygame.sprite.Sprite):

    def __init__(self, x, y, gravity):

        # Player dimensions and position
        self.gravity = gravity

        # Player image and animation
        self.images = []
        self.images.append(pygame.image.load('images/player.png'))
        self.images.append(pygame.image.load('images/player2.png'))
        #~ self.images.append(pygame.image.load('ball1.png'))
        #~ self.images.append(pygame.image.load('ball2.png'))
        self.maxImage = len(self.images)
        self.currentImage = 0

        #~ self.rect = pygame.Rect(x, y, 80, 80)
        self.rect = self.images[0].get_rect()
        self.rect.x = x
        self.rect.y = y

        self.timeTarget = 10
        self.timeNum = 1

        self.velX = 0
        self.velY = 0

        # Jump and gravity
        self.vSpeed = 3
        self.jumpForce = 15
        self.maxVspeed = 3
        self.isJumping = False

    # Jump inputs
    def handle_events(self, event):

        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_SPACE:
                if not self.isJumping:
                    self.isJumping = True

            elif event.key == pygame.K_a:
                self.velX = -5

            elif event.key == pygame.K_d:
                self.velX = +5

        elif event.type == pygame.KEYUP:
            if event.key in (pygame.K_a, pygame.K_d):
                self.velX = 0

    # PLayer updates
    def update(self, ground):

        keys = pygame.key.get_pressed()

         # Jumping
        self.vSpeed += gravity
        if self.vSpeed >  self.maxVspeed:
            self.vSpeed = self.maxVspeed
        self.rect.y += self.vSpeed
        if self.rect.y >= ground.y:
            self.vSpeed = 0
            self.rect.y = ground.y
            self.isJumping = False
            if keys[pygame.K_SPACE]:
                if not self.isJumping:
                    self.isJumping = True
        if self.isJumping:
            if pygame.time.get_ticks() < jump_time:
                self.isJumping == True
            else:
                self.isJumping = False
            self.vSpeed -= self.jumpForce

        #print "isJumping:", self.isJumping


        # Animations

        if self.timeNum == self.timeTarget:
            self.currentImage += 1
            if self.currentImage >= self.maxImage:
                self.currentImage = 0
            self.timeNum = 0

        self.rect.centerx += self.velX
        self.rect.centery += self.velY

        # Screen wrap
        if self.rect.right > 1280:
            self.rect.left = 0

        elif self.rect.left < 0:
            self.rect.right = 1280

    # Player rendering
    def render(self, surface):
        surface.blit(self.images[self.currentImage], self.rect)

#----------------------------------------------------------------------

class Zombie():

    def __init__(self, x, y):

        self.image = pygame.image.load('images/zombie.png')
        #~ self.image = pygame.image.load('ball2.png')
        self.rect = self.image.get_rect()

        self.rect.x = x
        self.rect.y = y

        self.direction_left = True

    def update(self, surface_rect):
        if self.direction_left:
            self.rect.x -= 1
            if self.rect.left <= surface_rect.left:
                self.direction_left = not self.direction_left
        else:
            self.rect.x += 1
            if self.rect.right >= surface_rect.right:
                self.direction_left = not self.direction_left

    def render(self, surface):
        surface.blit(self.image, self.rect)

#----------------------------------------------------------------------

class Background():

    def __init__(self):

        self.image = pygame.image.load('images/arena2.jpg')
        #~ self.image = pygame.image.load('background.jpg')
        self.rect = self.image.get_rect()

    def render(self, surface):
        surface.blit(self.image, self.rect)

#----------------------------------------------------------------------

class Game():

    def __init__(self):
        pygame.init()

        # A few variables
        self.gravity = .50
        self.ground = pygame.Rect(0, 640, 1280, 80)

        # Screen
        size = (1280, 720)
        self.screen = pygame.display.set_mode(size)
        pygame.display.set_caption('Moon Survival!')

        # Moon / Background
        self.moon = Background()

        # Zombies
        self.zombies = []
        for i in range(10):
            self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )

        # Player
        self.player = Player(25, 320, self.gravity)

        # Font for text
        self.font = pygame.font.SysFont(None, 72)

        # Pause - center on screen
        self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
        self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)

    def run(self):

        clock = pygame.time.Clock()

        # "state machine" 
        RUNNING   = True
        PAUSED    = False 
        GAME_OVER = False

        # Game loop
        while RUNNING:

            # (all) Events

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                elif event.type == pygame.KEYDOWN:

                    if event.key == pygame.K_ESCAPE:
                        RUNNING = False

                    elif event.key == pygame.K_p:
                        PAUSED = not PAUSED

                # Player/Zomies events  

                if not PAUSED and not GAME_OVER:
                    self.player.handle_events(event)

            # (all) Movements / Updates

            if not PAUSED and not GAME_OVER:
                self.player.update(self.ground)
                for z in self.zombies:
                    z.update(self.screen.get_rect())

            # (all) Display updating

            self.moon.render(self.screen)

            for z in self.zombies:
                z.render(self.screen)

            self.player.render(self.screen)

            if PAUSED:
                self.screen.blit(self.pause_text, self.pause_rect)

            pygame.display.update()

            # FTP

            clock.tick(100)

        # --- the end ---
        pygame.quit()

#---------------------------------------------------------------------

Game().run()

任何帮助将不胜感激,谢谢。

最佳答案

我为 PyWeek #17 制作了一款非常类似的游戏,名为“Miner”。 这是屏幕截图:http://media.pyweek.org/dl/17/powrtoch/miner_ss.png (你可以看到相似之处!)

您可以在 GitHub 上找到相关代码:https://github.com/marcusmoller/pyweek17-miner/blob/master/miner/engine.py#L202-L220 :

def checkCollision(self, sprite, xVel, yVel):
    for x in range(len(level.levelStructure)):
        for y in range(len(level.levelStructure[x])):
            block = level.levelStructure[x][y]

            if block is not None:
                if pygame.sprite.collide_rect(sprite, block):
                    if xVel < 0:
                        sprite.rect.x = block.rect.x + block.rect.w

                    if xVel > 0:
                        sprite.rect.x = block.rect.x - sprite.rect.w

                    if yVel < 0:
                        sprite.rect.y = block.rect.y + block.rect.h

                    if yVel > 0 and not sprite.onGround:
                        sprite.onGround = True
                        sprite.rect.y = block.rect.y - sprite.rect.h

关于python - Pygame - 与地板/墙壁的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20337502/

相关文章:

python - 复制一组并排除一个项目

python - 如何优化 Django 的分页器模块

python - pygame-如何使屏幕变暗

python - 检测矩形与圆的碰撞

ios - Box2D 中的高级碰撞检测 - 碰撞点、力等

algorithm - 圆圈碰撞

python - wrapTransform后如何找到一个点?

python - 使用requests向Mixcloud发送POST请求

python-3.x - 如何使用 systemd 服务显示 PyGame 帧缓冲区?

python - Pygame:玩家 Sprite 与墙壁碰撞时动画不正确