Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров2.6K

Привет ,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, чтобы была возможность отслеживать каждую карту в руке и взаимодействовать только с ней, если такого не было-бы, то в местах наслаивания карт друг на друга, мы бы брали две карты сразу или поворачивали две карты сразу при наведении.

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


Заключение

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

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии3

Публикации

Истории

Работа

Ближайшие события

19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн