矩形在触地时振动。

huangapple go评论71阅读模式
英文:

rectangle vibrating when touching the ground

问题

大家好。我正在尝试学习关于瓦片地图中的碰撞。但是,我在y轴碰撞方面遇到了问题。当玩家矩形触碰地面时,它开始抖动。我一直在努力找出问题所在,但一直没有成功。有人可以帮助我吗?

这是我的代码:

英文:

everyone. I am trying to learn collisions in tilemaps. I am however having problems with the y-collision. when the player rectangle touches the ground, it starts to vibrate. I have been trying to figure out what the problem is, but to no avail. can someone help me?

Here is my code:

import pygame
from sys import exit
pygame.init()

screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()


class Player:
    def __init__(self, x, y):
        self.rect = pygame.Rect(x, y, 40, 40)
        self.rect.x = x
        self.rect.y = y

        self.vel = 4
        self.dx = 0
        self.dy = 0

        self.is_jump = False
        self.is_stand = False
        self.jump_count = 10

    def handle_input(self):
        key = pygame.key.get_pressed()
        if key[pygame.K_RIGHT]:
            self.dx = self.vel
        elif key[pygame.K_LEFT]:
            self.dx = -self.vel
        else:
            self.dx = 0

        if key[pygame.K_SPACE]:
            self.is_jump = True
            self.is_stand = False
            self.dy = -self.jump_count

    def update(self):
        self.handle_input()
        pygame.draw.rect(screen, (0, 255, 0), self.rect)
        self.rect.update(self.rect.x, self.rect.y, 40, 40)


class Game:
    def __init__(self):
        self.map = [
            ["T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T", "T", "T", "T", "T", "T", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "T", "T", "T", "T", "T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "P", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "T"],
            ["T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T"]
        ]

        self.tiles = []
        for row_num, row in enumerate(self.map):
            for col_num, column in enumerate(row):
                if column == "T":
                    rect = pygame.Rect(40*col_num, 40*row_num, 40, 40)
                    self.tiles.append(rect)
                elif column == "P":
                    self.player = Player(40*col_num, 40*row_num)

        self.gravity = 5
        self.grav_rate = 0.3

    def physics(self, obj):
        obj.dy += self.grav_rate
        if obj.dy > self.gravity:
            obj.dy = self.gravity

        for tile in self.tiles:
            coll_x = obj.rect.x + obj.dx, obj.rect.y, obj.rect.w, obj.rect.h - 1
            coll_y = obj.rect.x, obj.rect.y + obj.dy, obj.rect.w, obj.rect.h

            if tile.colliderect(coll_x):
                pygame.draw.rect(screen, (255, 255, 0), (tile.x, tile.y, 10, 10))
                if obj.dx < 0:
                    obj.rect.left = tile.right
                elif obj.dx > 0:
                    obj.rect.right = tile.left
                obj.dx = 0

            if tile.colliderect(coll_y):
                pygame.draw.rect(screen, (255, 255, 255), (tile.x, tile.y, 10, 10), 2)
                if obj.dy < 0:
                    obj.dy = -obj.dy
                elif obj.dy > 0:
                    obj.dy = 0
                    obj.is_jump = False
                    obj.is_stand = True
                    obj.rect.bottom = tile.top

            # pygame.draw.rect(screen, (255, 255, 0), coll_x, 1)
            # pygame.draw.rect(screen, (255, 255, 255), coll_y, 1)

        obj.rect.x += obj.dx
        obj.rect.y += obj.dy

    def update(self):
        while True:
            screen.fill((0, 0, 0))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    exit()

            for tile in self.tiles:
                pygame.draw.rect(screen, (255, 0, 0), tile)

            self.physics(self.player)
            self.player.update()

            pygame.display.update()
            clock.tick(60)


g = Game()
g.update()

答案1

得分: 0

你必须在进行碰撞检测和游戏物理运算之前更新玩家的位置:

class Game:
    # [...]

    def physics(self, obj):
        obj.dy += self.grav_rate
        if obj.dy > self.gravity:
            obj.dy = self.gravity

        obj.rect.x += obj.dx                # <-- 插入
        obj.rect.y += obj.dy

        for tile in self.tiles:
            coll_x = obj.rect.x + obj.dx, obj.rect.y, obj.rect.w, obj.rect.h - 1
            coll_y = obj.rect.x, obj.rect.y + obj.dy, obj.rect.w, obj.rect.h

            if tile.colliderect(coll_x):
                pygame.draw.rect(screen, (255, 255, 0), (tile.x, tile.y, 10, 10))
                if obj.dx < 0:
                    obj.rect.left = tile.right
                elif obj.dx > 0:
                    obj.rect.right = tile.left
                obj.dx = 0

            if tile.colliderect(coll_y):
                pygame.draw.rect(screen, (255, 255, 255), (tile.x, tile.y, 10, 10), 2)
                if obj.dy < 0:
                    obj.dy = -obj.dy
                elif obj.dy > 0:
                    obj.dy = 0
                    obj.is_jump = False
                    obj.is_stand = True
                    obj.rect.bottom = tile.top

        # obj.rect.x += obj.dx               <-- 删除
        # obj.rect.y += obj.dy
英文:

You must update the player's position before doing collision detection and game physics:

class Game:
    # [...]

    def physics(self, obj):
        obj.dy += self.grav_rate
        if obj.dy &gt; self.gravity:
            obj.dy = self.gravity

        obj.rect.x += obj.dx                #&lt;-- INSERT
        obj.rect.y += obj.dy

        for tile in self.tiles:
            coll_x = obj.rect.x + obj.dx, obj.rect.y, obj.rect.w, obj.rect.h - 1
            coll_y = obj.rect.x, obj.rect.y + obj.dy, obj.rect.w, obj.rect.h

            if tile.colliderect(coll_x):
                pygame.draw.rect(screen, (255, 255, 0), (tile.x, tile.y, 10, 10))
                if obj.dx &lt; 0:
                    obj.rect.left = tile.right
                elif obj.dx &gt; 0:
                    obj.rect.right = tile.left
                obj.dx = 0

            if tile.colliderect(coll_y):
                pygame.draw.rect(screen, (255, 255, 255), (tile.x, tile.y, 10, 10), 2)
                if obj.dy &lt; 0:
                    obj.dy = -obj.dy
                elif obj.dy &gt; 0:
                    obj.dy = 0
                    obj.is_jump = False
                    obj.is_stand = True
                    obj.rect.bottom = tile.top

        # obj.rect.x += obj.dx               &lt;-- DELETE
        # obj.rect.y += obj.dy

huangapple
  • 本文由 发表于 2023年6月19日 23:01:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507872.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定