如何添加平台碰撞?

Posted

技术标签:

【中文标题】如何添加平台碰撞?【英文标题】:How I can add platform collision? 【发布时间】:2021-08-12 02:25:15 【问题描述】:

我是编程新手,我还在学习,我尝试制作我的第一个平台游戏。 在第一步中,一切都很好,但我在检测与平台的碰撞时遇到了问题。 如果玩家跌倒,我会添加碰撞并且效果很好,但是如果我尝试添加与底部、左侧和右侧平台的碰撞,效果会不好:(

我将所有代码添加到清晰视图。如果玩家摔倒了,代码可以正常工作。

你知道我能做些什么来添加碰撞吗?

#main

# Project 1 - platform game

import pygame as pg 
import random
from settings import *
from sprites import *
from os import path

class Game:
    def __init__(self):
        # inicjalizacja okna gry itd
        pg.init()
        pg.mixer.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.running = True 
        self.font_name = pg.font.match_font(FONT_NAME) # fonts
        
    def new(self):
        # start a new game
        self.all_sprites = pg.sprite.Group()    # all sprite's
        self.platforms = pg.sprite.Group()
        self.player = Player(self)  # dodaję gracza
        self.all_sprites.add(self.player)   
        # dodaję platformy
        for plat in PLATFORM_LIST:
            p = Platform(*plat)
            self.all_sprites.add(p)
            self.platforms.add(p)
            
        #ground generator  
        i = 0
        x = 0
        while i < 35:
            ground = Platform(x, HEIGHT - 40, 50, 40)
            self.all_sprites.add(ground)
            self.platforms.add(ground)
            i += 1
            x += 50
        
            
        
        
        self.run() # game loop start
    
    def run(self):
        # game loop
        self.playing = True 
        while self.playing:
            self.clock.tick(FPS)
            self.events()   
            self.update()   
            self.draw()     
            
    def update(self):
        # game loop udpate
        self.all_sprites.update()
        # collision if player is falling
        if self.player.vel.y > 0:
            hits = pg.sprite.spritecollide(self.player, self.platforms, False)
            if hits:
                self.player.pos.y = hits[0].rect.top
                self.player.vel.y = 0   
                
                # still I don't have idea what I can make collision with right, left and bottom 
                  platform
        
                
                
                
        # if player reach 1/2 screen
        if self.player.rect.right >= WIDTH / 2: 
            self.player.pos.x -= abs(self.player.vel.x)
            for plat in self.platforms:
                plat.rect.right -= abs(self.player.vel.x)  
                if plat.rect.right <= WIDTH:    
                    plat.kill                   
                    
        # player die
        if self.player.rect.bottom > HEIGHT:
            self.playing = False
                    
        
    def events(self):
        # game loop - events
        for event in pg.event.get():
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    self.player.jump()
        
    def draw(self):
        #game loop - draw
        self.screen.fill(BLACK) 
        self.all_sprites.draw(self.screen) 
        
        pg.display.flip()  
        
    def show_start_screen(self):
        # start screen not add yet
        pass
        
    def show_go_screen(self):
        # game over screen
        if not self.running:
            return
        self.screen.fill(BLUE)
        self.draw_text("GAME OVER!", 48, WHITE, WIDTH / 2, HEIGHT / 4)
        self.draw_text("Press button to play again", 22, WHITE, WIDTH / 2, HEIGHT * 3 / 4)
        pg.display.flip()
        self.wait_for_key()
            
    def wait_for_key(self):
        waiting = True
        while waiting:
            self.clock.tick(FPS)
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    waiting = False
                    self.running = False
                if event.type == pg.KEYUP:
                    waiting = False
                    
    def draw_text(self, text, size, color, x, y):
        font = pg.font.Font(self.font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        text_rect.midtop = (x, y)
        self.screen.blit(text_surface, text_rect)
            
        
    
g = Game()      
g.show_start_screen() 
while g.running:    
    g.new()     
    g.show_go_screen()   
    
pg.quit()

#SPRITES

import pygame as pg
from settings import *
import random
vec = pg.math.Vector2 


class Player(pg.sprite.Sprite):
    def __init__(self, game):
        pg.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pg.Surface((30, 40))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)
        self.pos = vec(WIDTH / 2, HEIGHT / 2)  
        self.vel = vec(0, 0)    
        self.acc = vec(0, 0)   
        
    def jump(self):
        
        self.rect.x += 1
        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        self.rect.x -= 1
        if hits:
            self.vel.y = - PLAYER_JUMP
        
    def update(self):
        self.acc = vec(0, PLAYER_GRAV)  # PLAYER_GRAV - gravity
        keys = pg.key.get_pressed()
        if keys[pg.K_LEFT]:
            self.acc.x = - PLAYER_ACC
        if keys[pg.K_RIGHT]:
            self.acc.x = PLAYER_ACC
        
        
        # add friction
        self.acc.x += self.vel.x * PLAYER_FRICTION 
        # równanie ruchu
        self.vel += self.acc
        if abs(self.vel.x) < 0.1:
            self.vel.x = 0
        self.pos += self.vel + 0.5 * self.acc 
        if self.pos.x > WIDTH:
            self.pos.x = WIDTH
        if self.pos.x < 0:
            self.pos.x = 0
        
        self.rect.midbottom = self.pos 
        
class Platform(pg.sprite.Sprite):
    def __init__(self, x, y, w, h):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((w, h))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
    


    # settings

TITLE = "Project One"
WIDTH = 800
HEIGHT = 600
FPS = 60
FONT_NAME = 'comic sans ms'  # arial, verdana, times new roman, palatino, garamond, comic sans ms

# ustawienia gracza
PLAYER_FRICTION = -0.12
PLAYER_ACC = 0.5
PLAYER_JUMP = 20
PLAYER_GRAV = 0.8

# lista platform

GROUND_LIST =[(0, HEIGHT - 40, 50, 40),
              (50, HEIGHT - 40, 50, 40),
              (100, HEIGHT - 40, 50, 40),
              (150, HEIGHT - 40, 50, 40),
              (200, HEIGHT - 40, 50, 40),
              (250, HEIGHT - 40, 50, 40),
              (300, HEIGHT - 40, 50, 40),
              (350, HEIGHT - 40, 50, 40),
              (400, HEIGHT - 40, 50, 40)]

PLATFORM_LIST = [(300, 300, 75, 40),
                (400, 350, 75, 40),
                (600, 300, 75, 40),
                (800, 250, 75, 40),
                (1000, 350, 75, 40),
                (1200, 400, 75, 40),
                (1400, 200, 75, 40),]


# defined colors

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)

【问题讨论】:

水平和垂直碰撞见:geeksforgeeks.org/collision-detection-in-pygame 【参考方案1】:

我再写一次, 我做了一些工作并找到了解决问题的方法:) 我不得不分别描述 x 和 y 的碰撞。此外,在 Player 类中输入碰撞有助于消除玩家跳到顶部平台的问题。

【讨论】:

以上是关于如何添加平台碰撞?的主要内容,如果未能解决你的问题,请参考以下文章

ue5怎么增添模型碰撞体积

如何添加与多个精灵的碰撞

如何在我的程序中向我的对象和屏幕周围添加碰撞?

使用固定的 SKPhysicsJoint 将作为孩子的平台检测命中框附加到玩家精灵会更改玩家的碰撞和检测位掩码

使用固定的SKPhysicsJoint将平台检测命中框作为子项附加到玩家精灵更改玩家的碰撞和检测位掩码

如何检测精灵套件中的碰撞?