Карты, Деньги, Два копыта

от автора

Привет ,Habr. Сегодня мы начнём разработку своего карточного рогалика про приготовление… рогаликов! Именно эта тема победила в обсуждении под предыдущим туториалом. Работать будет на свежем Godot 4.1. В этой статье добавим карты, «Руку (Копыто) карт» и реализуем функцию Drag & Drop.



Знакомство

Для начала давайте познакомимся с Эдгаром, отважным поросёнком, который мечтает стать пекарем и ради своей мечты отправится в подземелье, чтобы накормить тамошних обитателей свежей выпечкой.

В последующих статьях он будет для нас:

  • Замешивать тесто

  • Формировать рогалики

  • Печь

  • Сервировать стол

С Эдгаром познакомились, вернёмся к нему в следующей части. Пока, Эдгар…


Создание проекта

Создаём проект примерно так:

После создание проекта, заходим в настройки проекта -> Список действий и добавляем действие «click», щелчок ЛКМ

Сцена болванка для карт

Начнём как всегда с создания сцены, которую позже будем наследовать для разных карт.

Главным узлом выбираем Node2D(CardDefault), дочерний к нему Sprite2D(CardSprite) — текстурка нашей карты, дочерние к CardSprite:

  • Sprite2D(CardTitul) — Картинка рисуемая на карте

  • Label(CardName) — Заголовок карты

  • Label(CardDescription) — Описание карты

Дерево объектов:

Выглядеть это должно примерно так:

Давайте загрузим шрифт в Label, на 4 версии, это делается в пару кликов. Найдите где-то шрифт, файл .ttf. Выберите в дереве объектов Label, В инспекторе на вкладке «Control», последний пункт «Theme Overrides», выбираем Fonts -> загрузить и загружаем свой шрифт, поменяйте ему цвет, размер, сделайте всё под себя. Также в инспекторе, найдите свойство Autowrap Mode и установите его в Word (Smart), для обоих Label. Создайте несколько карт. Изменяя текстуру в CardTitul и напишите для них название в CardName и описание в CardDescription. Должно получится примерно следующее:

Чтобы создать карту:

  • Создаём новую сцену

  • Главным узлом сцены выбираем «Инстанцировать дочернею сцену» (Ctrl+Shift+A) и выбираем нашу сцену, которую только-что создали.

  • CardTitul, В свойстве Texture, нажимаем на стрелочку «Сделать уникальным» и добавляем свою картинку.

  • В оба Label пишем текст.

К скрипту вернёмся чуть позже.

Сцена «Руки карт»

Главным узлом сцены выбираем Node2D(CardArm), и дочерние к нему элементы:

  • Sprite2D

  • 4 Marker2D(Card1…Card4)

Каждая метка будет указывать местоположение и угол поворота для карты. У вас может быть больше 4-х, просто у Эдгара влезает только 4 карты. Заливаем текстуру нашей руки и выставляем местоположение для Marker2D. Не большое отступление, так-же выставляйте угол поворота. Карты обычно держат под углом. Для Sprite2D выставляем Z_index = 2

Небольшой лайфхак. Вы можете добавить на сцену, 4 карты, инстанцировав дочернею сцену. Расположить их как вам нравится. Потом записать в Marker2D положения по X и Y и угол поворота

Добавляем скрипт на CardArm и переходим к его редактированию:

extends Node2D #Объявляем 4 переменных на экспорт, это и будут наши карты @export var card1:PackedScene @export var card2:PackedScene @export var card3:PackedScene @export var card4:PackedScene  #Записываем наши паркеры и переменные @onready var _card1_marker = $Card1 @onready var _card2_marker = $Card2 @onready var _card3_marker = $Card3 @onready var _card4_marker = $Card4 #Спрайтик тоже запишем, вдруг пригодится потом @onready var _sprite = $Sprite2D #Каждой карте мы будем присваивать ID, просто пропишите эту строчку var ID = 0  #В функции _ready, создаём наши карты func _ready(): place_card(card1,_card1_marker) place_card(card2,_card2_marker) place_card(card3,_card3_marker) place_card(card4,_card4_marker)  #Функция создания карты, в качестве аргумента, #передаём сцену, которую ставим и маркер - куда ставим. func place_card(scene,marker): #Установили сцену карты var s = scene.instantiate() #Выставили карте поворот s.rotation_degrees = marker.rotation_degrees #Выставили карт местоположение s.position = marker.position #Увеличили счётчик, перед присваиванием, т.к. ID начинается с 1 ID += 1 #Присвоили ID s.ID = ID #Добавили сцену, как потомка add_child(s)  

