当前位置: 首页 > 知识库问答 >
问题:

玩偶与墙壁碰撞 随机传送

呼延渝
2023-03-14

我知道已经有一些关于墙壁碰撞的问题了,但是这些答案中的技术都没有帮助我。我正在做一个没有重力的自上而下的探索游戏。运动很好,但是一旦我制造了墙壁和碰撞,它就开始出现故障并传送。我已经包含了(并大大减少了)我认为问题所在的两个功能,在底部我包含了整个代码。

def render(self):
    self.x += self.xvel
    self.app.wall_collision(self, self.xvel, 0)
    self.y += self.yvel
    self.app.wall_collision(self, 0, self.yvel)
    self.rect.topleft = (self.x, self.y)
    self.app.screen.blit(self.surf, self.rect)

根据pygame精灵墙碰撞的建议,我分割了x和y墙碰撞代码。墙壁碰撞代码基于https://github.com/marcusmoller/pyweek17-miner/blob/master/miner/engine.py#L202-L220。

def wall_collision(self, player, xvel, yvel)
    for wall in self.maze.walls:
        if pygame.sprite.collide_rect(player, wall):
            if xvel > 0:
                player.x = wall.rect.left-player.w
            if xvel < 0:
                player.x = wall.rect.right
            if yvel > 0:
                player.y = wall.rect.top-player.h
            if yvel < 0:
                player.y = wall.rect.bottom

此代码适用于一维移动。一、 拥抱一堵墙,直走很好,但同时按下两个移动按钮,心灵传送开始发生。非常感谢您的帮助!我已经把这玩意儿调试好了。以下是播放器位置(x,y)输出的简短片段:

348.4 278.4
348.4 220
348.4 220
348.4 185
348.4 185
348.4 150
348.4 150
348.4 115
348.4 115
348.4 80
348.4 80
348.4 45

如你所见,在y方向上有很多随机的跳跃。跳跃是35的原因是墙壁的块尺寸是35x35。

import pygame
import pygame.freetype
from pygame.locals import (
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    KEYDOWN,
    QUIT,
)

import numpy as np


class App:
    def __init__(self):
        self.running = True
        self.width = 800
        self.height = 600
        self.player = Player(self)
        self.maze = Maze(self, 35)
        pygame.init()
        self.screen = pygame.display.set_mode((self.width, self.height))
        self.clock = pygame.time.Clock()
        self.font = pygame.freetype.SysFont('Times New Roman', 10) 

        while self.running:
            pressed_keys = pygame.key.get_pressed()
            
            for event in pygame.event.get():
                if event.type == QUIT:
                    self.running = False
            self.render()
            self.player.update(pressed_keys)
            
    def render(self):
        self.screen.fill((255, 255, 255))
        text_surf, text_rect = self.font.render('({}, {}) ({}, {})'.format(self.player.x, self.player.y, self.player.xvel, self.player.yvel), (0, 0, 0), size=10)
        self.screen.blit(text_surf, (500, 300))
        self.player.move()
        self.maze.render()
        pygame.display.flip()
        self.clock.tick(60)
        

    def wall_collision(self, player, xvel, yvel):
        for wall in self.maze.walls:
            if pygame.sprite.collide_rect(self.player, wall):
                if xvel > 0:
                    self.player.x = wall.rect.left-self.player.w
                if xvel < 0:
                    self.player.x = wall.rect.right
                if yvel > 0:
                    self.player.y = wall.rect.top-self.player.h
                if yvel < 0:
                    self.player.y = wall.rect.bottom
        
class Player(pygame.sprite.Sprite):
    def __init__(self, app):
        super(Player,self).__init__()
        self.app = app
        self.x = 100
        self.y = 100
        self.xvel = 0
        self.yvel = 0
        self.max_speed = 8
        self.acc = self.max_speed / 2
        self.de_acc = self.max_speed * 0.8

        self.h = 25
        self.w = 25
        
        self.surf = pygame.Surface((self.h, self.w))
        self.surf.fill((0, 0, 204))
        self.rect = self.surf.get_rect()
        self.rect.topleft = self.x, self.y
        
    def update(self, pressed_keys):
        if pressed_keys[K_UP]:
            self.yvel = max(self.yvel - self.acc, -self.max_speed)
        if pressed_keys[K_DOWN]:
            self.yvel = min(self.yvel + self.acc, self.max_speed)
        if pressed_keys[K_LEFT]:
            self.xvel = max(self.xvel - self.acc, -self.max_speed)
        if pressed_keys[K_RIGHT]:
            self.xvel = min(self.xvel + self.acc, self.max_speed)

        if not pressed_keys[K_UP] and not pressed_keys[K_DOWN]:
            if self.yvel > 0:
                self.yvel = max(0, self.yvel - self.de_acc)
            if self.yvel < 0:
                self.yvel = min(0, self.yvel + self.de_acc)
                
        if not pressed_keys[K_LEFT] and not pressed_keys[K_RIGHT]:
            if self.xvel > 0:
                self.xvel = max(0, self.xvel - self.de_acc)
            if self.xvel < 0:
                self.xvel = min(0, self.xvel + self.de_acc)

    def move(self):
        self.x += self.xvel
        self.app.wall_collision(self, self.xvel, 0)
        self.y += self.yvel
        self.app.wall_collision(self, 0, self.yvel)
        self.rect.topleft = (self.x, self.y)
        self.app.screen.blit(self.surf, self.rect)






        
class Maze:
    def __init__(self, app, size):
        super(Maze, self).__init__()
        self.maze = np.array([[1,1,1,1,1,1,1,1,1,1],
                     [1,0,0,0,0,0,0,0,0,1],
                     [1,0,0,0,0,0,0,0,0,1],
                     [1,0,1,1,1,1,1,1,0,1],
                     [1,0,1,0,0,0,0,0,0,1],
                     [1,0,1,0,1,1,1,1,0,1],
                     [1,0,0,0,0,0,0,0,0,1],
                     [1,1,1,1,1,1,1,1,1,1]])
        self.size = size
        self.app = app
        self.draw()

    def draw(self):
        self.walls = pygame.sprite.Group()
        for i, row in enumerate(self.maze):
            for j, el in enumerate(row):
                if el == 1:
                    x = i * self.size
                    y = j* self.size
                    self.walls.add(Wall(x, y, self.size))
                    
    def render(self):
        for wall in self.walls:
            self.app.screen.blit(wall.surf, wall.rect)
            

class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, size):
        super(Wall, self).__init__()
        self.surf = pygame.Surface((size, size))
        self.x = x
        self.y = y
        self.rect = self.surf.get_rect()
        self.rect.topleft = (self.x, self.y)
    


app = App()
pygame.quit()

共有1个答案

东方森
2023-03-14

玩家的位置被正确地限制在墙壁上,但是玩家的速度仍然在增加。如果速度足够大,玩家一步就“跳过”墙壁。当玩家撞到墙壁时,您需要将速度设置为0。
此外,您需要考虑玩家在墙壁的哪一边,并且需要更新palyer的. rect属性:

class App:
    # [...]

    def wall_collision(self, player, xvel, yvel):
        for wall in self.maze.walls:
            if pygame.sprite.collide_rect(self.player, wall):
                if xvel > 0 and self.player.rect.left < wall.rect.left:
                    self.player.rect.right = wall.rect.left
                    self.player.x = self.player.rect.x
                    self.xvel = 0
                if xvel < 0 and self.player.rect.right > wall.rect.right:
                    self.player.rect.left = wall.rect.right
                    self.player.x = self.player.rect.x
                    self.xvel = 0
                if yvel > 0 and self.player.rect.top < wall.rect.top:
                    self.player.rect.bottom = wall.rect.top
                    self.player.y = self.player.rect.y
                    self.yvel = 0
                if yvel < 0 and self.player.rect.bottom > wall.rect.bottom:
                    self.player.rect.top = wall.rect.bottom
                    self.player.y = self.player.rect.y
                    self.yvel = 0
 类似资料:
  • 所以我目前正在尝试做一个几乎像迷宫一样的游戏。问题是墙壁碰撞,一旦角色撞到墙上,我就不能再把他弄出来了,不管碰撞后我试图带他去哪个方向,他都会被“卡住”。我想的一个解决方案是,每当角色撞到墙上时,“支持他”,这样就不会再检测到碰撞。然而,当我这样做的时候,他以一种奇怪的方式穿墙。这是我的代码,所以你们可以知道我在做什么: 这段代码的很大一部分实际上是从另一个问同样问题的人那里得到的。即使按照另一个

  • 我已经尝试解决了平滑的玩家-墙壁碰撞的问题,这样玩家可以沿着墙壁滑动。 我尝试了以下内容: 但是如果玩家碰到了墙,他不会滑动...他只是停下来了。(我对W,A,S,D也是分开做的。) 只有当我将玩家位置设置回他正在触摸的墙壁位置时,它才有效。如下: 但是它不起作用,因为对于与另一面墙相连的墙,玩家会接触更多的边,玩家会跳到角落...所以它只适用于一面墙... 我的问题是:如何以另一种方式使玩家与墙

  • 我目前正在开发一个自上而下的射击游戏,在碰撞方面有一些问题。我的世界是瓷砖做的(64x64)。瓦片和实体是矩形。玩家以例如2.74的速度移动(为了更平滑的移动,不以像素为单位)。但是当涉及到玩家(一个实体)和墙之间的碰撞时,我有一些问题。为了检查是否有碰撞,我用我的球员的当前位置和他的移动速度来计算他的下一个位置和是否有碰撞。但我会检查途中的每个像素,所以即使移动速度非常快,我也无法跳过障碍。假设

  • 我有一个球,我可以在由大小相等的瓷砖组成的地图上移动。玩家应该不能在较暗且有黑色边框的瓷砖上行走。我有一个多维的瓷砖阵列,我用它来检查哪些瓷砖是实心的。 我希望玩家在水平和垂直移动时,可以靠墙滑动。问题是,如果他那样做,他就会固执己见。我设法使它在每个轴上都能完美工作,但是分开的。下面是我的水平碰撞检查代码: level.isBlocked() 方法检查数组的索引是否被实心磁贴占用。i 和 j 变

  • 我一直在尝试在Libgdx中找到/创建矩形的碰撞检测,但似乎什么都做不到。我有一个叫bucket的矩形,宽度和高度为64,还有一个叫wall的矩形,宽度和高度为64。我试着让玩家不穿过矩形,可以在粘墙的同时继续移动,而不需要通过相位或随机传送。我的方法在有1个块的情况下有效,但当有多个块的时候,它就会中断,不起作用。 我知道这种方法很难看但这只是实验 如果有人能给我指出正确的方向或分享一些对我有帮

  • 我一直在尝试使用碰撞检测来阻止物体相互碰撞。但我不知道怎么做。 当物体碰撞时,我试着颠倒它们速度矢量的方向(所以它远离碰撞的地方),但是有时物体会卡在对方体内。 我试着改变他们的速度,但这只是父母彼此的反对。 有没有一种简单的方法来限制物体的运动,这样它们就不会穿过其他物体?我一直在使用矩形相交来进行碰撞,我还尝试了圆形冲突检测(使用对象之间的距离)。 思想? 希望它不太难阅读。 编辑:所以我一直