英文:
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 > self.gravity:
obj.dy = self.gravity
obj.rect.x += obj.dx #<-- 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 < 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 <-- DELETE
# obj.rect.y += obj.dy
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论