Тема для само-мотиваций. Буду делать версию-113.
И на долю этого номера - выпало пере-ползание на Годот-4.
// ---
Создать промежуточный годот-проект, чтобы частями
перекидывать старые скрипты, и сцены.
Брать лиш нужный код - исчезнут наброски и дубляжы функций.
Создать глоб-скрипты.. g1 и подобные,
чтобы использовать привычные глобалки.
Оформить нормальный годот-проект, и туда забрать успешные куски
промежуточного проекта. Нужно большэ наглядности.
Редактор годота, как редактор локаций, и реадктор юнитов.
Экшн-часть игры - наверно, будет три-мерной, с примитивами.
Нужно найти готовый пример, и его внедрить.
Шаговая часть игры - пусть остаётся дву-мерной, но надо соблюдать
класичную изометрию - обновить геометрию тайлов.
// ---
Шаговая часть..
t_unit --> tbs_u // или придумать дургое название.
Для масива заготовок - есть константа предмета - есть заготовка.
Одно из свойств заготовки - не обязательная указка на ресурс сцены.
И внедрить отдельные сцены tbs_u_captain, tbs_u_soldier.
tbs_u_boat можт содержать ноды верхних сцен.
tbs_town - сцена, куда не допускаем внедрение tbs_u_boat,
потому-что подразумеваем приватную линковку с невидимым отрядом.
Но при этом, чилд-ноды города - простые ноды солдат и капитанов,
которые подразумеваются для авто-линковки, в невидимый отряд.
Вероятно, масив клеток должн быть свойством tbs_field, как
личный масив клеток (переносим из глобал-модуля).
// Почерпнуть свойства из вар-филдов, чтобы это был
// гибкий вариант - поле для глобалки, и поле для боя.
// Хотя надо ешё думать - возможно, это две разных сцены.
Но подразумеваю, что нода, с клетками (приключение или арена),
можт-быть множэственая, и входит в состав ноды tbs_etap.
Тоесть, класичная пара поверхности и подземки, либо набор схем,
аля цепочка-или-метрошка.
// Метрошка - восприятие схем, как _все_сразу_грузим.
// Цепочка - телепорты в братскую схему, с выгрузкой текушей.
Вобшем, загружая этап, можно загружать все схемы, либо _первую.
И сохранка - для этапа - вписывает всё имушество этапа
(пачку обше-свойств, масивы клеток).
(старые подобия t_unit - прямо в масив клеток, как и было).
Сцена, внутри движка - остаётся главным стартером сценария.
Сохранка - лиш промежуточный файл, в юзер-папке, вне-проги.
// читая масив клеток, видим юнит - создаём ноду, и заполняем.
Типаж увиденого юнита: этап.ПОЛЕ.нужная_група.add_child( юнит).
ПОЛЕ - нода, которая образовалась, с шаблона, и в неё накидывают
содержымое, из файла сохранки. Когда встретим новое поле, то
создаём новую ноду поля, и теперь - читаем для нового поля.
// Перекидка отрядов, между полями - reparent.
// Например, это переход капитана в новую часть приключения.
Как-быть с принципом дубляжа юнитов, которые вошли в Арену ?
Считаю, что надо оставить старый принцип - дублировать юниты,
потому-что это правильней, учитывая правила игры, где можно
прервать бой, и этим - отказаться, как-будто не нападали.
Если будут картинки, облегчающие восприятие стихов - будет просто здорово.
Обзор тайлмэпки..
// --- мой отчёт знакомства с комплексной нодой TileMap..
(наверно, подобная пропечатка закрепляет изученое)
Создал пустую сцену, на основе Node2D, синия. Назвал tbs_map.
Добавил чилда TextureRect, и оставил пустым - сюда можно загрузить
скриншот, как фон, чтобы подстраивать _как_надо, а потом - удалить фон.
Добавил чилда TileMap - отличается от подобного, из Годот3.
Вкладка Инспектор - кликаем свойство tile_set, на слове <empty>.
Выбираем (кликаем) строку New TileSet, и кликаем, внизу TileSet,
чтобы переключить _нижний_экранчик. Кликаем плюсик, рядом с ведром,
выбираем "Атлас", и находим подготовленую текстуру, в папке проекта.
Отказываемся от автоматического нарезания тайлов.
Внизу, во втором столбике, слева - свойства атласа - выставляю там
размер своего нормального тайла (Texture Region Size).
// Не нормальный - из нескольких тайл-размеров,
// клик-растягивая, с зажатой кнопкой SHIFT.
Справа, от Paint, есть галочка ластика (Eraser) - тыкаем туда, и
кликаем по тайлам, чтобы убрать инфу об этом регионе.
Например, сменил размер, и надо убрать старую разметку - зажал Контрл,
и растянул рамочку - отпустил кнопку мышки, и стёрлось, что в рамочке.
Не забудь снова нажать на ластик, чтобы отжать его галочку-статус.
Как нормальный результат - должны быть кликнутые светлые регионы,
с белой рамочкой - разметка назначеных тайлов.
// Я выбрал построение текстуры - в один горизонтальный ряд.
Вкладка Инспектор, верхния строка, над строкой Filter свойств - кликаю,
и выбираю строку TileSet - вижу tile_shape - ставлю Hexagon,
и меняю размер клетки (можно его потом подстраивать, покрасив тайлы).
Чтобы вернуться к TileMap - выбираю корневую ноду, и затем снова
кликаю ноду тайлмэпа. Ну либо кликать <previous edited obj>.
Но наверно, правильней - кликать по значку, и по слову TileSet, не
задевая стрелочку вниз - клики открывают и закрывают саб-окно ресурса.
Порисовал немножко тайлами - они плохо пересекаются.
Добиваемся, чтобы Инспектор показывал свойства TileMap,
видим яркую групу "layers" - раскрываем её - кликаем "y_sort_enabled",
распахиваем групу "ordering" - кликаем, и здесь - "y_sort_enabled".
И у меня, сразу наладилась картинка - тайл-спрайты нижней строки,
начали накладываться на верхнию строку.
Важная добавка - в групе "layers", есть плюсик "Add Element".
Я его пару раз нажал, и теперь, тайл-мэп несёт в себе три слоя.
// В каждом слое, я выставил галочку "y_sort_enabled", на всяк-случий.
Не забываем переключать слой, в который красим тайлы - при этом,
тайлы будут тёмными - кликай соседнию ноду, чтобы посмотреть на
результат покраски тайлов, и снова кликай ноду тайл-мэпа, чтобы
продолжать вносить тайлы в ячейки.
// Есть переключатель, рядом со сменой слоя, но соседния нода - привычней.
@onready var tile_map := $TileMap # // не забываем оптимизировать - внял совету, спасибо func _input(event): # // скрипт корневой ноды. #{ if event is InputEventMouseButton: # // if event.button_mask: # if Any_Mouse_Button: # // pass if event.button_index == MOUSE_BUTTON_LEFT: if event.pressed: # // Это момент нажатия - можно не отпускать кнопку, и сдвинуть, но # // нажатие ужэ случилось - забираем первую прицельную позицию. # // var pos2 = get_global_mouse_position() var k = tile_map.local_to_map( tile_map.get_local_mouse_position( )) # // get_cell_source_id // atlas // набор тайлов. # // Слой _нуль, с текстурой, где тайлы, в одну строку, и # // значит, лиш хикс можно сравнивать с константой поверхности. var atlas_xy = tile_map.get_cell_atlas_coords( 0, k) print( "pressed tile: ", atlas_xy.x) elif not event.pressed: # // Момент отпускания кнопки. Если нажали, двинули мыш, и отпустили, # // то учитываем сдвинутую позицию, в момент отпускания кнопки. var pos2 = get_global_mouse_position( ) var v2i = tile_map.local_to_map( tile_map.to_local( pos2)) print( v2i) # // сдвинул тайл-мэпку, вправо - пропечатка правильная. #}
В начале видео, автор создаёт вариант организации - атлас, как один тайл..
( tile_map.get_cell_source_id, как разница между поверхностями)
https://www.youtube.com/watch?v=zZ3VxvlDrnQ
slatazan
Ты в курсе, что такой вот $TileMap оператор разбросанный по функциям - это гамнокод, который при каждом вызове ищет в дереве ноду по имени?
Вместо того, чтобы делать это один раз, например типа
onready var tileMap := $TileMap
Der FlugSimulator
Спасибо, я не знал.
Я думал, при экспорте (аля компиляция), будет замена $TileMap на местные указки.
Теперь - надо соблюдать он-рэди :)
// ---
Трэш-затея:
Итог испытания - сомнительная анимация моря, хотя можно пробануть
разные варианты шума - почти моно-тон.
Вместо g2.random, использовать прокрутку (0, 1, 2, 3), если найти
4 профи-кадра для имиты моря.
const tm_sea_wait_full = 0.042 # длительность кадра, при 24, в секунду. var tm_sea_wait = 0.0 var tm_sea_m = null @onready var tile_map2 := $TileMap2 #// g2.land__water_first первый, из четырёх кадров - шум синего цвета. func _ready(): #{ tm_sea_m = tile_map2.get_used_cells_by_id( 1, 3, Vector2i( g2.land__water_first, 0)) #print( tm_sea_m) #} func _process( delta): #{ if tm_sea_m: tm_sea_wait -= delta if tm_sea_m.size( ) > 0 and tm_sea_wait < 0.0: tm_sea_wait = tm_sea_wait_full for i in range( 0, tm_sea_m.size( )): var v2i = tm_sea_m[ i] tile_map2.set_cell( 1, v2i, 3, Vector2i( g2.land__water_first + g2.random( 0, 3), 0)); #for # #}
slatazan
> Теперь - надо соблюдать он-рэди :)
slatazan
> Я думал, при экспорте (аля компиляция), будет замена $TileMap на местные указки.
Какие еще указки?
Будет замена на get_node("TileMap")
Капля за каплей продвигаю новую версию.
В основном, залип на шаговой части.
Можт-быть сделаю картинку шаговой части чуть красивей.
https://godotengine.org/asset-library/asset?filter=SirRamESQ&cate… &sort=updated
// ---
(Пре-инфо) Смарт-шэйп-нода оперирует рёбрами - талия.
Представь песочные часы - узкая серединка часов, будет поставлена
на технический отрезок, между точками "формы".
<1>--н--<2> // пере-мычка буквы эн, поставлена на отрезок.
Я делаю обводку, в прямом смысле (об вожу клетки воды).
Поэтому, моя текстура - моно-тон, плюс хитрый альфа-слой, где
основную роль играют пикселя верхней половины - они, как берег.
Чем вышэ - тем прозрачней, начиная с не-прозрачной середины.
0.0 // верхния строка пикселей - прозрачна, полностью. 0.3 0.7 // числа примерные. 1.0 // совсем не-прозрачно 0.5 // быстрый спад 0.0 0.0 0.0
После пробы - я увеличил высоту текстуры до 16 пикселей.
// --- GIMP2
Грузим нужный сэмпл-кусочек (цветные пикселя воды, не-прозрачные).
Меню (наверху) Цвет.. Составляюшие.Разобрать
Чтобы получить три слоя.
Моя версия гимпа - создаёт новый файл, с нужными слоями.
Добавляем новый слой, называем alpha, рисуем туда, свои пикселя.
Цвет.. Составляюшие.Собрать - выбрать RGBA.
// У меня создаётся ешё один файл, где всё соединилось.
Экспортируем текстуру, как PNG, и переносим в папку годот-проекта.
// После этого, подправленые пикселя, экспортируем в готовый файл,
// пере-записывая, а годот - сам обновляет, видя отличие даты сохранения.
Так можно выправлять пикселя, запустив игру из редактора.
// ---
Внутри тэст-проекта, создал ноду SS2D_Shape_Closed
Если нужна пила, и есть текстура зубчика, тогда, чтобы текстуру
не растягивали, а ставили зубчик за зубчиком - находим раздел
CanvasItem, раскрываем групу Texture, и там для свойства "repeat",
выставляем вариант Enabled. Там рядом - можно сделать острые пикселя,
если выставить filter, как Nearest.
Раскрыл групу ссвойств Material, клик по знаку кубика, в первой строке
(shape_material, который сразу создан).,
игнорирую все строки fill_ ., клик по слову Array[SS2D_], чтобы
увидеть, и нажать кнопку "Add Element". Появилась строка <empty>,
жму её, выбираю строку "New" - создали контэйнер, в пустой строке,
и можно сюда кликать, на знак кубика, чтобы открыть саб-ресурс,
в сиреневой рамочке. Здесь, установки для первой авто-кисти, для бортов.
Клик на <empty>, выбираем строку "New", и кликаем на появившыйся кубик,
справа от "edge_matarial" - раскрыли фиолетовый саб-ресурс - там, клик
по верхнему свойству "textures", на слове Array, чтобы увидеть,
и нажать кнопку "Add element" (подразумевая добавку слота текстуры).
Над кнопкой плюсика, кликаю по <empty>, и выбираю слово "Load",
чтобы найти нужную текстуру (png или типа того).
Отключаю галочки, чтобы не мешались.. use_corner_, use_taper_.
// Иначе - будут белые квадратики, на прямо-угловых точках.
Остальные свойства "textures_x" - не трогаю, но там подразумевается
тонкий тюнинг, для углов и подобного.
Справившысь с практикой добавки первой текстуры - наверно, можно
посмотреть обучалку, и освоить остальные хитрости плагина.
После создания заготовки, настроив текстуры, делаем копию ноды, и ...
не забываем раскрыть групу свойств Геометрия, и кликнуть, там,
по местной Execute - будет вопрос - отвечаем, ДА, чтобы разлинковать
старый набор точек. Но если эту смарт-ноду планируем использовать,
как _шаблоновый_кирпич, который мы наштампуем везде - не надо
делать разлинковку - пусть все кирпичи используют _один_набор_точек.
Я не трогаю свойство "normal_range" - меня устраивает, что эта кисть
будет красить - весь борт, на все 360 градусов. Мне нужна простая
каёмка, одной текстурой. Если нужны три каёмки (верх, низ, борта),
тогда нужно добавить ешё ТРИ сиреневых элемента "Add Element",
и настроить, там, свойства "normal_range", примерно так..
45 и 90, как верхний борт.
135 и 90, как левый борт.
225 и 90, как нижний борт.
315 и 90, как правый борт.
// Счёт градуса угла, начинаем, справа, в середине,
// и мотаем размер угла (distance), против часовой стрелки.
Все эти элементы - можно рисовать друг-на-друге.
Тоесть, можт быть обше-каёмка 0-360, и добавочные, аля 45-90.
Меняй свойство _сиреневый..z_index,
чтобы нужна дуга рисовалась вышэ других.
Если белая дуга не обновилась, то закрой-открой этот саб-ресурс
(дуга схлопнется, и снова появится - будет вынуждена _заново_нарисовать).
Если нода не обновила свой рисунок, то надо жать "Execute",
в самом верху свойств всей ноды Shape_Base (_refresh == обновить).
// ---
Медленая скорость работы над проектом - ничего удивительного.
Вручную выставляю габариты старых картинок и кнопок - надеюсь,
что будет _новей_правильней.
Сделал функцию сохранения скриншотов - помогает _примечать фиговые места, в картинке игры.
var next_n_screen := 0 #func make_screenshot( alt_name: String = ""): func make_screenshot(): next_n_screen += 1 #var pr_name = ProjectSettings.get_setting( "application/config/name") var pr_name = "action_tbs" # "slatazan_action_tbs" #if alt_name: # pr_name = alt_name #var an_int = Time.get_ticks_msec() // милисекунды, от запуска проги. #"HH:MM:SS" = Time.get_time_string_from_system() // час, минута, секунда. var an_time = Time.get_datetime_string_from_system() #an_time = an_time.replace( ":", "_") an_time = an_time.replace( ":", "") var filename = "user://%s_%s_%d.png" % [ pr_name, an_time, next_n_screen] #user://action_tbs_2024-03-13T15_25_18_1.png #user://action_tbs_2024-03-13T152518_1.png print( filename) await RenderingServer.frame_post_draw var v = get_viewport() v.get_texture().get_image().save_png( filename) #---------
Не получилось сигнаоить кнопкой "Print_Screen",
и сигналю скриншот, через "F12"
func _input(event): #// if event is InputEventKey and event.pressed: #// if event.keycode == KEY_PRINT: # не проходит = буду юзать "F12" #// print("KEY_PRINT was pressed") #// OR if event.is_action_pressed( "print_screen"): make_screenshot( ) #---------
Я многого в твоём тексте не понимаю, а с картинками - гораздо лучше )))
У меня кстати вопрос, про хексагоновые тайлы.
Это ведь Godot4? Там кажется есть такая опция, ты её пользовался?
И еще, есть ли там утилитарная поддержка такого типа координатной системы?
Типа найти соседние клетки, повернуть направо, расстояние между.
Или ты сам всё писал?
Der FlugSimulator
Это Годот-4.
Тайлмэп реагирует на клик и выдаёт мне хикс-угрик - два числа,
под которыми подразумеваем тайл. // как и с обычным квадратным тайл-мэпом.
Годот правильно обрабатывает клик по хексо-тайл-мэпу, во всех уголках клетки.
Найти соседей - примерно, как на квадратной сетке.
Дистанция между клетками - я такого не видел "из коробки".
// --- комент-отрывок из моего скрипта
Что специфичного делать (мне) автору новой схемы приключений ?
Ничего.
Но надо помнить - если кликнутый, в редакторе, тайл показывает
числа-координаты, вышэ нуля - этот тайл будет кликабелен, в игре.
Рутина кликов приключения должна выводить, в игре, динамичную
подсказку: "клетка не доступна" // или подобные слова.
Тоесть, на краях (нуль-негативах) - любые типы поверхности - игнорятся.
// сначала, напечатал один вариант. гы-гы. // ofsX, oY - 1 // сосед на 11 часов. // ofsX + 1, oY - 1 // сосед, по направлению - час. // ofsX, oY // ofsX + 1, oY + 1 // сосед на 5 часов. // ofsX, oY + 1 // сосед на 7 часов. // А потом вспомнил, что их два .. // 1. Для нечётной строки, когда угрик с первым битом.. ofsX, oY - 1 // сосед на 11 часов. ofsX + 1, oY - 1 // сосед, по направлению - час. ofsX, oY ofsX + 1, oY + 1 // сосед на 5 часов. ofsX, oY + 1 // сосед на 7 часов. // 2. Для чётной строки.. ofsX - 1, oY - 1 // сосед на 11 часов. ofsX, oY - 1 // сосед, по направлению - час. ofsX, oY ofsX, oY + 1 // сосед на 5 часов. ofsX - 1, oY + 1 // сосед на 7 часов.
Итого.. планирую, что проекция одного номера клетки - не нужна ...
Идём навстречу логике..
Добавляем свойства (в tbs_unit)..
kle1y
kle2y
kle3y
чтобы назначать кардины из двух номерков, от оригинального тайлмэпа.
Понятно, речь не совсем про клики, а именно про утилитные функции.
Так то есть много вариаций сетапов и координатная арифметика отличается.
Это довольно рутинные функции, просто может что-то сделали, чтобы не велосипедить.
Я не сильно 2D использую, но недавно понадобились - вот и спрашиваю.
Вообще был аддон, для v3 точно, который решал подобные штуки (но там нет встроенных шестигранников).
Можт это видео чего-то полезное показывает (но я не смотрел. гы-гы)
Hex Grid Basics
https://www.youtube.com/watch?v=1qmXFIJU1QE
Из очень полезного есть такие материалы
https://www.redblobgames.com/grids/hexagons/
Не про Godot, но очень основательно.
Красным, намечены клетки, которые авто-закрываются "городом",
и по ним нельзя ходить, чтобы спрайты города _не_кринжовать.
Причал для двух отрядов - выемка, внизу, слева, к двум овалам.
Хотя, не исключено, что город надо делать маленьким,
как спрайт, справа (scale 0.777)
//
// шаговая часть..
Меня раздражает даж медленый скролинг, в фоне, в меню.
Постараюсь не повторять такую гадость (песни ...)
// ---
Авто-враги (другие штабы, против игрока).
Пусть собирают статистику _от_игрока.
Если игрок побеждает нейтралов, то запоминается - состав
отряда игрока, и потери. Если у авто-бота не получается пробить
нейтрал-отряд _пробным_боем, то можно проверить статистику
других боёв (других игроков) - и если составы примерно совпадают,
и хит-поинты примерно похожы - можно бросить жребий,
чтобы выкинуть нейтралов, заплатив потерями, из статистики.
Вобшем, липовая победа.
Ну а если жребий не бросился, то авто-бот можт
иметь план штурмового отряда - сегодня убиваю вредных
солдат, внутри нейтрал-помехи, а завтра (или позжэ) копим
норм-отряд, и добиваем нейтралов, в меченом (автором) тупике.
Вобшем, три вида зачистки нейтралов, для авто-ботов..
1. пресетовый, за счёт накопления _правильной_колоды,
которая указана авто-пилотам за каждый клан, от авторов игры.
2. жребий статистики - шулер-копирование игрока.
3. штурм-отряды (в несколько раз, с возможностью капитан-набегов).
// ---
Версия-113 - готова. Архив скинул на внешний хард-диск.
Фигово, что не удалось сделать _перенос_всего на Годот-4,
но я доволен, что проект не застопорился ...
Лезут мысли по экшн-части - это и есть энтузиазм - надо переключаться.
GridMap Tutorial - TileMaps, but 3D:
(три-мерные тайлы нам помогут)
https://www.youtube.com/watch?v=JxbnStn-BIY
Game Beam Effect VFX:
(визуальные эфекты - луч мега-выстрела)
https://www.youtube.com/watch?v=N8bRwCvhH6g
Gaea - world creation:
(генератор миров, универсальный)
https://github.com/BenjaTK/Gaea
Procedurally Generated 3D Dungeons:
(вдруг захочется генерить много-этажные подземелья)
https://www.youtube.com/watch?v=TPvxWIKHE6Q
Lukky ресурсы и микро-демо тримерной комнаты
https://www.youtube.com/watch?v=r8hCzFHw9vs
https://www.youtube.com/@lukky.
Third Person Controller:
(сделай свою смуту)
https://www.youtube.com/watch?v=C-1AerTEjFU
Boost your games performance:
(оптимизация - брат, 5 сотен кадров, тебе, на днюху)
https://www.youtube.com/watch?v=q1nwCJpjURQ
Post Processing & World Environment:
(настроить свет _как_надо)
https://www.youtube.com/watch?v=3EMG2jGKkdw
COGITO: Wieldables - Immersive Sim:
(настроить пистолетики)
https://www.youtube.com/watch?v=9TK4Tw48nKQ
Stylized Fire Effect:
(или создать огненый кинжал)
https://www.youtube.com/watch?v=R3xMwfrlTI8
Soulslike / ZeldaLike controller:
(? а можт бахнем супер-душу ?)
https://www.youtube.com/watch?v=uxpQYYByv8k
"Cat Prisbrey" продолжэние..
https://www.youtube.com/watch?v=35h5mqNQu-M
"Cat Prisbrey" Плэй-лист..
https://www.youtube.com/watch?v=6WdAxzw8pnE&list=PL35yqmsJzxjsbQ_… xcuukFJxWR-Mb