Переменная ID, потребуется в дальнейшем, чтобы управлять картами.

Синглтон CardMover

Создаём новый скрипт, обязательно проверяем, чтобы он наследовал Node. После создания скрипта, это делается на вкладке «Script» -> Файл -> Новый скрипт. Обязательно назовите его CardMover. Переходим в настройки -> Автозагрузка -> выбираем путь до нашего скрипта и нажимаем добавить. Мы будем использовать Глобальный синглтон, для управления рукой карт. Переходим к редактированию этого скрипта:

extends Node  #Выбранная карта var selected_card_ID = null  #Установить ID func set_ID(ID): selected_card_ID = ID  #Обнулить ID func unset_ID(): selected_card_ID = null  #Получить ID func get_ID(): return selected_card_ID  #Проверить ID #Мы можем взаимодействовать только с выбранной картой  #Или с пустой func check_ID(ID): if((selected_card_ID == null) or (selected_card_ID == ID)): return true else: return false

Тут никаких сложных функций нет, только почти обычные гетеры и сетеры.

Скрипт болванки для карт

Навешиваем скрипт на CardDefault и переходим к его редактированию:

extends Node2D  #Объявили переменные дерева @onready var _card_sprite = $CardSprite @onready var _card_titul = $CardSprite/CardTitul @onready var _card_description = $CardSprite/CardDescription  #Объявили переменную ID @export var ID = "0"  #Объявили локальные переменные var start_rotation:int#Переменная стартовой позиции var start_position:Vector2#Переменная стартового поворота var dragable = false#Выделен-ли объект, для перетаскивания var start_z_index#Стартовый Z-index  #Объявляем все стартовые переменные func _ready(): start_z_index = z_index start_rotation = rotation_degrees start_position = position  #Функция обработки ввода игроком func _input(event): #Если нажата ЛКМ if event is InputEventMouseButton and event.is_action_pressed("click"): #Если клик произошёл в области спрайта карты и проверили ID if (_card_sprite.get_rect().has_point(to_local(event.position)) and CardMover.check_ID(ID)): #Можно перетаскивать dragable = true #Установили ID CardMover.set_ID(ID)  #Если отпущена ЛКМ if event is InputEventMouseButton and event.is_action_released("click"): #Если отпустили ЛКМ в области спрайта карты и проверили ID if (_card_sprite.get_rect().has_point(to_local(event.position)) and CardMover.check_ID(ID)): #Отменили перетаскивание dragable = false #Обнулили ID CardMover.unset_ID() #Если переместили карту, то if(position != start_position): #Убирам стартовый поворот start_rotation = 0 #Меняем стартовое положение start_position = position #Поменяли угол rotation_degrees = start_rotation  #Если курсор мыши двигается if event is InputEventMouseMotion: #Если при движении курсор мыши задел спрайт нашей карты и проверили ID if (_card_sprite.get_rect().has_point(to_local(event.position)) and CardMover.check_ID(ID)): #Убрали поворот rotation_degrees = 0 #Установили поверх других карт z_index = 2 #Задали ID CardMover.set_ID(ID) else: #Проверили ID if (CardMover.check_ID(ID)): #Вернули z_index z_index = start_z_index #Вернули угол поворота rotation_degrees = start_rotation #Обнулили ID CardMover.unset_ID()  func _process(delta): #Если состояние карты перетягивание, то следуем за курсором if dragable: set_global_position(get_global_mouse_position()) 

При создании карт в «Руке карт» мы добавляли каждой карте ID, чтобы была возможность отслеживать каждую карту в руке и взаимодействовать только с ней, если такого не было-бы, то в местах наслаивания карт друг на друга, мы бы брали две карты сразу или поворачивали две карты сразу при наведении.

Код в целом прокомментирован очень подробно, думаю вопросов не должно возникнуть.


Заключение

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


ссылка на оригинал статьи https://habr.com/ru/articles/747206/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *