*Вы можете найти ссылки на предыдущие части в нижней части этого руководства.

В предыдущих частях мы создали пушку (спаунер бомб) и бомбу. Теперь пришло время создать нашего обработчика пушек, который представляет собой высокомерную зеленую свинью, которая будет выкрикивать на нас случайные речевые пузыри и «зажигать» пушку. У этого обработчика пушки нет особой цели в нашей игре, кроме как дать нашему игроку кого-то, кто ему не нравится (например, осла из Donkey Kong). Наша игра могла бы прекрасно работать и без этого обработчика, но что было бы интересного, если бы пушка выстрелила сама по себе?

ЧТО ВЫ УЗНАЕТЕ В ЭТОЙ ЧАСТИ:

  • Как работать с методами RandomNumberGenerator.
  • Как изменить время ожидания таймера.

Давайте создадим новую сцену с узлом Node2D в качестве корневого узла. Переименуйте этот узел в «CannonHandler» и сохраните сцену в папке «Сцены».

Теперь в этой сцене мы хотим, чтобы у нашего CannonHandler было два узла AnimatedSprite2D. Первый AnimatedSprite2D будет служить телом для нашей свиньи, а второй AnimatedSprite2D будет служить речевым пузырем для нашей свиньи.

Переименуйте их в «Body» и «SpeechBubble».

Нам также нужно добавить в нашу сцену узел Timer, который рандомизирует нашу возвращаемую анимацию речевого пузыря после истечения времени таймера. Мы сделаем это, рандомизировав wait_time нашего таймера, то есть время в секундах, которое требуется для обратного отсчета от x до 0. Проще говоря, каждые x секунд наш таймер будет вызывать timeout() и возвращать новый речевой пузырь!

Мы хотим, чтобы этот таймер начал рандомизировать наши речевые пузыри, как только начнется игра, поэтому включите свойство Autostart на панели Inspector.

Выберите узел Body и добавьте к нему две новые анимации: «холостой ход» и «сопоставление».

Для анимации idle перейдите к «res://Assets/Kings and Pigs/Sprites/07-Pig With a Match/Match On (26x18).png» и обрежьте все три кадра анимации. Оставьте значение зацикливания включенным и измените его значение FPS на 3.

Для анимации совпадения перейдите к «res://Assets/Kings and Pigs/Sprites/07-Pig With a Match/Lighting the Match (26x18).png» и обрежьте все три кадра анимации. . Отключите значение цикла и измените его значение FPS на 3.

На панели Inspector также включите свойство «Flip H» под опцией Offset — так как мы хотим, чтобы наша свинья также была повернута влево к нашей пушке.

Выберите узел SpeechBubble и добавьте к нему три новые анимации: «бум», «лузер» и «ругань».

Для анимации boom перейдите к «res://Assets/Kings and Pigs/Sprites/13-Dialogue Boxes/Boom In (24x8).png» и обрежьте все три кадра анимации. Отключите значение цикла и измените его значение FPS на 3.

Для анимации неудачника перейдите к «res://Assets/Kings and Pigs/Sprites/13-Dialogue Boxes/Loser In (24x8).png» и обрежьте все три кадра анимации. Отключите значение цикла и измените его значение FPS на 3.

Для анимации ругательств перейдите к «res://Assets/Kings and Pigs/Sprites/13-Dialogue Boxes/WTF In (24x8).png» и обрежьте все три кадра анимации. Отключите значение цикла и измените его значение FPS на 3.

Теперь прикрепите новый скрипт к корневому каталогу сцены CannonHandler и сохраните его в папке Scripts.

Кроме того, подключите сигнал timeout() узла Timer к вашему сценарию.

Поскольку наша пушка выстрелит бомбой, как только начнется игра, нам нужно, чтобы первая анимация нашего обработчика пушки была нашей подходящей анимацией, поскольку свинья зажжет пушку, как только игра начнет возрождаться. бомба. Мы установим эту анимацию в нашей функции ready().

### CannonHandler.gd

extends Node2D

#when it's loaded into the scene
func _ready():
    #play cannon lighting animation on start
    $Body.play("matching")

Затем мы хотим, чтобы наша холостаяанимация воспроизводилась, если наша бомба движется, и мы также хотим, чтобы наша свинья кричала на нас случайные вещи. Мы можем выполнить это, запустив условное выражение, чтобы увидеть, установлено ли для нашей глобальной переменной is_bomb_moving значение true, и если оно вернется как true, мы сделаем видимым наш узел SpeechBubble (чтобы показать наши речевые пузыри). Мы запустим это условие в нашей встроенной функции processing(), которая будет проверять состояние движения нашей бомбы в каждом кадре. Это позволит нам запускать код, который обновляет узел каждый кадр, и, следовательно, обновлять действия наших обработчиков пушек как можно чаще.

### CannonHandler.gd

#older code

func _process(delta):
    #idle animation
    if Global.is_bomb_moving == true:
        $Body.play("idle")  
        #show speech bubble
        $SpeechBubble.visible = true

Мы хотим, чтобы наша совпадающаяанимация воспроизводилась, если наша бомба не движется, так как это означает, что наша бомба создается. Мы хотим, чтобы наша свинья перестала кричать на нас случайные вещи и вместо этого подобралась к пушке. Этого можно добиться, запустив условное выражение, чтобы проверить, установлено ли для нашей переменной Global is_bomb_moving значение false, и если оно истинно, мы сделаем узел SpeechBubble невидимым.

### CannonHandler.gd

#older code

func _process(delta):
    #idle animation
    if Global.is_bomb_moving == true:
        $Body.play("idle")  
        #show speech bubble
        $SpeechBubble.visible = true    
    #matching animation
    if Global.is_bomb_moving == false:
        $Body.play("matching")
        #hide speech bubble
        $SpeechBubble.visible = false

Нам нужно воспроизвести анимацию, которую мы настроили для нашего узла SpeechBubble, когда он станет видимым. Мы сделаем это, рандомизируя наше значение речи с помощью метода randi(), который будет генерировать случайное целое число. Затем это случайное целое число будет разделено на количество анимаций, которые у нас есть для нашего узла SpeechBubble (которое в нашем случае равно 3). Это означает, что результатом может быть только 0, 1 или 2 — и мы можем использовать эти значения для случайного воспроизведения анимации на основе этого возвращаемого значения.

### CannonHandler.gd

#older code

func _on_timer_timeout():
        #randomizes speech
        var random_speech = randi() % 3 #will return 0, 2, or 2
        match random_speech:
            0:
                $SpeechBubble.play("boom")
            1:
                $SpeechBubble.play("loser")
            2:
                $SpeechBubble.play("swearing")

Наконец, нам нужно рандомизировать время ожидания для timeout() нашего таймера. Это гарантирует, что наш речевой пузырь будет восстанавливаться через случайные промежутки времени, а не каждые установленные x секунд. Мы сделаем это с помощью метода randi_range(), который позволит нам сгенерировать псевдослучайное 32-битное целое число со знаком между от и до (включительно). Мы рандомизируем наш речевой пузырь через любую секунду от 1 до 10.

### CannonHandler.gd

#older code

func _process(delta):
    #randomizes speech bubble randomize time
    $Timer.wait_time = randi_range(1, 10)

    #idle animation
    if Global.is_bomb_moving == true:
        $Body.play("idle")  
        #show speech bubble
        $SpeechBubble.visible = true
    
    #matching animation
    if Global.is_bomb_moving == false:
        $Body.play("matching")
        #hide speech bubble
        $SpeechBubble.visible = false

Ваш код должен выглядеть как это.

Теперь давайте исправим наш узел Body, чтобы он стал немного больше. Измените его свойство «Масштаб» под параметром «Преобразование» на значение, например «1,5». Вы можете изменить это значение, чтобы сделать вашу свинью такой большой или маленькой, как вы хотите.

Затем измените узел SpeechBubble, чтобы он также был немного больше. Измените его свойство «Масштаб» под параметром «Преобразование» на значение, например «2,5». Мы также хотим переместить этот речевой пузырь над головой свиньи.

Сохраните свою сцену и добавьте ее в сцену BombSpawner. Мы хотим переместить свинью перед нашей пушкой.

Теперь, если вы запустите свою основную сцену, ваш обработчик пушки должен «сопоставить» пушку, чтобы создать бомбу, а также изменить ее речь каждые x случайных секунд.

Поздравляем с созданием обработчика пушек! Это изменение в нашей игре могло быть чисто визуальным, но оно добавило жизни нашему генератору пушек. В следующей части мы рассмотрим добавление камеры в нашу игру.

Сейчас самое время сохранить ваш проект и сделать резервную копию вашего проекта, чтобы вы могли вернуться к этой части, если возникнут какие-либо ошибки, нарушающие работу игры. Вернитесь и повторите то, что вы узнали, прежде чем продолжить серию, и как только вы будете готовы, увидимся в следующей части!

Следующая часть серии руководств

Учебная серия состоит из 24 глав. Я буду публиковать все главы в отдельных ежедневных частях в течение следующих нескольких недель. Вы можете найти обновленный список ссылок на учебники для всех 24 частей этой серии на моем GitBook. Если вы еще не видите ссылку, добавленную к части, это означает, что она еще не опубликована. Кроме того, если будут какие-либо будущие обновления серии, мой GitBook будет местом, где вы сможете быть в курсе всего!

Поддержите серию и получите ранний доступ!

Если вам нравится эта серия и вы хотите поддержать меня, вы можете пожертвовать любую сумму моему магазину KoFi или купить оффлайн PDF, в котором вся серия собрана в одном буклете, который можно взять с собой!

Брошюра дает вам пожизненный доступ к полной автономной версии брошюры «Изучайте Godot 4, создавая двухмерный платформер» в формате PDF. Это 451-страничный документ, содержащий все учебные пособия из этой серии в последовательном формате, а также вы получите от меня специальную помощь, если вы когда-нибудь застрянете или вам понадобится совет. Это означает, что вам не нужно ждать, пока я опубликую следующую часть серии руководств на Dev.to или Medium. Вы можете просто двигаться дальше и продолжать обучение в своем собственном темпе — в любое время и в любом месте!

Эта книга будет постоянно обновляться для исправления недавно обнаруженных ошибок или устранения проблем совместимости с более новыми версиями Godot 4.