Я разрабатываю 2D-раннер с использованием Kivy и реализую точное по пикселям обнаружение столкновений. Я использовал свойство Keep_data = True, чтобы разрешить доступ к данным пикселей для моих спрайтов, и метод read_pixel() для проверки непрозрачных пикселей в перекрывающихся областях. Проблема Описание:
Обнаружение столкновений работает нормально, когда передняя часть персонажа касается передней части монстра. Столкновение срабатывает только тогда, когда их непрозрачные пиксели перекрываются, что является ожидаемым поведением (как показано на изображении 1).
Однако, когда персонаж прыгает и приземляется на спину монстра, столкновение иногда срабатывает, даже если их пиксели на самом деле не соприкасаются, а именно тогда, когда соединительная рамка персонажа касается области пикселей монстра (как показано на изображении 2).
Изображение1
Изображение2 Обзор кода:
Вот соответствующая часть моего Класс CollisionMixin, который обеспечивает точное обнаружение столкновений:
class CollisionMixin:
def collide_widget(self, other):
# First, check if bounding boxes overlap
if not super().collide_widget(other):
return False
# Get the overlapping area between the bounding boxes
x1 = max(self.x, other.x)
y1 = max(self.y, other.y)
x2 = min(self.right, other.right)
y2 = min(self.top, other.top)
# Check pixel-perfect collision within the overlap
for y in range(int(y1), int(y2)):
for x in range(int(x1), int(x2)):
# Ensure that both widgets have non-transparent pixels at the same point
if self.pixel_collides_at(x, y) and other.pixel_collides_at(x, y):
return True
return False
def pixel_collides_at(self, x, y):
"""Check if the widget has a non-transparent pixel at (x, y)."""
if not super().collide_point(x, y):
return False
# Convert to local coordinates of the widget
x_local = int(x - self.x)
y_local = int(self.height - (y - self.y))
# Check if the pixel at (x_local, y_local) is non-transparent
try:
color = self._coreimage.read_pixel(x_local, y_local)
return color[3] > 0 # Check alpha channel for transparency
except:
return False
class GameScreen(Screen):
monsters = ListProperty([])
.
.
def __init__(self, **kwargs):
super(GameScreen, self).__init__(**kwargs)
self.update_event = None
def start(self):
.
.
.
self.update_event = Clock.schedule_interval(self.update, 1/60)
def update(self, dt):
# Logics for generating and moving monster
for monster in self.monsters:
# Check for pixel collision
if self.ids.character.collide_widget(monster):
print('Pixel-perfect collision detected!')
# Stop the current animation and movement for the character and the monster
self.ids.character.stop_current_animation()
monster.stop_current_animation()
Я пробовал: Проверка ограничивающей рамки: Я проверил, что ограничивающая рамка Проверка рамок работает правильно — столкновение обнаруживается только тогда, когда ограничивающие рамки перекрываются. Проверка столкновения пикселей: я использую read_pixel(), чтобы определить, есть ли не -прозрачные пиксели в области перекрытия. В большинстве случаев это работает, но, похоже, возникает проблема, когда персонаж приземляется на спину монстра.
Я разрабатываю 2D-раннер с использованием Kivy и реализую точное по пикселям обнаружение столкновений. Я использовал свойство Keep_data = True, чтобы разрешить доступ к данным пикселей для моих спрайтов, и метод read_pixel() для проверки непрозрачных пикселей в перекрывающихся областях. [b]Проблема Описание:[/b] [list] [*]Обнаружение столкновений работает нормально, когда передняя часть персонажа касается передней части монстра. Столкновение срабатывает только тогда, когда их непрозрачные пиксели перекрываются, что является ожидаемым поведением (как показано на изображении 1). [*]Однако, когда персонаж прыгает и приземляется на спину монстра, столкновение иногда срабатывает, даже если их пиксели на самом деле не соприкасаются, а именно тогда, когда соединительная рамка персонажа касается области пикселей монстра (как показано на изображении 2). [/list]Изображение1 Изображение2 [b]Обзор кода[/b]: Вот соответствующая часть моего Класс CollisionMixin, который обеспечивает точное обнаружение столкновений: [code]class CollisionMixin: def collide_widget(self, other): # First, check if bounding boxes overlap if not super().collide_widget(other): return False
# Get the overlapping area between the bounding boxes x1 = max(self.x, other.x) y1 = max(self.y, other.y) x2 = min(self.right, other.right) y2 = min(self.top, other.top)
# Check pixel-perfect collision within the overlap for y in range(int(y1), int(y2)): for x in range(int(x1), int(x2)): # Ensure that both widgets have non-transparent pixels at the same point if self.pixel_collides_at(x, y) and other.pixel_collides_at(x, y): return True return False
def pixel_collides_at(self, x, y): """Check if the widget has a non-transparent pixel at (x, y).""" if not super().collide_point(x, y): return False
# Convert to local coordinates of the widget x_local = int(x - self.x) y_local = int(self.height - (y - self.y))
# Check if the pixel at (x_local, y_local) is non-transparent try: color = self._coreimage.read_pixel(x_local, y_local) return color[3] > 0 # Check alpha channel for transparency except: return False [/code] Вот фрагменты кода персонажа и монстра: [code]class Character(CollisionMixin, Image): """ some properties """
def __init__(self, **kwargs): super(Character, self).__init__(**kwargs) self.size_hint = (None, .18) self.fit_mode = 'contain' self.frame_index = 0 self.idle_frames = [f'assets/cat/idle/Idle_{i:02d}.png' for i in range(20)] self.run_frames = [f'assets/cat/run/Run_{i:02d}.png' for i in range(30)] self.jump_frames = [f'assets/cat/jump/Jump_{i:02d}.png' for i in range(20)] self.source = self.idle_frames[0] self.keep_data = True self.current_animation = Clock.schedule_interval(self.update_idle_frame, 0.05) self.ground_y = Window.height * 0.09
""" Function to handle movement """ [/code] Вот код функции, которая обновляет игру на GameScreen: [code]class GameScreen(Screen): monsters = ListProperty([]) . . def __init__(self, **kwargs): super(GameScreen, self).__init__(**kwargs) self.update_event = None
def update(self, dt): # Logics for generating and moving monster
for monster in self.monsters: # Check for pixel collision if self.ids.character.collide_widget(monster): print('Pixel-perfect collision detected!') # Stop the current animation and movement for the character and the monster self.ids.character.stop_current_animation() monster.stop_current_animation() [/code] [b]Я пробовал:[/b] [b]Проверка ограничивающей рамки[/b]: Я проверил, что ограничивающая рамка Проверка рамок работает правильно — столкновение обнаруживается только тогда, когда ограничивающие рамки перекрываются. [b]Проверка столкновения пикселей[/b]: я использую read_pixel(), чтобы определить, есть ли не -прозрачные пиксели в области перекрытия. В большинстве случаев это работает, но, похоже, возникает проблема, когда персонаж приземляется на спину монстра.
Я создаю pygame для проекта старшей школы, срок реализации которого составляет менее месяца, и использую специальное руководство для PACMAN и адаптирую его для создания своей собственной игры с аналогичной концепцией. Однако, поскольку я следую...
Я работаю над проектом JavaFX, вдохновленным руководством Rysnow по созданию игр на YouTube ( oPzPpUcDiYY Я внимательно следил за руководством, но у меня возникли проблемы с обнаружением столкновений. Несмотря на то, что я распечатал координаты для...
Я программирую на Java 2D-игру с видом сверху и 8 направленными движениями, и во время написания своего следующего большого достижения — обнаружения столкновений — я столкнулся с серьёзной ошибкой. Как описано в вопросе, персонаж игрока (который на...
Я программирую на Java 2D-игру с видом сверху и 8 направленными движениями, и во время написания своего следующего большого достижения — обнаружения столкновений — я столкнулся с серьёзной ошибкой. Как описано в вопросе, персонаж игрока (который на...
Этот класс меня беспокоил какое-то время, но по какой-то причине он не позволяет мне обнаруживать столкновения.
Я перепробовал почти все функции столкновений Pygame, и они не работают, предполагается, что он конфликтует с классом игрока и выводится...