Anonymous
Обработка столкновений в pygame
Сообщение
Anonymous » 29 дек 2024, 21:57
Я делаю платформер. Я использую масштабируемый режим изменения размера pygame, поэтому дисплей поддерживает постоянное соотношение сторон. Моя проблема в том, что прямоугольник игрока сталкивается с прямоугольником земли, толкая игроков снизу вверх, но я вижу много сбоев, таких как движение по прямой линии, а затем возврат к предыдущей плитке. И я с нетерпением жду новых советов и оптимизаций моего кода. и спасибо.
Код: Выделить всё
class Player(Sprite):
def __init__(self, pos=(10, -10), config=None):
super().__init__()
self.pics = {
"stand": [load_file("entities/player.png")],
"idle": load_dir("entities/player/idle"),
"jump": load_dir("entities/player/jump"),
"run": load_dir("entities/player/run"),
"slide": load_dir("entities/player/slide"),
"wall_slide": load_dir("entities/player/wall_slide"),
}
self.animations = {
"stand": Animation(self.pics["stand"], 0.1),
"idle": Animation(self.pics["idle"], 0.3),
"jump": Animation(self.pics["jump"], 0.1),
"run": Animation(self.pics["run"], 0.1),
"slide": Animation(self.pics["slide"], 0.1),
"wall_slide": Animation(self.pics["wall_slide"], 0.1),
}
self.state = "idle"
self.image, _ = self.animations[self.state].frame
self.rect = self.image.get_rect(center=pos)
self.mask = pg.mask.from_surface(self.image)
self.pos = pg.math.Vector2(self.rect.center)
self.vel = pg.math.Vector2(0, 0)
self.speed = 3
self.max_speed = 15
self.gravity = 1
self.jump_strength = -3
self.is_jumping = False
self.idle_timer = 0
self.flip = False
self.keys = {key: False for key in ("left", "right", "up", "down")}
self.colls = {"left": False, "right": False, "up": False, "down": False}
self.key_map = config or {
"left": pg.K_a,
"right": pg.K_d,
"jump": pg.K_SPACE,
}
def update(self, dt):
self.flip = self.vel.x < 0
self.animations[self.state].update(dt)
self.image, _ = self.animations[self.state].frame
self.rect.size = self.image.get_size()
self.rect.center = self.pos
if not self.colls["down"]:
self.vel.y += self.gravity * dt
else:
self.vel.y = 0
if self.keys["left"]:
self.vel.x = -self.speed
elif self.keys["right"]:
self.vel.x = self.speed
else:
self.vel.x = 0
if self.colls["down"]:
if abs(self.vel.x) > 0:
self.state = "run"
else:
self.state = "idle"
elif self.is_jumping:
self.state = "jump"
self.colls = {key: False for key in self.colls}
def handle_event(self, event):
if event.type == pg.KEYDOWN:
if event.key in self.key_map.values():
self.idle_timer = 0
if event.key == self.key_map["left"]:
self.keys["left"] = True
self.vel.x -= self.speed
self.state = "run"
if event.key == self.key_map["right"]:
self.keys["right"] = True
self.vel.x += self.speed
self.state = "run"
if event.key == self.key_map["jump"] and not self.is_jumping:
self.vel.y = self.jump_strength
self.state = "jump"
self.is_jumping = True
elif event.type == pg.KEYUP:
if event.key == self.key_map["left"]:
self.keys["left"] = False
self.vel.x = 0
if event.key == self.key_map["right"]:
self.keys["right"] = False
self.vel.x = 0
if not self.keys["left"] and not self.keys["right"]:
self.state = "idle"
def handle_collisions(self, tiles):
self.pos.x += self.vel.x
self.rect.centerx = self.pos.x
for tile in tiles:
if self.rect.colliderect(tile.rect) and tile.type in TOUCHABLES:
if self.vel.x > 0:
self.rect.right = tile.rect.left
self.colls["right"] = True
elif self.vel.x < 0:
self.rect.left = tile.rect.right
self.colls["left"] = True
self.pos.x = self.rect.centerx
self.pos.y += self.vel.y
self.rect.centery = self.pos.y
for tile in tiles:
if self.rect.colliderect(tile.rect) and tile.type in TOUCHABLES:
if self.vel.y > 0:
self.rect.bottom = tile.rect.top
self.colls["down"] = True
self.is_jumping = False
self.vel.y = 0
elif self.vel.y < 0:
self.rect.top = tile.rect.bottom
self.colls["up"] = True
self.vel.y = 0
self.pos.y = self.rect.centery
if self.colls["left"] or self.colls["right"]:
self.vel.x = 0
if self.colls["up"] or self.colls["down"]:
self.vel.y = 0
def draw(self, screen, offset):
pg.draw.rect(screen, (255, 0, 0), self.rect, 1)
screen.blit(pg.transform.flip(self.image, self.flip, False), self.rect.topleft - offset)
Это происходит потому, что self.colls сбрасывает каждое обновление.
Подробнее здесь:
https://stackoverflow.com/questions/793 ... -in-pygame
1735498653
Anonymous
Я делаю платформер. Я использую масштабируемый режим изменения размера pygame, поэтому дисплей поддерживает постоянное соотношение сторон. Моя проблема в том, что прямоугольник игрока сталкивается с прямоугольником земли, толкая игроков снизу вверх, но я вижу много сбоев, таких как движение по прямой линии, а затем возврат к предыдущей плитке. И я с нетерпением жду новых советов и оптимизаций моего кода. и спасибо. [code]class Player(Sprite): def __init__(self, pos=(10, -10), config=None): super().__init__() self.pics = { "stand": [load_file("entities/player.png")], "idle": load_dir("entities/player/idle"), "jump": load_dir("entities/player/jump"), "run": load_dir("entities/player/run"), "slide": load_dir("entities/player/slide"), "wall_slide": load_dir("entities/player/wall_slide"), } self.animations = { "stand": Animation(self.pics["stand"], 0.1), "idle": Animation(self.pics["idle"], 0.3), "jump": Animation(self.pics["jump"], 0.1), "run": Animation(self.pics["run"], 0.1), "slide": Animation(self.pics["slide"], 0.1), "wall_slide": Animation(self.pics["wall_slide"], 0.1), } self.state = "idle" self.image, _ = self.animations[self.state].frame self.rect = self.image.get_rect(center=pos) self.mask = pg.mask.from_surface(self.image) self.pos = pg.math.Vector2(self.rect.center) self.vel = pg.math.Vector2(0, 0) self.speed = 3 self.max_speed = 15 self.gravity = 1 self.jump_strength = -3 self.is_jumping = False self.idle_timer = 0 self.flip = False self.keys = {key: False for key in ("left", "right", "up", "down")} self.colls = {"left": False, "right": False, "up": False, "down": False} self.key_map = config or { "left": pg.K_a, "right": pg.K_d, "jump": pg.K_SPACE, } def update(self, dt): self.flip = self.vel.x < 0 self.animations[self.state].update(dt) self.image, _ = self.animations[self.state].frame self.rect.size = self.image.get_size() self.rect.center = self.pos if not self.colls["down"]: self.vel.y += self.gravity * dt else: self.vel.y = 0 if self.keys["left"]: self.vel.x = -self.speed elif self.keys["right"]: self.vel.x = self.speed else: self.vel.x = 0 if self.colls["down"]: if abs(self.vel.x) > 0: self.state = "run" else: self.state = "idle" elif self.is_jumping: self.state = "jump" self.colls = {key: False for key in self.colls} def handle_event(self, event): if event.type == pg.KEYDOWN: if event.key in self.key_map.values(): self.idle_timer = 0 if event.key == self.key_map["left"]: self.keys["left"] = True self.vel.x -= self.speed self.state = "run" if event.key == self.key_map["right"]: self.keys["right"] = True self.vel.x += self.speed self.state = "run" if event.key == self.key_map["jump"] and not self.is_jumping: self.vel.y = self.jump_strength self.state = "jump" self.is_jumping = True elif event.type == pg.KEYUP: if event.key == self.key_map["left"]: self.keys["left"] = False self.vel.x = 0 if event.key == self.key_map["right"]: self.keys["right"] = False self.vel.x = 0 if not self.keys["left"] and not self.keys["right"]: self.state = "idle" def handle_collisions(self, tiles): self.pos.x += self.vel.x self.rect.centerx = self.pos.x for tile in tiles: if self.rect.colliderect(tile.rect) and tile.type in TOUCHABLES: if self.vel.x > 0: self.rect.right = tile.rect.left self.colls["right"] = True elif self.vel.x < 0: self.rect.left = tile.rect.right self.colls["left"] = True self.pos.x = self.rect.centerx self.pos.y += self.vel.y self.rect.centery = self.pos.y for tile in tiles: if self.rect.colliderect(tile.rect) and tile.type in TOUCHABLES: if self.vel.y > 0: self.rect.bottom = tile.rect.top self.colls["down"] = True self.is_jumping = False self.vel.y = 0 elif self.vel.y < 0: self.rect.top = tile.rect.bottom self.colls["up"] = True self.vel.y = 0 self.pos.y = self.rect.centery if self.colls["left"] or self.colls["right"]: self.vel.x = 0 if self.colls["up"] or self.colls["down"]: self.vel.y = 0 def draw(self, screen, offset): pg.draw.rect(screen, (255, 0, 0), self.rect, 1) screen.blit(pg.transform.flip(self.image, self.flip, False), self.rect.topleft - offset) [/code] Это происходит потому, что self.colls сбрасывает каждое обновление. Подробнее здесь: [url]https://stackoverflow.com/questions/79316157/collision-handling-in-pygame[/url]