Тема 4 из 6

Столкновения и монеты

Два спрайта

if arcade.check_for_collision(player, enemy):
    print("Столкновение!")

Спрайты сталкиваются, когда заходят друг на друга хотя бы на долю пикселя. Если они только касаются краями (правый край одного ровно на левом крае другого), это ещё не столкновение.

Спрайт и список

Чаще нужно проверить спрайт сразу со всеми монетами, врагами или стенами:

hits = arcade.check_for_collision_with_list(self.player, self.coins)
for coin in hits:
    self.score += 1
    coin.remove_from_sprite_lists()

Функция возвращает список задетых спрайтов. Пустой список в if — это False, поэтому можно писать if hits:.

Найти спрайты под курсором мыши: arcade.get_sprites_at_point((x, y), sprite_list).

Своё поле у спрайта

Спрайту можно добавить любые поля — например, стоимость монеты или здоровье врага:

coin = arcade.SpriteCircle(10, arcade.color.GOLD)
coin.value = 5

Одно событие — один раз

Проверка столкновений идёт каждый кадр. Поэтому всё, что должно сработать один раз, нужно сразу «выключать»:

  • собранную монету — убрать из списка;
  • после удара — включить таймер неуязвимости и не наносить урон, пока он не кончится.
if self.timer > 0:
    self.timer -= 1
if hits and self.timer == 0:
    self.lives -= 1
    self.timer = 60          # секунда неуязвимости при 60 кадрах в секунду

Откуда пришёл удар

Касание сверху и сбоку отличают по скорости и положению. Игрок «прыгнул на голову», если он падает (change_y < 0) и его низ не ниже середины врага:

if player.change_y < 0 and player.bottom >= enemy.center_y:
    enemy.remove_from_sprite_lists()     # победили врага
    player.change_y = 10                 # отскок вверх
else:
    lives -= 1

Итог

  • check_for_collision(a, b) — True или False; касание краями — не столкновение;
  • check_for_collision_with_list(sprite, list) — список задетых спрайтов;
  • собранное — remove_from_sprite_lists(), после урона — таймер неуязвимости;
  • прыжок сверху: change_y < 0 и bottom >= enemy.center_y.