Вы видите копию треда, сохраненную 12 сентября в 07:35.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Шапка: https://hipolink.me/godothread
Предыдущий: >>919752 (OP)
Архивный: >>914638 (OP)
Не, ну это то понятно. Всегда надо ставить паузу на время сохранения.
Ну, в таких играх как "костры-бомжи-души", например, пауза не предусмотрена по геймплею, поэтому на такой случай, можно реализовать фишку с правами доступа. Один дополнительный энум и дополнительный свич{} в функциях.
Почему?
Потому что действующий и отлаженный механизм сохранений/загрузок подавляет необходимость в "магических числах". Обычно при быстром девелопе мы как делаем? "Нууу, пусть скорость будет 500, а высота прыжка 30, потом переделаю..."
А с отлаженным механизмом, мы можем удобно и красиво вписать:
> var move_speed = SLMGR.get_data(self, 500)
> var jump_speed = SLMGR.get_data(self, -30)
Здесь SLMGR (Save Load Manager) - это тот самый словарь-синглтон, и первым параметром приходит инстанс-нода, из которой при желании можно получить уникальное строковое имя и искать в базе данных как ключ. Второй параметр - дефолтное значение, которое вернётся, если не найдено в базе.
Магические числа вроде как и остались, а вроде как они уже и красиво обёрнуты в метод получения данных, и при необходимости уже файл данных может быть проанализирован отдельно, и скорректирован для задания начальных значений при старте новой игры, и не придётся лезть в скрипты, чтобы переделать где-то в глубине скриптов 500 на 450.
Мы можем внутри SLMGR установить состояние при котором он будет создавать все отсутствующие ключи, при обращениях к нему, и при запуске проекта получить огромный стартовый файл со всеми магическими числами ото всех объектов. Постоянно это делать не стоит. Из этого файла отбираем нужные ключи, правим и уже его грузим при старте игры как эталон начального состояния игровой сессии. Так можно легко реализовать уровни сложности, например, заложив в игру несколько стартовых эталонов с разными дефолтными значениями и пусть игрок выбирает из них перед стартом.
> > var move_speed = SLMGR.get_data(self, move_speed, 500)
> > var jump_speed = SLMGR.get_data(self, jump_speed, -30)
> и первым параметром приходит инстанс-нода, из которой при желании можно получить уникальное строковое имя, объеденить со вторым параметром и искать в базе данных как ключ. Третий параметр - дефолтное значение, которое вернётся, если не найдено в базе.
Быстрофикс.
Да делаю я делаю!
Старые видосы Пети Сканера - и то полезнее.
Я в этом вопросе последовательный сторонник Романа Сакутина: он говорил что так называемый "новичковый код" - это попытка безруких инфоцыган замаскировать свою безрукость. Грамотный, красивый, эффективный код именно новички поймут намного лучше.
Я не спорю, Сакутин сам тоже инфоцыганин, ни в коем случае не смотрите его. Пердаки сгорят нахуй. Я предупредил:
https://www.youtube.com/watch?v=RBk49B0lFaQ
Прозрачный спрайт персонажа на самом верхнем слое, в дополнение к основному или что-то вроде того.
Всё работает в нативной для хексов координатной системе:
q, r, s, где q + r + s == 0
Сделал рендеринг с нуля и всякие helper-классы.
Возможно когда-то оформлю это в полноценный аддон, потому что существующие решения меня не устраивают.
Сделал на этой основе простенькую генерацию мира в нативных для хексов координатах.
Ссылка для тех кто любит копаться в неоформленных проектах: https://github.com/1ort/hexgrid/
Да, у меня была такая мысль, только вот сферу невозможно замостить полностью только шестиугольниками. Понадобится, ЕМНИП 12 пятиугольников дополнительно.
Алсо есть вот такой вариант с псевдо-сферой: https://www.youtube.com/watch?v=mWIIy4eh6bE
Но тут мы имеем свои подводные в виде траблов со спрайтами.
Третий вариант - визуально оставить как есть, но добавить бесшовный wrapping по всем трём осям с возможностью сдвигать карту
> сферу невозможно замостить полностью только шестиугольниками
Видос не смотрел, может там про псевдосферу именно это говорится, что я напишу сейчас. Сферу можно получить "надуванием" куба. В годоте 3 в тайлмапе гексы получали сдвигом тайлмапа по рядам на половину длины. Всё остаётся квадратным, но полностью замощённая сфера - вуаля.
Попадалась странная статья, может ты что поймешь. https://mirror.xyz/avsa.eth/thyWt1xkoxjbV7Ai7AU4xEa-8t50Gj5dJCAj4mmbq-s
> mirror.xyz/avsa.eth
Чота ссыкотно такое открывать. Похоже на фишинг. Зарепорчу-ка я тебя. АБУ узнает своих.
Судя по всему автор Web3- криптоанархист и в другом месте ее не постил. Понимаю твои опасения, вот скрин презентации, вроде бы тут вся суть. Остальное касается irl earth географии
Теперь я умею генерировать сколько угодно островов на глобальной карте. Также могу генерить и тайлы-океаны. Каждый остров может иметь свои настройки (Только я этого пока не реализовал)
Реквестирую идеи, что можно из этого сделать
>926487
Это 2D? Добавь высоту. Камеру сбоку поставь. Сделай что-нибудь в духе цивилизации.
Это 2д, значение высоты у каждого гекса есть. Цвет определяется по матрице высота - влажность (или температура) путём наложения двух шумов.
Вопрос больше про геймплей был
В будущем генератор планет
> что можно из этого сделать
Вселенную-наоборот с Толщеходами. Очевидно же.
Сделой ассет-заготовку для хекс-ртс-игор. Выложи в ассетлиб. Получай донаты.
> Вопрос больше про геймплей был
Идешь в АААА-тред >>605406 (OP) выбираешь подходящий кириллопост и реализуешь.
Ок
Эта штука лишь реализует тип uuid. С тем же успехом можно просто рандомное число той же размерности использовать.
Мимокрок
Тогда пусть генерирует уникальные айдишники на любом из онлайн-сервисов и вручную вписывает в свои сцены.
100 чего, микромортов?
>тормозило
Схуяли оно должно тормозить?
Ты репу открывал? Запускал?
Там нагрузка только в момент генерации.
Сами гексы отрисовываются ровно один раз.
upd.
Оно действительно виснет нахуй при генерации больших карт.
Буду думать как оптимизировать генератор
Ветку не читал, вбрасываю ответ чисто по этому посту.
>как оптимизировать генератор
Разбить генерацию на части. Выполнять каждый фрейм по чуть-чуть, ограничив время выполнения. Например, если в теле генератора есть циклы - за один вызов генерации выполнять только одну итерацию цикла. Опционально отрисовывать прогрессбаром готовность.
const FRAME_TIME = 10
func _process(delta: float) -> void:
far start_time = Time.get_ticks_msec()
while Time.get_ticks_msec() < start_time + FRAME_TIME:
_ var progress = generator.do_generation_part()
_ $progressbar.value = progress
_ if progress >= 1.0: # 1.0 это 100%
_ _ self.set_process(false)
_ _ end_generation()
Да, это не оптимизация. Но зато можно такую генерацию делать загрузочным экраном. И даже выполнять [псевдо]параллельно всему остальному, не мешая геймплею.
Не до конца понимаю как замедление генерации поможет её ускорить, но твой тейк про разделение на чанки понятен.
Алсо годот нормально умеет в мультипоток, так что буду экспериментировать в эту сторону
Я может слишком молод, и слишком много слушаю иностранную музыку, но... А в чём разница?
Я имею ввиду, почему не сделать карты на основе стандартного тайлмапа? А не велосипедных классов.
Потому что это это не гексы, а прямоугольники со сдвигом.
При таком представлении чтобы посчитать дистанцию, покрутить гекс вокруг другого/нарисовать кольцо или линию тебе либо придётся переводить их в трёхосевую систему координат, либо потеть и изобретать велосипед.
Можешь почитать это
https://www.redblobgames.com/grids/hexagons/#coordinates-comparison
>>26656
Я всё ещё могу использовать гекс тайлмапы для отрисовки
> чтобы посчитать дистанцию, покрутить гекс вокруг другого/нарисовать кольцо или линию тебе либо придётся переводить их в трёхосевую систему координат, либо потеть и изобретать велосипед
На дисплей всё равно в двухосевой выводить.
Поэтому чтобы не изобретать велосипед, ты изобрёл три?
1. генерируем в трёхосевой
2. переводим в двухосевую
3. переводим в трёхосевую
Нет, я рили не въезжаю.
Не замедление. Просто за один кадр не пытаться сделать всю генерацию, а выполнять лишь часть, ограниченную каким-то интервалом времени. Тогда у тебя не будет происходить общий зависон.
И давно твои быстрые искаробочные тайлмапы умеют в генерацию карт? Повторюсь - тормозит именно она. Генератору плевать как ты будешь выводить их.
По поводу способа хранения - я думаю как можно это оптимизировать.
>>26665
Я не понимаю откуда ты взял три пункта.
Логика такая:
1) Генерируем в трёхосевой множество тайлов (гексов). Ни генератор ни гексы ничего не знают о дисплее и о том как они будут выводиться. Это просто модель.
2) Отдельная нода (HexLayout) знает как гексы маппятся на 2д-плоскость. У неё получаем множество вершин для каждого гекса и рисуем полигон на канвасе (HexCanvas).
HexCanvas зависит от HexLayout чтобы знать как рисовать гексы.
HexOverlayCanvas - тот же класс что и HexCanvas, только используется чтобы рисовать всякое поверх. Линии, контура выделений и тд чтобы не перерисовывать карту на каждый чих.
>>26667
Спасибо, анончик. Я понял, о чем ты.
> если ты выложишь в открытый доступ
Оно в принципе уже в открытом доступе. Сейчас курю доку, как это оформить в полноценный аддон и выложить в asset library
>пук
И как же должен работать твой шейдер?
Напомню, у тайла на тайлмапе всего 4 соседа. Или 8, если считать диагонали.
Спасибо, анончик, я не самый внимательный...
Естественно, я не буду ебать мозги ни себе ни людям с ебанутыми генераторами соседних тайлов. Я возьму шум, на основе этого шума получу континенты. Этот же шум передам в шейдер, а дальше отсечение больших и меньших значений от уровня океана. Хуяк-хуяк и в продакшен. Пока ты какую-то тормозень велосипедишь, пердонюх.
Игроку ведь похуй как это реализовано. Игроку нужен фан, а не рассуждения о удобстве трёхосевых координат на плоскости.
А я часто замечаю в ассетлибе аддоны, которые делают то, что и так есть из коробки.
Просто движок уже достаточно большой с большим количеством функций, их не все читают и изучают.
Это тебе в другие разделы тематические, там где по психиатрии.
Как по-быстрому поменять цвет фона кнопки при нажатии на неё? Никто такое не делал?
Хеллоу ворлд и синтаксис я так то и из документации могу освоить, но методы и классы вот для меня тёмный лес.
И ещё вопрос. Как происходит перемещение объекта/границы столкновения, перенос множества точек, или объекта в целом?
1) Есть ли ультимативный гайд по интерфейсу? Где на примерах объяснялось бы, как запилить диалоговую систему, штуки вроде чтения записок, журнала заданий, эффектов на экране и все в таком духе.
2) Какой лучше шаблон для рисования тайлмап для 2d платформера использовать? На пике ок? Или есть получше варианты?
> ультимативный гайд
Это как? Один видос на 10 часов? Не встречал. Серии видосов есть. Будешь?
https://www.youtube.com/watch?v=dMYv6InQgno&list=PLcZp9zrMgnmOOQXevC-2CfH67QP3mB4wv
Ссылочка с плейлистом.
И работает шустро.
Да, именно так! А потом всё это выводишь во вьюпорт-текстуру и делаешь дисплеи компов в своей триде-игоре.
И вот такие штуки для целей игры нужно делать мимоходом, не отвлекаясь от основного девелопа.
И вот скажите мне, геймдев не вершина ли айти?
Более того - годот позволяет на изичах вставлять в свои новые игоры свои старые игори. Я так уже сделал, зависимость есть.
>Dev snapshot: Godot 4.3 dev 2
https://godotengine.org/article/dev-snapshot-godot-4-3-dev-2/
Не ждём, а готовимся!
Ну так показывай.
Добавил рандомно раскиданные города и дороги между ними.
Для генерации дорог использовал кастомный AStar3D.
Не смог до конца поправить то, что астар постоянно срезает углы, от чего в некоторых местах находится несколько паралельных дорог
А ты объединяй параллельные дороги в шоссе
И еще вопрос, другой. Загрузил в аудиостим рандомазер несколько звуковых дорожек, хочу чтобы они в случайном порядке играли друг за другом, а он играет одну и останавливается. Что делать?
Со звуками лучше работать на основе сигналов (событий), а не process.
Скорее всего ты в process постоянно вызываешь play(), но в годоте это означает не "продолжить играть, если играет", а "сбросить и играть сначала", Тебе надо самому проверять if not sound.playing: sound.play(). либо пользоваться сигналами.
В годоте сделано спорно на мой взгляд, loop относится не к плееру, а к импортированному файлу. Поэтому в годоте есть два подхода
1. При импорте указать, что файл будет loop. Тогда он всегда будет зациклен. ЕМНИП он не будет присылать сигнал finished. Но это позволяет сделать бесшовный звук. Но если хочется разорвать loop придется как то мутить с таймерами (проверять текущий таймстамп плеера)
2. При импорте указать что файл не loop. Тогда он будет присылать сигнал finished. И в нем ты уже по своей логике можешь начать играть повторно, или другой звук. Но там по идее может быть микрозадержка между повторами.
>Загрузил в аудиостим рандомазер несколько звуковых дорожек, хочу чтобы они в случайном порядке играли друг за другом, а он играет одну и останавливается. Что делать?
По идее то же самое. Нигде не сказано что рандомайзер будет играть их по кругу. Ты либо переимпортируешь все файлы как loop, либо обрабатываешь событие finished и заново делаешь рандомайзеру play, а он уже выберет какой файл играть согласно mode.
По поводу лупа - помню еще поведение разных звуковых форматов отличалось. Может в четверке унифицировали, хз.
Не само поведение, а в 3 импорт ogg был с лупом по умолчанию и надо было заходить снимать галочку с каждого.
О спасибо, то что надо. Правда теперь у меня звуковой сигнал резко обрывается когда значение хелсбара выходит за установленные рамки.
И соответственно еще вопрос с которым мучаюсь, как мне звуки и анимации проигрывать до конца при их смене на другие? Пробовал await animation_finished но что-то не то. Может не так пишу. Думаю что можно сделать через animation tree, но хочется более простое решение. Ну и звуки там не сделать вроде.
Тебе нужен пул аудиопотоков. При проигрывании, будет выделяться свободный, если свободного нет, гасится самый давний. Ну и свою логику использования добавляешь. https://kidscancode.org/godot_recipes/4.x/audio/audio_manager/
>анимации проигрывать до конца при их смене на другие? Пробовал await animation_finished
Сходу сложно что то посоветовать, не зная жанра игры. Ну типа советую конечный автомат (fsm)
Переписал алгоритм генерации дорог. Удалось избавиться от всех артефактов
ибо всякий просящий получает, и ищущий находит, и стучащему отворят.
Литералли ми.
Не используй refcounted в шарпе. Вообще не используй. Совсем. Он только для гдскрипта, который вообще без сборщиков мусора. В шарпе используй стандартные шарп class если тебе нужен POCO объект.
По моему как раз получит повторно, если ты про Node@1, Node@2. Хотя я давно смотрел.
А ты так же динамически задавай имена сам при создании, если ты их создаёшь относительно редко, то например можешь добавлять эпоху в мс или даже в секундах к имени
Сделал через ноду-компонент, которая выдает числовой айди и устанавливает его в мету своего родителя. В мету - чтобы не лезть в родителя и не трогать его внутренние переменные. Прикрепил эту ноду ко всем нужным сценам.
Басикалли, зис:
get_parent().set_meta("uid", some_big_number)
Читаю так:
obj.get_meta("uid")
Впервые использовал мету годота. Нишево, но удобно.
https://github.com/godotengine/godot/issues/18591
https://forum.godotengine.org/t/what-is-the-purpose-of-object-meta-data/27571
Найс. Им про метадату нужно чаще в доках/гайдах упоминать.
Я в блокбенче херачу модельки. Главное не охуевать с комплексной геометрией и тем более анимацией.
> нормально моделить оружие и людских персонажей
Если ты не человек-оркестр, мессия, рождающийся раз в тясячелетие, то даже и не думай о том, чтобы тащить в одиночку такие вещи, качай готовые анимированные модели с миксамнимо, и не выёбывайся.
Тоже недавно вкатился в блокбенч. Неплохо знаю блендер, но понял что нужно упростить модели для скорости их создания. Да и пиксель арт люблю.
=(
Я не считал, технологические предметы не очень долго, там все таки по чертежам можно, может полгода-год, гуманоидов даже не начинал еще, ну как кучу курсов пересмотрел, там столько нюансов в анатомии. Наверное года 2-3 минимум на просто приятную аниме девочку. Да сам процесс даже с готовыми долго занял, освоить риги, миксамо, каскадер, собрать все это в анимейшн три может месяца три-6 занять.
Ну да, а потом идет GTA V
Или например рядом с террарией RDR2
Не все так однозначно
Второй раз продать кубы еще поди попробуй.
А, и если говорить про анимэ, то сразу после гта5 по скачиваниям идет ф2п геншин
1280x720, 0:24
Может, через 10 лет на Годоте8 таки выпущу свой первый Понг
И каковы шансы у тебя повторить визуал РДР2 или ГТА, и каковы шансы повторить визуал майнкрафта? Кроме того, в РДР2 и ГТА люди все равно в геймплей играют, а не в графику. Тогда как графонистые безгеймплейные залупы помирают никем не замеченные на дне стима.
Люди играют в геймплей. В игру. То, что крупные компании способны прицепить к крутому геймплею крутую графику - это бонус, а не основа. Если ресурсов мало и ты работаешь один, то разумней фокусироваться на более важном геймплее, чем на графоне. Я так щитаю. Впрочем, ты и сам это поймешь через пару лет твоего геймдевного приключения.
Вот тут есть объяснение https://dzen.ru/a/YBKPwfJr9iwWW5iD
Но я тупой не понял, каким образом call_deferred() спасает положение? Если отслеживание сигнала уже прошло. Разве не нужно его добавлять тогда в B1?
И вообще, разве отслеживание сигнала не работает всегда? Почему не срабатывает без call_deferred()?
Алсо, объяснение из доки:
>Idle time happens mainly at the end of process and physics frames. In it, deferred calls will be run until there are none left, which means you can defer calls from other deferred calls and they'll still be run in the current idle time cycle. If not done carefully, this can result in infinite recursion without causing a stack overflow, which will hang the game similarly to an infinite loop.
>This method supports a variable number of arguments, so parameters can be passed as a comma separated list.
Ситуацию не прояснило
Не могу позволить себе тратить время на прокачку скиллов в визуал. так что отдаю графон, анимации и саунд на аутсорс. С меня код и все остальное
Я понимаю это так.
Колл деферред, это когда написал пост в тред, отошёл покурить, по пути похавал на кухне, посмотрел ютубчик на толчке, посрал. Покурил ещё раз. Возвращаешься к пека, а там пост твой не отправленный. Вводишь капчу и отправляешь.
Я же описал.
Ждёт пока годот покушоет, покакоет, покурит, рыгнёт, почешет пузо, и присядет отдохнуть. "О, у меня тут деферед коллы навалены, а ну, колл, колл, колл!"
1.https://www.youtube.com/watch?v=G4VEHi3dI6w&ab_channel=ALLTHEWORKS[РАСКРЫТЬ] Сделать деревья через ноды, то создаваемые после модели можно ли будет экспортировать в ГОДО ?
2. https://www.youtube.com/watch?v=zk6aUkl115E&ab_channel=CGIGuru[РАСКРЫТЬ] Создания через привязку листьев через ту же сферу, саму сферу спрятать как альфа каналом, в рендере самого блендера выглядит норм, а если перенести в ГОДО кто нибудь сталкивался ?
Почему они тогда не работают в движке по умолчанию? Или почему их не использовать всегда, типа:
_ready():
call_deferred("eat")
call_deferred("poop")
call_deferred("sleap")
Потому что по умолчанию нужно вызывать методы сразу, а не отложенно. Отложенный вызов наоборот требуется редко.
Оно потом показывается где-нибудь в тултипах, или так и остается только в этом поле?
Я не в курсе. Сам проверь.
А можешь подробнее об этом? Я сам тоже нихуя не умею кроме сценариев и кода, ну может быть дизайна персонажей и интерфейса но это нужно суждение профессионалов уже.
Тоже думал что легко смогу в дизайн персонажей. Хуй там. Чтобы задизайнить оригинального, приятного и удобного для игры персонажа придется постараться.
И нет, анимедевочки с цветыми волосами - не оригинальные персонажи.
Особо не закапывался в это и группами не пользуюсь, но подозреваю что там сравнение строк участвует.
А насчет parent.get_children, можешь сравнить еще просто с массивом нод, который сам заполняешь, думаю это еще быстрее будет.
Я не тот анон.
Вызов call_deferred происходит "между" кадрами.
Полного описания всех процессов, вроде бы, нигде не находил.
Очевидные два - это физика и дерево нод.
Говоря терминами программиста, когда происходит инвалидация итератора
Пример 1 - движок перебирает в цикле все ноды и вызывает у них процесс. Ты в процессе хочешь сделать add_child или remove_child. Если это сделать сразу, то получится, что дерево, которое перебирал движок, уже не соответствует реальности.
По сути то, что описано в статье, этот случай, поскольку связан с _ready, то есть именно с тем в какой момент создаются/удаляются ноды.
Пример 2 - физический движок это черный ящик с коллбеками, внутри него на c++ есть ссылки на разные объекты. Если поменять какой то объект в произвольный момент, то все упадет.
>>27582
Это значит, что сначала в кадре выполнились все _process, и некоторые могли составить список deferred вызовов. Теперь, между кадрами, начинается вызов deferred, всех из списка пока он не опустеет. Но, видимо, если внутри deferred вызова взывать другую функцию deferred, она добавляется в текущий список, который сейчас обрабатывается, логично ведь мы между кадрами и свободны. Но может быть ситуация, что ты из deferredA вызвал deferredB(), а из нее deferredA(), и они будут бесконечно добавлять друг друга по кругу и все встанет
>>27602
Это будет геморно (у тебя исчезает все автодополнение и проверки типов например), это будет вносить задержку (даже откладывать что то на 1 кадр заметно - помню тут анон жаловался что у него персонаж появлялся на сцене смотря влево, а потом флипался смотря вправо), и скорее всего потом появятся ситуации где тебе нужен условный deferred_from_deferred.
В Самодумии мне понадобилось 2 раза call_deferred (конечно потому что это игра на джем и некогда продумывать архитектуру)
1 раз это опять add_child, плюс там я еще жду 2 кадра чтобы я получил доступ к global_transform (такой подводный, ведь если ты deferred add_child, то глобальная координата на этот момент неизвестна)
2. Мне надо было чтобы первый button получил фокус автоматически из _ready и там тоже она была не готова это сделать.
Вызов call_deferred происходит "между" кадрами.
Полного описания всех процессов, вроде бы, нигде не находил.
Очевидные два - это физика и дерево нод.
Говоря терминами программиста, когда происходит инвалидация итератора
Пример 1 - движок перебирает в цикле все ноды и вызывает у них процесс. Ты в процессе хочешь сделать add_child или remove_child. Если это сделать сразу, то получится, что дерево, которое перебирал движок, уже не соответствует реальности.
По сути то, что описано в статье, этот случай, поскольку связан с _ready, то есть именно с тем в какой момент создаются/удаляются ноды.
Пример 2 - физический движок это черный ящик с коллбеками, внутри него на c++ есть ссылки на разные объекты. Если поменять какой то объект в произвольный момент, то все упадет.
>>27582
Это значит, что сначала в кадре выполнились все _process, и некоторые могли составить список deferred вызовов. Теперь, между кадрами, начинается вызов deferred, всех из списка пока он не опустеет. Но, видимо, если внутри deferred вызова взывать другую функцию deferred, она добавляется в текущий список, который сейчас обрабатывается, логично ведь мы между кадрами и свободны. Но может быть ситуация, что ты из deferredA вызвал deferredB(), а из нее deferredA(), и они будут бесконечно добавлять друг друга по кругу и все встанет
>>27602
Это будет геморно (у тебя исчезает все автодополнение и проверки типов например), это будет вносить задержку (даже откладывать что то на 1 кадр заметно - помню тут анон жаловался что у него персонаж появлялся на сцене смотря влево, а потом флипался смотря вправо), и скорее всего потом появятся ситуации где тебе нужен условный deferred_from_deferred.
В Самодумии мне понадобилось 2 раза call_deferred (конечно потому что это игра на джем и некогда продумывать архитектуру)
1 раз это опять add_child, плюс там я еще жду 2 кадра чтобы я получил доступ к global_transform (такой подводный, ведь если ты deferred add_child, то глобальная координата на этот момент неизвестна)
2. Мне надо было чтобы первый button получил фокус автоматически из _ready и там тоже она была не готова это сделать.
> Если поменять какой то объект в произвольный момент, то все упадет.
P.s. тут они кажется делают так - в годоте есть "копии" физических объектов из физдвижка, если ты что-то поменял, то ничего не упадет, но физдвижок просто перезатрет твое изменение в следующем кадре. Чтобы вносить изменения, надо делать это только там где предусмотрено - в integrate_force() или через physicalserver.set(...)
1. Да, в геометри нодах надо чтобы была нода realize instances и можно сделать apply и получить статичную модель. Которую можно обычным образом экспортировать. Но моделька может выходить тяжелой.
Хотел как то воспроизвести нечто подобное нодам в самом годоте, чтобы одинаковые листики рисовались через multimesh, но руки не дошли.
2. Не понял вопрос честно говоря. Если сфера отдельный объект, то ее лучше как то совсем скрыть или вообще использовать только позиции листьев, а саму сферу удалить.
Вообще самые легковестные деревья не используют отдельные объекты листьев. Самое простое дерево это два квадрата пересекающихся с текстурой с листьями и прозрачными дырками. Ну или как вариант если ты запечешь на эту сферу текстуру листьев.
Можешь так же поискать что именно для деревьев в годоте делали. Этокак минимум какой то генератор попадался, и еще плагин для импостеров (это когда 3д дерево впекается в 2д спрайт, для рисования кучи деревьев на большой дальности), и всякие плагины на scatter (чтобы расставлять кучу одиинаковых объектов автоматически через multimesh)
Ну, тащемта секретов тут нет. У меня есть четкое видение визуала/звука, есть референсы, нормально составленное тз. Далее идут на какой-нибудь сайт по типу https://gamedev.ru и там на форуме ищу людей для разовых заказов по своим нуждам (там есть раздел с поиском работы)
Благодарю!
Спасибо большое за ответ.
По поводу 2 квадрата с текстурой дерева, и прозрачным альфаканалом видел, так делают и траву и кусты и деревья, но если посмотреть на них сверху выглядит стремно.
Что до тяжести, больше всего это и напрягает, посмотрел кучу видосов как делают растительность разного рода в блендере, вроде часть простая, но выглядит тяжелой. Даже про те же 2 квадрата, видел много кто так делает, но говорилось в одном из видосов, что создания большого количества такие моделей нагружает видюху, посколько она пытается высчитать кучу наложений друг на другу прозрачных альфа каналов, и ладно если у тебя дерево из 2 таких 2д спрайтов, а если каждая ветка такая?
Я вот и думал, лучше ли склипать 2-3 дерева lowpoly самому, или поебаться с генерацией деревьев этих, с помощью стороних программ или же аддонов к годоту.
Там есть спец режим прозрачности для материала листвы, alpga scissor и с 4-ки alpha hashing
https://docs.godotengine.org/en/stable/tutorials/3d/standard_material_3d.html#transparency
Конечно лучше слепить самому, нр советую скачать на скетчфабе разных, засунуть в движрк и пощупать производительность и визуал.
Как, например, подключить джава-док и вообще нужен ли он, если у меня, скажем, сотня квестов всего?
Все ли ок?
Тут не ок. У тебя потерянные ноды-сироты болтаются. В идеале там должно быть 0. Ты где-то удаляешь ноду у родителя, но не освобождаешь ее.
Тач-кнопки для перпеключения режима огня не хочу - моя дрочильня слишком проста для кнопок. Один палец / два пальца кажется неудобным - моя игра в горизонтальном режиме, а у людей, как правило, всего по одному большому пальцу на каждой руке.
двойной тап, жест, долгое нажатие
Визуальную кнопку переключения типа огня попробуй.
А вообще, не забывай, что для мобил есть геймпады, и что при наличии геймпада в ОС, годот автоматически видит его и принимает с него инпут. И поэтому забинди управление на геймпад, и при активации этого управления убирай с экрана всё что относится к тач-управлению. Твои игроки тебе спасибо скажут. Посоветуют твою игру друзьям. Станешь богат и знаменит. Тяночка твоей мечты сама найдёт тебя и сама предложит тебе встречаться. А если у тебя уже есть тяночка, то она не откажется от жмж. А если ты тяночка, то инвертируй предыдущие два предложения на кунчика.
>А насчет parent.get_children, можешь сравнить еще просто с массивом нод, который сам заполняешь, думаю это еще быстрее будет.
Проверил. Все так.
У mr D дошел до этого урока но он во первых нихуя не обьясняет + он на старой версии и там дохуя чего изменилось
Вот лежит на карте предмет нагенерированый главной сценой и добавленый как чайлд сцене items, содержит текстуру и имя, вот функция у персонажа get_item на кнопку
Как мне сделать чтобы она проверяла рядом ли предмет с персонажем, удалить его с карты и добавить в инвентарь grid conteiner как дитятко
У меня голова дымится от этой хуйни
Делай коллизию персонажа/мышки и предмета. По коллизии удаляешь предмет из мира и добавляешь в инвентарь.
Я бы еще советовал подумать нужен ли тебе инвентарь вообще, или достаточно простого неинтерактивного списка.
>По коллизии удаляешь предмет из мира и добавляешь в инвентарь.
Как логика кода выглядит? Ее в скрипте персонажа писать?
> У меня голова дымится от этой хуйни
А игра ещё не начиналась, заметь. А я говорил, геймдев - вершина айти. Без 10 лет формошлёпства в тырпрайзе в геймдев соваться - сомнительная затея.
>>27999
> Как логика кода выглядит?
1. Предмет - это абстрактная математическая сущность. В программировании это будет отдельный класс.
2. У него будут поля, указывающие на его представление в интерфейсе инвентаря и на его представление в игровом мире.
3. Предметы игрового мира должны быть через связь с базой данных быть привязаны к классу инвентарного предмета, например через композицию, иметь накинутый сверху компонент "подбираемый предмет"
4. Вот в скрипте этого класса логику и надо писать. В общем случае, нужны методы, задающие поведение при подборе игроком получающие от игрока ссылку на его инвентарь, делающие там соответствующие записи и уничтожающие свой объект-хост вместе с собой (или выключающие видимость, но это уже вопросы оптимизации, опустим пока).
5. Инвентарь это тоже должна быть математическая абстракция, манипулирующая через сигналы и ивенты своим отображением в интерфейсе, но зачастую код инвентаря ебашат в сам ГУИ. Осуждаю.
6. Что бы ты не выбрал, логика инвентаря у тебя всегда будет разновидностью CRUD из тырпрайза. И если ты в геймдев из тырпрайза пришёл, то с крудами проблем не должно возникнуть. Просто пилишь круд. И всё как бы. Ему приходят новые записи в базу данных, он их выводит в листбокс. Можно перемещать, изменять, удалять.
7. В некоторых играх в инвентарь можно пихать объекты контейнеры. Некоторые объекты могут стакаться, это можно реализовать через создание контейнера идентичного по внешнему виду предмету который стакается. В общем, полезно уметь создавать коллекции типа "коллекция".
Ты - это я, антоша.
Тоже скоро начинаю пилить инвентарь. И сука, пока это самое сложное из всего. А еще его нужно будет как-то с сохранениями коннектить...
>Без 10 лет формошлёпства в тырпрайзе в геймдев соваться - сомнительная затея.
Либо надо СИЛЬНО упрощать. Берете свои графонистые фуллбоди 3д, свои открытые миры, свои инвентари, и делите все эти хотелки на 10.
>>28008
Упрощая, можешь сделать так: у каждого предмета area2d. У персонажа area2d. Делаешь сигнал на их коллизию. Персонаж наступает на предмет. У персонажа триггерится сигнал, в нем вызываешь функцию get_item, передаешь ей предмет, с которым произошла коллизия. Добавляешь текстуру и имя предмета в инвентарь. Картинка и текст. Тут я хз как ты добавлять будешь - зависит от реализации твоего инвентаря. Я бы сделал тупо словарь имя:картинка. Сам предмет удаляешь из мира через ту же функцию внутри игрока, remove_child, queue_free. Если предмет нужно из инвентаря-словаря поставить обратно в мир, берешь имя из словаря, по нему берешь сцену, создаешь новую сцену и ставишь ее в мир в нужное место. Из словаря удаляешь.
Все, проще не будет. Если все еще сложно и непонятно - отложи этот проект, сделай 3-4 игры попроще, потом вернешься с опытом.
Кстати, на счет CRUD. Логика - логикой, но насколько вообще реально и удобно использовать sql для подобных задач в связке с годот? Есть ли адекватные примеры/туториалы?
Хммм, ну это надо разобраться как сигналы юзать, вроде понял
Этот ютубер просто делает сцену, в нее сует плашку текстурой, в нее скролл контейнер, и в нутрь него грид контейнер
Предметы добавляются в грид контейнер как дети и сразу отображаются, хз может потом поменяет в следущих уроках
Код игрока:
var Main_instances = GlobalResourceLoader.Main_instances
func _ready():
Main_instances.Player = self
Ресурс:
extends Resource
class_name Main_instances
var Player = null
Ресурс лоадер
extends Node
var Main_instances = preload("res://Resources/Main_instances.tres")
Что не так блять? Что этому говну не нравится? Почему он сука просто не может закинуть player в player блять?
Не работал с ресурсами, а что непонятно в ошибке? У Resource нет поля Player. Проверяй что у тебя загрузилось. Может быть надо объявить тип переменной. А откуда вообще тут появилась нужда в ресурсе?
>У Resource нет поля Player
А это что?
var Player = null
>Может быть надо объявить тип переменной
Делал вот так, тоже не помогает
var Player:CharacterBody2D = null
>А откуда вообще тут появилась нужда в ресурсе?
Нужно сконнектить скрипт, где меняется уровень, когда player проходит через дверь
> Упрощая, можешь сделать так: нахуячить абы чего абы куда и через неделю игра в производственном аду крошится в рандомных местах, предметы дюпаются, сейвы херят прогресс квестов, нихуя не можешь понять, где в этой каше с лапшой что фиксить.
Упростил твой пост до одной строчки.
В том то и дело, что var Player - в Main_instances, а тебе пишет, что Player нет в Resource.
А что если написать var Main_instances : Main_instances= GlobalResourceLoader.Main_instances
А не может ли быть этой путаницы из за того что у тебя имя переменной и имя класса одинаковое? Так вообщем то не принято делать. Делают к примеру Player player.
спрайт никак не перемещается или типа того
вот список из которого выбирает имя по индексу от нуля до двух
далее _ready вызывает функцию set_item которая передает в нее имя из списка, в set_item уже имя подставляется в название ссылки на файл
На что он блять ругается?
Дико извиняюсь что надристал в тред
Root
UI
Control
Plashka (текстура)
Scroll conteiner
Grid conteiner
Item apple
Item hui
Tilemap
Player
Items on map (сюда добавляются предметы при генерации)
И у меня плашка интерфейска как бы привязана к тайлмапе и двигается вместе с ней пока я бегаю, а надо чтобы в углу экрана постоянно была как везде сделано
Как фиксить?
Один из способов это размещать весь гуй дочерним к CanvasLayer.
Там бывают неочевидные приколы, но для новичка простой способ
Включаются в дебаггере.
У меня словарь с "айди объекта: [аррей даты]", где аррей - 10к записей. И так с каждым объектом. Объектов 5-15 на уровень. Потери производительности не заметил, памяти 400мб улетает. Зависит от твоих данных короче.
Но как мне его название добавить в словарь инвентаря, который лежит в скрипте игрока, как ключ с дефолт значением 1?
Как вообще можно реализовать словарь инвентаря, чтобы из него можно было и название и количество получить?
1) Есть игрок, есть дверь (в скрипте, куда ведет дверь и т.п.).
2) Игрок рядом с дверью -> func _on_body_entered() даем игроку знать, что он рядом с дверью
3) Игрок жмет кнопку, дверь должна отправить сигнал с данными о себе в сцену, которая меняет уровень
Так вот, как двери дать знать, что игрок нажал кнопку? func _on_body_entered() отрабатывает то единожды, а не следит за состоянием игрока.
Через синглтон пилить с отслеживанием переменной через process? Или через _on_body_entered давать player данные двери в какие-нибудь переменные, и уже оттуда посылать сигнал?
Есть изящное решение?
добавить чарактеру аналогичный area (возможно чуть другой формы/размера, например больше для интеракций, меньше для хитбокса), поместить его в отдельный слой физики по необходимости.
Кроме body_entered есть и body_exited
А, точно... Спасибо анонче
Добавлю что делаю с расчетом на слабые мобилки, поэтому надо что-то реально простое.
if жопа.has(хуй) = false:
Жопа += хуй
?
Уже нашел ответ в документации
Попробуй этот аддон https://github.com/HungryProton/proton_trail
Я им вроде пользовался в 3-ке, но сейчас он для 4-ки.
Другие аддоны для 4-ки требуют или с++ модуль или C#
Еще в 4-ке вроде какая то специальная нода добавлена parcticle trail, но я не знаю как она на мобилках и вообще.
Спасибо.
Подошло решение через обычные партикли, но с лимитом фпс в самих партиклях. Свойство fixed_fps. Поставил 25, ведь как известно больше глаз не видит!!1 Тем более глаз мобильных геймеров.
А там же ещё из-за того что удаляю "|" длинна строки меняется постоянно, так что даже по длине не посчитать.
Блятд вроде справился. Смотрю каждый раз равен ли индекс длине всей строки.
Попробуй такой вариант: в таймере отрезаешь от входной строки один символ, проверяешь его, если он нужен, помещаешь его во вторую, выходную строку. Если символ не нужен, он просто исчезает, а входная строка уже обрезана. Если входная строка нулевая - процесс завершён.
Хотя... Этот вариант ничем не лучше. Тоже два ифа будет.
И ниже функцией буду в переменную "жопа" присваивать элемент списка "хуй2"
Жопа = жопа[1]
То жопа останется списком или станет переменной со строкой "хуй2" внутри?
> станет переменной со строкой
Это. Но если ты сделаешь статическую типизацию:
> var jopa : = []
То при попытке записать в неё строку проект упадёт в исключение.
Зачем так делать? Заведи новую переменную,иначе потом не разберешься в лапше которую наворотид.
Тогда я блять непонимаю почему обьекты недобавляются в массив инвентаряй
>>28471
Это так подбираемый предмет устроен
Там с списке разные названия итема, одно из которых выбирается рандомно и так устанавливается спрайт для него
Простенькая система
Но почему то он не хочет добавляться в грид контейнер, домой приду скину код
Звучит как жуткий оверинжиниринг. Зачем удалять это из строки? Если ты делаешь какие-то спецэффекты при выводе, просто пропускай этот символ, выставив нужные тебе флаги и все.
Упрощенный псевдокод
while index < my_string.length():
_var c = my_string[index]
_if c == '|':
__flipflags()
_else:
__print(c)
__break
_index += 1
Вопрос не в этом. Вопрос - зачем делать так?
Почему нельзя написать other_var = var[key]? Почему понадобилось именно в эту же переменную присваивать var = var[key]?
Или ты пытаешься изменить что-то в словаре?
var[key] = new_value
var["твой_ключ"] = new_value
Словари работают примерно одиноково во всех ЯП
Если ключа нет, создается пара ключ-значение
Если ключ уже есть, то значение для этого ключа заменяется.
> Тогда я блять непонимаю почему обьекты недобавляются в массив инвентаряй
Ну если ты не понимаешь, нам-то как понять? Экстрасенсов в тред не завезли. Показывай портянку кода, что ты там нахуевертил?
Ну генерится при запуске сцены условное яблочко, нахуй там продолжать хранить список названий итема для генерации если можно туда просто присвоить имя и список как бы самоудалится
Как с заводика прийду
В самой сцене итема хранится список с названиями и при добавлеии экземпляров этого итема на условную карту у него под функцией _реади выбирается рандомное имя и присваивается уже в туже переменную где был список
Ты не там оптимизируешь. Не неси хуйню. Ты сам себя запутаешь такими широкими трактовками содержимого переменных.
Хули там путаться
item name = [apple, rock, stick]
_ready():
Var a = randi_range(0, 2)
item name = item name[a]
И все, предмет лежит на карте пож своим именем и больше не содержит списка
>Хули там путаться
Чел, через неделю ты уже в этом не разберешься. Это ты сейчас думаешь такой ого как круто наебал систему, и че эти тупые погромисты так не делают.
Ну ладно, о вкусах не спорят. На мой вкус было бы лучше:
> _ready():
>
> item_name = ItemManager.get_name()
Я только вкатываюсь и сделал по гайду с ютуба, но я не понимаю где по твоему я еще буду юзать эти одинкавые списки в каждом экземпляре итема?
Ну опять, же код там в зависимости от потребностей. Чисто теоретически представим, что у нас есть необходимость раздавать предметы из некоторого набора, по некоторым критериям. Мы заводим список предметов. В методе get_name можем параметром указать критерий. Для критериев заводим энум. и вот это всё будет выглядеть так.
(Щас наваяю код и запощу.)
Пользоваться так:
> item_name = ItemManager.get_name(ItemManager.Level1)
Да, длинно. Да, многословно. Зато код высокоподдерживаемый, мидловский. Любому мидлу видно, что откуда берётся в этом коде.
Там вверху закоменчен еще более сложный код. Можешь пока на него не смотреть, так, для общего развития добавил.
Можно покороче сделать. Вопрос вкуса, опять же.
> _ready():
> var im := ItemManager.new()
> item_name = im.get_name(im.Level1)
Добавлена 2 года назад.
Ну да, я сам когда запостил, был уверен, что к этому моменту доебутся. Цикл с постусловием нужен так редко, что в современных языках про него забывают.
А дублирование кода да, устранять надо. Еще и мидлом назвался, ага. (эт я про себя)
Вот варианты как без дублирования кода. Просто с дублированием цикл иногда не будет выполняться ни разу, а в пикрелейтедах всегда один раз или больше.
Код повторил за mrD с ютуба но что то может проебал
func clear() закомнетировано для теста
Вот я.
> почему в гридконтейнер не добавляются предметы
ЯННП, но возможно там туториал по трёшке, а ты не глядя лепишь в четвёрке.
А картинки в папке Sprites/items есть? Она выглядит пустой, а TextureRect подсасывает картинки по пути с файлами 0.png, 1.png итд
Итем в радиуе игрока вызывал у него функцию _pick передавая имя
но потом удалялся, а скрипт _pick обращался опять к итемуб запрашивая имя и количество, а он то блять удален! и вылетала ошибка
Чутка переписал и сразу в функцию передаю и имя и количество в функцию
думал конечно что сначала функция у игрока выполнится и он потом удалится а оказывается хуй
>>28639
есть, просто это вид навигации такой, в одном окошке папки в другом их содержимое
стоит упомянуть что я скорее всего проебал момент где надо в итем писать функцию _пик
Ну ок, малаца, учись, постигай. Ждём шедевров от тебя. Обращайся за помощью. Поможем.
Жоская игра на пикче, выглядит жоще серии дарксоулс.
Создать новый проект и по очереди забрасывать ресурсы из старого, пока не произойдёт крош. Тогда и узнаешь, что вызывает крош.
Не вариант, он падает во время игры в неопределённые моменты, одна и та же последовательность действий не ведёт к его повторному падению.
>если игра просто закрывается и ничего не пишет в лог?
Уверен что у тебя ни в каком забытой коде не вызывается get_tree().quit() или подобное? Я помню на бете сегфолт поймал, но даже он в лог написался.
Ну как бы да. Ты как бы по факту сейчас мозги нам всем присутствующим ебал. Чистый годот без дополнений (а связка с шарпом выполнена как аддон, просто это упрятано с глаз) всегда пишет в лог и в консоль, когда падает.
Спасибо, а то я уже хотел колхозить сигнал к другому скрипту
0.6 чего епта?
все это вызывается функцией _process(delta): каждый раз когда у обьекта есть скорость
Условное значение, которое он посчитал достаточно маленьким, чтобы остановить на нем движение. Чтобы считать что объект пришел к своей цели.
это вообще функция для того чтобы если моб упрется в стенку то немедленно перестал идти и выбрал другую точку на карте для прогулки
так это 0.6 чего? координат? сантиметров? пикселей?
Godot uses the metric system for everything in 3D, with 1 unit being equal to 1 meter.
https://docs.godotengine.org/en/stable/tutorials/3d/introduction_to_3d.html
спасибо
Если 2д то пикселей
Если 3д то абстрактных единиц (которые можно считать метрами, а можно не считать)
Хочу сделать монитор на столе с текстом, кнопками и прочим, стоящий под небольшим углом к игроку
и еще в видосе чел сделал так
var healf : float
это как понять? почему не через знак "=" ?
https://www.youtube.com/watch?v=y3faMdIb2II
а тут он вообще пишет
var atack_damage := 10,0
Нахуя через двоеточие?
> Нахуя через двоеточие?
Автовыведение типа. Двоеточие - это токен указания типа, если тип не указан, а стоит равенство, то тип выводится из значения после него, в данном случае 10.0 - будет float
Гениальная хуйня, похоже не уёбищное присваивание в паскале, но в отличие от него имеет смысл, а не просто понтуется, как паскаль.
так оно же и просто через "=" само определяет тип, разве нет?
чето не догоняю, нахуя отдельно указывать тип данных
> разве нет?
Нет. Просто через равно присваивается как бы динамически, но по факту в тип Variant, который выполняет функции динамической типизации, что ооооочень медленно и из-за этого на годот постоянно ругались, что гдскрипт медленный. Поэтому Хуан сделал статическую типизацию, да ещё бонусом сделал автовыведение типа.
Мы это выше обсуждали, без конкретики:
> var d = 2
> d = "two"
Это работать будет, d поменяет вариантное значение-инт на вариантное значение-строку.
> var d := 2
> d = "two"
А тут вывалится эксепшн. Потому что d автоматически выведено как int и строку больше не примет.
Купи электронные
да блядь, я уже заебался отвлекаться на всякую хуйню в интернете. Работаем ребята!!!
Этот мем старше тебя.
Анон, без обид, но все вопросы, которые ты спрашиваешь - не относятся к движкам напрямую, а являются общими знаниями для геймдева, а такая вещь как паттерны так и вообще - фундаментальна для кодинга.
Нахуй тебе связка с годотом?
Изучи всё это в связке с си и консолькой, если всё будешь понимать, то реализация в годоте не составит труда, более того, обладая знаниями, ты сам будешь видеть, какие паттерны применялись в архитектуре годота, какие методы объектов редактора оставлены для реализации паттернов для тебя, и т.д.
Извини, но сейчас я в твоём посте знаний не вижу, я вижу, что ты выучил умные слова, но смысла их не понимаешь, и что самое страшное (для тебя), ты уверен что есть где-то волшебные книжки, в которых всё написано так, что ты мигом станешь новым Кодзимой.
Это так не работает. Пиздуй в /pr/ и смотри там в закрепе литературу. Вот её и читай. В геймдев рано тебе.
Смотри туториалы про систему компонентов. Можешь на х2 смотреть и на английском, не почувствуешь себя тупой школотой.
Пишешь что важно в файл
@
Не важное в файл не пишешь
При загрузке читаешь важное
@
Не важное считаешь заново
Базовый гайд. Базовитый. Возбазвлённый. Схоронил. Отчеканю в золоте. Внукам покажу.
Иронизировать не надо, к этому всё и сводится, дальше идут варианты в зависимости от архитектуры и в принципе игры. Если ООП - у каждого объекта должен быть своя функция сохранения/загрузки, если ЭКС - то по всем проходишься и сохраняешь у кого какие компоненты.
Мне нравится сохранение через синглтон-менеджер. Буду всегда воспевать его и форсить. (Пока не найду идею еще круче).
Как понять? Переменная становится узлом контроля для узлов в сцене и глобально меняет видимость?
>(вася_пупкин as Человек).пукнуть(вонюче)
>(вася_пупкин as Двачер).постить_на_дваче(хуйню)
Приведение типов это называется в информатике.
Совершенно новый проект, который я создал только-только накатив себе one-clock deploy. Гугл сказал что можно использовать button, но не уточнил каким именно образом
Ладно, пока я тут думал, я решил просто обернуть их в Control подогнав у них custom_minimum_size под сами кнопочки. Хз насколько это хорошее решение, но оно пока у меня работает
Это плохое решение. Тач-функционал есть и у зелёных кнопок. А синие тач кнопки нужны не для интерфейса, а для внутриигровых действий.
Вот тебе пять секунд гугла за разницу между зеленой кнопкой и синей тачскринкнопкой.
В игровых интерфейсах мультитач используется редко, мультитач используется именно в самих играх, поэтому такой функционал вынесли в синие ноды.
Если тебе нужен от кнопок мультитач, несложно его самому реализовать на зелёных кнопках, там десяток строк кода будет.
Базовые рецепты текстом
https://kidscancode.org/godot_recipes/
Также, на гитхабе сотни проектов-примеров которые можно скачать и посмотреть архитектуру.
Это называется каст, приведение типов. А конкретно, up-cast, приведение к базовому типу.
В массиве тебя объекты разных типов - TextureRect, Label. Но все они наследуются от Control.
Конкретно в данном примере - нахрен не нужно. А вообще
Плюсы
-Автодополнение.
-Доступ только к полям/методам указанного класса. Не будешь использовать поля label у texture_rect.
-Проверка ошибок во время разработки - если в массив попадет спрайт, программа здесь остановится с ошибкой.
Минусы
-Производительность. Если всю программу обмазать таким, наверное просядет на пару процентов
-В релизе программа будет падать. Надо бы еще обмазывать проверкой if control is Control и предусматривать что делать в таком случае. Возможно все равно падать.
Где полезно, например наоборот down-cast:
В обработке ввода, тебе прилетают InputEvent. У базового InputEvent мало свойств. Но если сделать что-то вроде
var mbevent = (event as InputEvenMouseButton)
if mbevent: var pressed = mbevent.pressed
Получаем доcтуп к полям которые у класса-наследника.
Можно писать и без каста, но с ним чуть удобнее разрабатывать.
> У базового InputEvent мало свойств. Но если сделать что-то вроде
> var mbevent = (event as InputEvenMouseButton)
> if mbevent: var pressed = mbevent.pressed
В четвёрке еще круче сделали. Если ты пишешь
>if event is InputEvenMouseButton:
внутри этого ифа для event происходит апкаст автоматически и подтягиваются методы в автодополнеии. Лично пользовался. Радовался.
Спасибо, нацепил таки на кнопочки скрипты с нужными строчками и всё вроде работает как надо
Чел если хочешь вкатится, то просто вкатываешься и все. Читать книжки, смотреть гайды ДО вката полная хуйня и нахуй не нужно
Открываешь в офф документации гайд по 1 игре, делаешь всё по пунктам и все. Просто чтобы ты понимал какие где находятся кнопки.
Дальше уже начинай делать собственную игру, очевидно не 3д открытий мир, а простенькую 2д, считай это даже не игрой, а демкой, над идей можешь не запариваться.
И уже в процессе гуглишь конкретные вещи, по типу как сделать игрока, чтобы двигался и так далее.
И уже сильно позже, когда у тебя получится кривой багованный кал, который невозможно дальше разрабатывать, ты начнёшь понимать как надо было делать, какая должна быть структура проекта, как подходить ко всему этому, чтобы работало нормально. И тут ты спокойно дропаешь свою демку и можешь начинать делать что то чуть серьезнее. А все эти видео, и особенно целые книги как правильно срать не нужны по крайней мере в начале
Бля а я решил сначала по ютуб гайдам игры поделать простенькие и уже потом чето свое пилить
+Мимо
Двачую этого. Базу выдал.
Норм план. Я так делал. Потом на основе гайдов можно пилить что-то свое адаптируя информацию из них под свои нужны + гуглить недостающую инфу.
>к движкам напрямую, а являются общими знаниями для геймдева
сцены, структурирование кода, является специфичным для godot
оно отличается от обычного программирования
лучше бы вместо сцен сделали структуру проекта в виде нод как на пикрил, т.е. универсальный абстрактный слой
в godot с наскоку непонятно к чему скрипты прикреплять и как вообще должна выглядеть программа, хочется создать "main.c" и модули/библиотеки для нее
Какая разница, что использовать? учитывая, что везде файлы можно хранить в json
Без разницы какой формат файла, важно что внутри
Не очень хочется заморачиваться со сторонними сервисами, типа draw.io
> оно отличается от обычного программирования
Это всё древовидные структуры данных, бои. Это еще в прошлом веке на курсах преподавалось. А самым ярким представителем прикладных языков разметки, основанном на НОДАХ является XML.
> лучше бы вместо сцен сделали структуру
Кому лучше? Тебе лучше? Так у тебя же каша в голове, даунинг-крюгерская. Ты не знаешь, что тебе лучше.
> универсальный абстрактный слой
Пустые слова рикошетом отразились в пустой голове и выплеснулись на двачи.
> в godot с наскоку непонятно к чему скрипты прикреплять
Всем понятно одной бабе яге непонятно.
> и как вообще должна выглядеть программа, хочется создать "main.c" и модули/библиотеки для нее
О, снова решил блеснуть умными словами. Скачиваешь исходники движка и пишешь ПРОГРАММУ прямо там, в проекте движка, дополняя его своими модулями с игрой, там тебе и мэйн.си будет и указатели на указатели. Но ты почему-то так не делаешь, ты прибежал ИТТ доёбываться к редактору движка, прикладному инструменту. Я тебя насквозь вижу, движкосрачерское животное.
Хорошо бомбанул :)
я просто проходил мимо
>ты прибежал ИТТ доёбываться к редактору движка, прикладному инструменту
ты просто очередной пограммист который наворачивает фреймворк с костылями и потом защищает костыли, потому что потратил на их изучение время
да да, сделай лучше, иди нахуй
>в godot с наскоку непонятно к чему скрипты прикреплять
К ноде. Больше не к чему.
>хочется создать "main.c" и модули/библиотеки для нее
Это один из штатных способов.
https://docs.godotengine.org/en/3.1/classes/class_mainloop.html#description
Базанул, два чая.
var a = 0
func test():
a += 1
Переменная a ведь все равно изменится, так? Так!
И второй вопрос. Зачем писать func test() -> void:?
Да делаю, делаю, блин! Вот заканчиваю набросок функциональности главного меню!
Void это вроде делает функцию глобальной
Return это когда ты в переменную суешь функцию из другого скрипта
Типа
var pipiska = $hui.drochit()
И в функции droichit() будет ruturn(cum)
То будет var pipiska = cum
Сколько времени прошло с последнего кадра, если кадры часто меняются - за раз движение маленькое, если редко - сразу на большое расстояние переместишься
Дельта это delta time, то есть разница времени между кадром и предыдущим. Формула расстояния S = t * v, поэтому чтобы узнать расстояние скорость умножают на это время, так движение будет пропорционально "порции", вне зависимости от фпс
void значит return не должно быть, и если ждать что то возвращаемое от это функции будет ошибка.
Войд не делает функцию глобальной. Войд это тайпхинт, показывающий что функция возвращает ничего. Если внутри такой функции сделать ретурн "пенис", то годот поймает это как ошибку.
Тайпхинты повышают понимаемость кода, помогают ловить ошибки типов и иногда ускоряют код - поскольку годоту не приходится самому распознавать чего ты там ему в переменную кладешь, он знает заранее. Актуально в интенсивных участках кода.
>Тайпхинты повышают понимаемость кода, помогают ловить ошибки типов и иногда ускоряют код - поскольку годоту не приходится самому распознавать чего ты там ему в переменную кладешь, он знает заранее. Актуально в интенсивных участках кода.
Хуя годноту нубикам сыплют в треде
Хотел посоветовать GPUAttractor,но в 2д их пока не завезли
Пикрил литерали getting started с оф сайта этого вашего годота. Миллион функций хуярится для какой-то банальной хуиты, умножение на неведомую хуйню, ну и конечно все эти функции завернуты еще в сотню функций с созданием миллиона нодов разных типов, в итоге передвинули инстанс на 2 пикселя влево. В то же время в каком-то геймейкере и прочих подобное выглядит как-то так:
>zalupa.speed = 100px
>if press(arrow_up) zalupa.y += 10
а не
>export balls
>$zalup_zalupa_speed = 666 * delta / alpha^1488
>$huesos(if_pidor) = !down
>func _pidoras($huesos(if_pidor)).govno.mocha:
>dvacher = !human + virgin
>zalup_zalupa = 100/10
>$CollisionShit2D.set_pidoras("disabled", true)
Ну и зачем тогда ты сюда пришёл? Не боишься что за посты деньги брать начнут?
>>zalupa.speed = 100px
>>if press(arrow_up) zalupa.y += 10
Аналогично можно и в годоте. Разница в том, что туториалы учат тебя делать тебя правильно, а не кое-как, и рассказывают как строить проект размером больше чем один спрайт.
чел ты буквально решил насрать в тред, но при этом забыл снять штаны
А мы послали на хуй юнити
Навскидку никак. В такой ситуации только вычислять поворот самостоятельно и передавать объекту. Но может кто подскажет хитрый хак?
Хитрый хак есть в каждом втором чарактер контроллере и туториале.
Воспользоваться силой нод.
Повернуть пустую ноду в нужную сторону, а уже ей спавнить дочернюю нужную. Потом при желании перенести заспавненное в другое место.
Ладно, погуглил и полистал другие статьи с их же сайта, стало понятнее. Но какого хуя не добавить все в первый тутор? Вот блять выбирай тут такой тип ноды, а тут такой, а в чем между ними разница - иди нахуй в гугл
Что делает "||" и "return" ?
Ничего, раз не написано. Просто возвращает досрочно, не продолжая выполнение функции.
Аааа, тепепь понял
Там просто под ней уже в переменную новые координаты персонажа записываются
Жаль ютуберы это нихуя не обьясняют
И еще есть проблема, как только ставлю mouse_captured, то экран начинает как бы моргать позади окна игры, если не в фул скрине запущено, но если перенесу окно на другой монитор, или скрою сам окно движка, то все ок.
Начни учить основы какого-нибудь языка, параллельно тыкаясь в игры, чтобы не скучно было. Ты простейших основ не знаешь
Найс
Когдато учил и питон и с# тоже по урокам с ютуба, но успешно задушился и бросил
Уж лучше так, на практике познавать
Рекомендую канал "godot для всех" на ютубе. Там довольно шарящий чел с самого нуля все рассказывает доходчиво и подробно. У него есть цикл, где игру с нуля делает, + параллельно цикл где разбирает основы гдскрипта.
Гляну, спасибо
Спасибо
Просто есть параноидальные мысли, что код/идею и прочее могут украсть или ещё как то поднасрать
>void значит return не должно быть
Из Void функций можно делать return, но без значения.
Возможно, я путаю с питоном
>Просто есть параноидальные мысли, что код/идею и прочее могут украсть
Именно поэтому не буду сюда ничего выкладывать, пока не буду на финальной стадии
> есть параноидальные мысли, что код/идею и прочее могут украсть
Код твой нахуй никому не нужен. У тебя же там каша из туториалов вместо кода. Проще с нуля всё переписать чем твоё пиздить.
Идею спиздят сразу же как увидят. От этого не застрахован никто. Посмотри, Palworld - наглый пиздинг покемонов и зельд, нинтенда в ахуе и уже пишет иски в суды, пиздинг фортнайта, пиздинг любых игор с данжами, нужное подчеркнуть.
Подводных никаких. Но лучше бы сразу на итч выкладывал - аудитория шире и веб-версию погонять можно.
Код твой никому не нужен, если только у тебя не йоба-хитрая идея, основанная на еще более йоба-хитром алгоритме. И то маловероятно.
>>29592
https://github.com/bruvzg/gdsdecomp
Да, годот без обфускации/шифрования легко декомпилируется. А андроидовские апк/абб можно открыть как зип-архив и почитать не-исходники голыми руками, например .txt. Сами исходники в байт-коде, поэтому их надо восстанавливать отдельно. Я как-то упаковал в андроид билд свой безумный TODO.txt, потом вспомнил что ЩАС ВСЕ ПРОЧИТАЮТ МОЮ ШИЗУ, и побежал пересобирать. Всем было похуй, 20 загрузок в гугл-плее за месяц.
А что если я игру залью а ее кто то просто возьмет и выдаст за свою, а на меня жалобу кинет
Как защититься от этого? Открывать струдию? Как права защитить?
А я не знаю. Ну, для перезаливки-перепродажи твою игру и декомпилировать не надо - взял экзешник и перезалил как свой. Так со всем итчем можно провернуть.
Помимо юридических залуп, в которых я не шарю, предположу что стоит делать все публично, заранее, и брендируя. Выкладываешь демки, видосы, девлоги, раскидываешь по соцсетям, чтобы всем было видно что vasyan666 работал над Cube Craft World 2D аж целых 8 лет. Заодно реклама. Я так делою, и ты так делой.
Еще ж можно в главное меню засунуть список авторов
Я так подумал, действительно кроме идеи пиздить у меня нечего, код это просто смех. Да и идею без специфических знаний просто так не украдешь.
Вообщем небольшой анонс, игра это симулятор врача приемного отделения в сеттниге мухосранской больницы. Как paper's please, только про медицину, бедность, алкашей и безнадежность. типичное приёмное отделение районной больницы
Геймплей это по жалобам определить диагноз и отделение для госпитализации. Пациенты генерируются полностью случайно, у них есть некоторые характеры, а ля агрессивный, доброжелательный, пьяный. Игра в том числе для людей, не знакомых с медициной, поэтому симптомы и диагнозы я упростил, но не сильно, подумать придется. Для помощи будет внутренний справочник, реализованный в виде монитора компьютера. То есть, вы будете буквально при пациенте гуглить его симптомы классика.
Когда будет тест неизвестно, но большую часть в виде генерации пациента и базы с диагнозами, симптомами и репликами я уже сделал, осталось допилить интерфейс и ещё пару фич по мелочи.
Я думаю будет хотя бы забавно, уже для теста я набросал 3 отделения по 5 диагнозов, у каждого несколько специфических симптомов + неспецифические.
> идею без специфических знаний просто так не украдешь
Чивобл?
Кабанчик проходит твою игру и делает 10 таких же.
Так понимание какое никакое надо, чтобы грамотно написать те же диагнозы и симптомы. Конечно все можно спиздить, но если кабанчик не разбирается в медицине, то хуй он что нормально даже спиздит.
Скажу честно, как человек много лет дрочивший симуляторы и всякие дотошно честные воссоздания разных явлений - в игре главное фановость, даже если там неправильные диагнозы. Врачи все равно найдут у тебя кучу неточностей. Еще хуже если кто то решит что твоя игра похожа на реальность и начнет по ней судить о здоровье. Как раз кабанчику проще, он просто будет пихать смищнявые несуществующие волчанки.
Смотрите, есть игрок, есть уровни-сцены. На уровнях есть объекты, которые могут изменять свои параметры. Например, дверь открылась, яблоко подобрал игрок, ящик передвинут и т.п. Игрок может перемещаться между уровнями, соответственно уровни-сцены загружаются туда-сюда по новой, но изменения должны сохраняться
И так, я верно понимаю, что при каждом пуке игрока, изменении параметров предметов, уровней и т.д. должны изменяться соответствующие параметры в глобальном скрипте. И уже из него при повторной загрузке уровня со всеми предметами должны подтягиваться актуальные параметры?
И этот скрипт должен быть подключен к каждой сцене в игре?
И также при сохранении в файл сохранения должны подтягиваться значения из этого скрипта? А если сохранения не было, например, игрок погиб (откат до чекпоинта) или вышел из игры, то значения должны обратно меняться на предыдущие, которые также хранятся в этом глобальном скрипте?
Ничего не путаю?
>Я так подумал, действительно кроме идеи пиздить у меня нечего
Т.е. кроме самого ценного, лул.
База.
> Ничего не путаю?
Ну вроде всё верно. Главное, чтобы тебе было удобно, не пытайся прямо буква в букву воссоздавать советы из прошлого треда. Действуй по ситуации.
В тройку везут ускорение освещения и теней.
Какие-то были, точно не смогу описать, связано с тем, когда что-то поменяешь в той сцене, или с экспортами. В общем, была ситуация что я чарактер контроллеру прицепил камеру,во время едит чилдрен. А потом передумал и сделал камеру внутри сцены чарактер контроллера. У них вообще-то одинаковые имена ноды получились, и потом галочки и возможные действия с ними подглючили.
Е-е-е, время обновиться к твг, самое то для проверки фич.
У меня похожее с наследованием сцен было на какой-то древней версии. Вроде пофиксили.
Ну, можно так.
Все предметы, которые должны сохраняться, добавляешь в группу Save. При сохранении глобальный скрипт опрашивает все ноды в этой группе на предмет изменений.
ИЛИ
В момент изменения предмет сам сообщает глобальному скрипту, что в нём что-то изменилось.
При загрузке глобальный скрипт смотрит все ноды, о которых у него есть записи. Обращается к ним и восстанавливает их состояния. О которых записей нет - к тем не обращается.
Мой личный подход:
Я храню глобальный словарь, внутри которого словари уровней и всякая глобальная метаинфа, внутри которых словари нод и всякая уровневая метаинфа.
Глобальный скрипт ничего не знает о нодах, он обращается к уровню, чтобы тот сам опросил своих детей. И ни глобальный скрипт, ни уровень не знают, как сохранять/загружать данные для конкретной ноды, этим должна заниматься сама нода.
У нод, которые надо сохранять, есть функция save() -> Dictionary, возвращающая собсно инфу о ноде; а что там сохранять - это для каждой ноды индивидуально прописывается. Если функции нет, то просто пишем пустой словарь. Если нода удалена, то вместо словаря - строка "deleted".
У тех же нод есть функция load_saved(data: Dictionary) -> void. Соответственно, скармливаем ноде её сохранённые данные, она уже сама разберётся, что с ними делать. Ну или если нету функции, то не скармливаем.
И да, обе эти функции есть и у уровня.
А получившийся глобальный словарь очень легко (одной строчкой буквально) отконвертить в жсон, хмл, сериализовать в бинарный или текстовый формат, чтобы сделать из этого сейв-файл. Ну и обратно точно так же в одну строчку. И да, в словарях для save и load_saved следует использовать только строки и числа.
Можно (но не очень желательно) всяким комплексным нодам разрешать в свой сейв-словарь вкладывать словари детей, чтобы они тоже сохраняли и загружали, но это чревато трудноуловимыми багами, когда у тебя что-то не загрузилось, а ты не знаешь, когда и почему.
А, и ещё. Глобальный словарь висит в памяти, но он не обязан сохраняться в файл всякий раз, когда получает изменения.
Ну, можно так.
Все предметы, которые должны сохраняться, добавляешь в группу Save. При сохранении глобальный скрипт опрашивает все ноды в этой группе на предмет изменений.
ИЛИ
В момент изменения предмет сам сообщает глобальному скрипту, что в нём что-то изменилось.
При загрузке глобальный скрипт смотрит все ноды, о которых у него есть записи. Обращается к ним и восстанавливает их состояния. О которых записей нет - к тем не обращается.
Мой личный подход:
Я храню глобальный словарь, внутри которого словари уровней и всякая глобальная метаинфа, внутри которых словари нод и всякая уровневая метаинфа.
Глобальный скрипт ничего не знает о нодах, он обращается к уровню, чтобы тот сам опросил своих детей. И ни глобальный скрипт, ни уровень не знают, как сохранять/загружать данные для конкретной ноды, этим должна заниматься сама нода.
У нод, которые надо сохранять, есть функция save() -> Dictionary, возвращающая собсно инфу о ноде; а что там сохранять - это для каждой ноды индивидуально прописывается. Если функции нет, то просто пишем пустой словарь. Если нода удалена, то вместо словаря - строка "deleted".
У тех же нод есть функция load_saved(data: Dictionary) -> void. Соответственно, скармливаем ноде её сохранённые данные, она уже сама разберётся, что с ними делать. Ну или если нету функции, то не скармливаем.
И да, обе эти функции есть и у уровня.
А получившийся глобальный словарь очень легко (одной строчкой буквально) отконвертить в жсон, хмл, сериализовать в бинарный или текстовый формат, чтобы сделать из этого сейв-файл. Ну и обратно точно так же в одну строчку. И да, в словарях для save и load_saved следует использовать только строки и числа.
Можно (но не очень желательно) всяким комплексным нодам разрешать в свой сейв-словарь вкладывать словари детей, чтобы они тоже сохраняли и загружали, но это чревато трудноуловимыми багами, когда у тебя что-то не загрузилось, а ты не знаешь, когда и почему.
А, и ещё. Глобальный словарь висит в памяти, но он не обязан сохраняться в файл всякий раз, когда получает изменения.
Какой вариант схавает билдер и кодогенератор годота на шарпе?
1. [Signal] delegate CockSuck + EmitSignal(nameof(CockSuck)) + handler в другом классе
2. event Action{add;remove;} + emit + handler в другом классе
3. event EventHandler + Invoke +EventHandler в другом классе
Переживаю что годот мне напарафинит генерейтед классов и придется потом все перепиливать
Пишу пока так, не знаю во что годотик развернёт это дело при билде
Всеравно 32х32 тайлы ебанешься рисовать, особенно если там будет больше трех оттенков
Ну нахуй
Возьми бесплатные сс0 ассеты на итче.
>неплохой хотя бы пиксельный
>хотя бы
Иные пиксели посложнее лоу-поли 3д будут. С пикселями тебе самому надо перспективу, форму и все такое прорабатывать, еще учитывая их пиксельность и стиль. В 3д, если ты не охуеваешь с хай-поли, у тебя уже готовые формы из примитивов, а перспективу за тебя код считает.
На итче все ассеты разные для конкретных задач. Не подходят друг-другу. В итоге будет винегрет, который потом еще и фиксить придется. Где-то кадров больше нужного, где-то размер, и т.д.
>Иные пиксели посложнее лоу-поли 3д будут. С пикселями тебе самому надо перспективу, форму и все такое прорабатывать, еще учитывая их пиксельность и стиль. В 3д, если ты не охуеваешь с хай-поли, у тебя уже готовые формы из примитивов, а перспективу за тебя код считает.
Я не против лоуполи. Но и лоуполи, и просто 2д графон со скелетной анимацией выходит и дороже и в больше шагов. Часто ассеты делает один человек, а анимацию другой. И тут уже надо колотить команду с бюджетом. Пиздец короче. А если все делает один человек, то он и денег возьмет больше, чем чел, который покадровую анимацию в пикселях сделает. Не говоря уже про совершенно другие текстуры окружения, эффектов и прочнго
>>29969
Вообще да, лоуполи даже предпочтительнее будет. Типа как в первых резеках и сайлет хилле. Коряво, но от этого атмосферней и страшней, ну вы поняли.
Но да
>Но там всеравно надо в цвет и светотень уметь
И в производстве сложней получится. А я знаю, что не потяну в соло сейчас. Нужно с чего-то попроще начинать
Кста реально годнота, особенно для нюфагов. Лучше и последовательнее погружение так сказать
> А где галочка?
В версии 4. Для версии 3 юзай ссылочку. Всё просто: трёшка - ссылочька, четвёрка - кнопочька.
Как раз в 3 галоку завезли. Правда, в GLES3 только, не обратил внимание. Так что да, лучше предпоказ для надежности.
Да, блять, я забыл, я всё перепутал, в трёшку завезли кнопочку бэкпортом.
Нет.
Нет.
В гдскрипте применяется принцип возврата кодов ошибок. Если некий метод может вернуть ошибку, он будет возвращать int, в котором 0 - это ОК, всё остальное - коды ошибок. Тебе следует делать так же. Впрочем, делай как хочешь.
> func true_godot_style_divide(a: int, b: int, result: ref int) -> int:
> > if b == 0:
> > > result = INF
> > > return ERR_DIVIDE_BY_ZERO
> > else:
> > > result = a / b
> > > return OK
Разумеется, этот код работать не будет. Домашнее задание - придумать, как заставить такой код заработать.
Функция с пикрила работает наоборот. Как такое может быть нахуй??? Аудиофайлы правильные привязаны, 100 раз проверил.
Может быть и не влияет, но у тебя нет конечного автомата. У тебя просто два независимых плеера которые играют когда ни попадя.
Зачем вообще два одноуровневых if, когда есть else?
Про play() я уже писал выше, он означает не "продолжить играть", а "сбросить поток и играть с начала". Который, судя по всему ты дергаешь каждый кадр.
Ну вот скорее всего так и получается, что тот плеер, который надо, ты этим каждый раз заглушаешь постоянными рестартами, а тот, который не надо, из за независимости, продолжает играть потому что его никто не стопает.
А почему играет фаст, по указанным обрывкам сложно угадать. Например процесс вызыаается всегда, включая первый кадр, а переменную ты инициализируешь позже, таким образом есть момент когда тайм лефт = 0, до того как станет 30. И поверь что не стоит галочка автоплея.
Код - пиздец.
Иф таймлефт меньше 20: эмит сигнал фастсаунд. Вот как надо. А в плеере подписаться на сигнал и при эмите сигнала переключить поток. Вместо этого два (2!) плеера! Судя по картинке, первый плеер как играл, так и играет, и после истечения времени плееры играют вдвоём.
Да еще и в процессе (через функцию-прокладку, что не поможет) дёргается дерево 60 раз в секунду (через сахарный $). Вообще пиздец.
Например, чтобы во всех диалогах и прочем говне названия скилов всегда были красными?
RichTextLabel с BB кодами, если не будет хватать, пробовать разные аддоны типа диалоговых
Я бы контекстное меню привязывал к элементу, на которой ты кликаешь, а не к самой мыши. Это, собственно, и был бы контекст. Каждый элемент содержит свой контекст.
Сделай сцену-компонент, назови ее типа ContextMenu, и втыкай ее всем элементам, по клику на которые должно вылезать меню. Потом, в этом элементе, лови эвент pressed, и по нему вызывай ContextMenu.display_your_menu()
> пробовать разные аддоны
Там всё делается через него же, по сути RichTextLabel с BB кодами - единственный штатный способ. Если анону не нравятся ББ-коды, то можно всё делать на низком уровне, через коллбэк _draw() делается, собсна пресловутый draw call. В нём через функции рисования на холсте можно с нуля построить всё что хочешь, в том числе самодельный ричтекст с разметкой.
Возможно ты прав, надо подумать...
Самому можно по разному сделать, вот навскидку:
- Состаалять динамический массив Label из подстрок
- то же самое, но делать Label только для цветных слов поверх них
- запилить модуль на c++ через freetype что нибудь
> динамический массив Label из подстрок
Ну это оверхед. Новичковый.
> запилить модуль на c++
А это наоборот слишком продвинуто.
Для среднестатистического годана намного выгоднее мой вариант, ИМХО.
Там есть draw text, но когда ты захочешь прыгающие по синусоиде буковки, то их вме равно по одной выводить, так что я не уверен что это сильно быстрее отдельных label
1280x720, 0:03
> их вме равно по одной выводить
То ты выводишь буковку в одном дравколле спецметодом, либо ты выводишь оверхед из кучи инстансов класса-ноды, набитых в дерево сцены, каждая из которых своим дравколлом рисует одну букву. Нуя хуй знает, конечно.
Вставлю свои 5 копеек
RichLabel + простенький модуль для оборачивания нужных слов в нужные теги по словарю
Щас бы это все вручную делать, конечно или целую либу на крестах писать
Мимошарподебил
На ютубе миллион видосов со сравнениями, особенно после осеннего бредка юнитеков, базарю, ты там быстрее и проще всё наглядно разузнаешь, чем будешь ждать ответов ИТТ.
>>30617
Но если вкратце, в основе отличий нет. Тот же мэйнлуп с коллбэками, как везде. Отличия в мелочах и в названиях. Там иерархия монобехов, тут дерево сцены из нод. Там префабы, тут сцены. Там ивенты как в винде, здесь сигналы как в линуксе. Там скриптобьекты, здесь ресурсы. И т.д. и т.п.
Для перекатунов с си-шарп-движка здесь искаропки поддержка сишарпа (ну как искаропки, отдельный билд с офсайта скачай всё равно), встроенный язык можно не учить. Официальная документация в основном на обоих языках даётся.
Щас пойду значит документацию всю читать, а потом и видосы разные наверну. Первый плюс который уже увидел, скорость блять. Как же он летает нахуй.
Я пробовал сделать двачебраузер, скажем так оборачивать пришлось бы дохуя и все равно не вся разметка покрывалась
Ты большой молодец, серьезно, но плохо продумал механизм работы с тегами, мог бы еще большим молодцом быть
Как бы ты сделал решение с подкрашиванием?
Я бы сделал так:
Допустим, диалоги это такая статичная штука, значит пишутся один или около того раз.
"Теперь ты умеешь пукоть %Skill%"
И вот нам надо покрасить этот %Skill%
На выходе получив что-то типа:
"Теперь ты умеешь пукоть [Color=green]%Skill%[Color/]"
Но, а если мы захотим изменить цвет отображения? Ползать по всем строчкам и менять? Да ну его нахуй.
Превратим строку в
"Теперь ты умеешь пукоть [Color=SkillColorTemplate]%Skill%[Color/]"
Я завожу класс DialogTextProcessor, где делаю словарь типа <string, string>, в который кидаю "StringColorTemplate"="Green"
Завожу метод Process, принимающий строку на вход, где будет foreach по этому словарю, реплейсящий все темплейты на их значение.
И возвращающий результирующую строку.
В итоге будем юзать так.
var incomingString = dialogsCache[dialogId][replicaId];
RichLabelText = DialogTextReplacer.Process(incomingString);
Сложность прохода foreach по словарю О(n), сложность поиска в словаре О(1), реплейс тоже О(n)
Значит все произойдет оче быстро.
Вот такую хуйню я придумал.
Ты большой молодец, серьезно, но плохо продумал механизм работы с тегами, мог бы еще большим молодцом быть
Как бы ты сделал решение с подкрашиванием?
Я бы сделал так:
Допустим, диалоги это такая статичная штука, значит пишутся один или около того раз.
"Теперь ты умеешь пукоть %Skill%"
И вот нам надо покрасить этот %Skill%
На выходе получив что-то типа:
"Теперь ты умеешь пукоть [Color=green]%Skill%[Color/]"
Но, а если мы захотим изменить цвет отображения? Ползать по всем строчкам и менять? Да ну его нахуй.
Превратим строку в
"Теперь ты умеешь пукоть [Color=SkillColorTemplate]%Skill%[Color/]"
Я завожу класс DialogTextProcessor, где делаю словарь типа <string, string>, в который кидаю "StringColorTemplate"="Green"
Завожу метод Process, принимающий строку на вход, где будет foreach по этому словарю, реплейсящий все темплейты на их значение.
И возвращающий результирующую строку.
В итоге будем юзать так.
var incomingString = dialogsCache[dialogId][replicaId];
RichLabelText = DialogTextReplacer.Process(incomingString);
Сложность прохода foreach по словарю О(n), сложность поиска в словаре О(1), реплейс тоже О(n)
Значит все произойдет оче быстро.
Вот такую хуйню я придумал.
Ну или унаследоваться от ричтекста, переопределив сеттер Value
И название скилла из темплейта и словаря собирать
> Сложность прохода foreach по словарю О(n), сложность поиска в словаре О(1), реплейс тоже О(n)
Годаны, научите считать сложность вот в этих терминах? Несколько раз пытался понять - нихуя.
Сап, годач. Значт делаю шейдер для избегания повторяющихся паттернов в повторяющейся текстуре. Идея проста -- рандомно крутить каждую плитку текстуры. Повторение по плитке я сделал, кручение каждой плитки я сделал, вроде бы самое просто осталось, крутить их отедельно, и на этом я застрял.
пикичи: 1-результат на пока что. видно что повторяется.
2- выражение в ноде, по сути ядро шейдера, тут то мне и надо что то дописать, думаю через 2д шум наверно рандомно крутить.
4- узлы визуального шейдера до выражения. Прошу помощи поскольку этот шейдер довольно важный.
добавлю как выглядит ЮВишка на выходе сейчас и как примерно надо
Все просто, считается по тому сколько данных мы обработаем. Самые легковесные операции типа сложения, вычитания или поиска в словаре или хешмапе, где время не зависит от размера входных данных - О(1)
Циклы О(n), потому что пройдем чаще всего всё
Цикл двойной вложенности О(n^2)
Тройной n^3 и так далее.
Обычно вот тут и появляются бутылочные горлышки
Поиск в бинарном дереве - О(log(n)), из-за постоянного деления количества элементов в котором ищем на два
Факториал O(n!) При, допустим, реализации комбинаторики, где сопоставляешь каждый элемент со всеми другими
Ну и экспонента n^сколько-то
При рекурсиях типа вычисления чисел фиббоначи
Тут можешь почитать подробнее
https://habr.com/ru/articles/782608/
да для меня тоже, всё то что на экране -- понимаю лишь отчасти (а код с реддита спизженный), но вот это избегание паттерна нужно пиздец как сильно, без него никуда.
это потому что ты пользуешься движком
>>30666
Помог чем мог. Угол свой поставишь и должно быть збс.
Код: https://pastebin.com/zKHpm7Pg
Песочника: http://editor.thebookofshaders.com/
вроде оно, но чёто угол не сильно рандомный. или рандом угла меньше 90 градусов? бля это получается я дебил, мнеж нужно чтоб 90 градусов кратное значение было, ибо швы будет видно. Но я наверное уж сам поиграюсь, спасибо анон, я тебя запомню.
Не понял, на кого это вешать? На InEvent? Но так нельзя же. Или я тебя не понял?
на курсор скрипт с "гет парент", или в случае если тебе надо верхушку сцены можешь попробовать "гет_рут"
Не слушай этих. Щас накатаю тебе пример. Вешать надо во внутреннюю export -переменную, через инспектор редактора, если есть возможность, если нет, то через код туда же. Тебе для трёшки или для четвёрки?
Но зачем, я же всегда знаю где в дереве объект курсора, мне нужно то, на что над чем находится объект курсора, когда нажимается кнопка мыши, то есть если кликается в всплывающем меню - то одно, если на игровом поле - то другое, если на боковой панели, то третье.
я в этой хуйне постоянно путаюсь, то у них 1 это 180 градусов то у них радианы ебучий цирк блять. Как мне из рандома вычлинить это самое число кратное 0.5 ?
так это дружок, через другое делается, а не гет парент вовсе. погугли( да бля, в доске помощи говорить погулить, я знаю) как определять объект на который кликнули. Это и у контрольных узлов есть и у простых 2д-шек. Есть сигнал такой _gui_input -- он показывает где мышка на узле(а если мышка и вовсе не на узле, то сигнал ничего не возращает).
это да. Но если без рандома то паттерн же потом заметно повторяется, когда увеличивает колл-во квадратов, разве нет?
точнее возвращает он event вообще, то есть и клики тоже.
> мне нужно то, на что над чем находится объект курсора, когда нажимается кнопка мыши, то есть если кликается в всплывающем меню - то одно, если на игровом поле - то другое, если на боковой панели, то третье
Тебе же выше написали, что это неправильный подход. При нажатии мышки генерирует событие клика тот объект, на котором произведён клик. У этого объекта должно быть контекстное меню для показа. В этом суть слова "контекст" в выражении "контекстное меню". Это такая база, что просто фейспалм. Знаешь что. Не буду я тебе ничего накатывать. Пиздуй учить матчасть.
жоско но честно
> я в этой хуйне постоянно путаюсь, то у них 1 это 180 градусов то у них радианы ебучий цирк блять
Запомни, у "них" всегда радианы, всегда! Если ты где-то встретил углы в градусах (которые при этом никак не подписаны градусами), то сразу же знай, что между "ними" и "тобой" находится "мэн ин да мидл" который нахуярил градусов из дефолтных радианов, но тебе не сказал.
по идее второе то что нужно, но почему то ровные 90-кратные повороты оно не делает
На пикриле синим то что не 90-кратное.
забыл добавить, да, заработало как надо.
У меня сейчас так:
for object in get_nodes_in_group("mygroup"):
object.get_node("SomeChildNode").myfunc()
Думаю как это переписать на call_group
а как он это делает вообще? ну в плане, я понимаю как нормализовать вектор, берёшь самую большую переменную (X, Y или Z) и делишь на неё все, получается что самая большая по итогу один (X / X = 1) а остальные пропорционально поделились. А с одной переменной как узнать максимальное значение?
а... я думал пропорционально уменьшает. ну одной загадкой меньше. пойду переписывать шейдер в годот штоли.
Спасибо, не извиняйся, но больше постарайся на других не срываться
А вот и арт на перекат подвезли!
ещё раз спасибо, уже конвертировал в шейдер для годота (тоже пришлось поебаться но всё работает и вроде даже не костыльно).
эффект не особо заметен но я ещё шума сверху накину и нормально будет думаю.
А зачем? Частицы и перерисовать можно, никто париться не будет запоминая ХУЗ координаты каждой
Я длинный шлейф делаю. Объект, испускающий частицы, двигается и поворачивает. Шлейф, соответственно, изгибается. И он может быть реально длинным - дальше экрана. И зигзагообразным. Сохранись-загрузись, и он пропадет. На форумах советуют preprocess выставить, но тут он не поможет.
Сработает только для этого конкретного случая. Есть десяток других. Для каждого костылять не будешь.
В packedscene индивидуальные партикли тоже не сохраняются. Проверил.
Ну так пиши свой сохранятор/загружатор, который для каждого эффекта реализует свой алгоритм сохранения/загрузки частиц.
Дак потому и не реализовано как и волшебной кнопки сохранения :)
Нужно костылять под конкретные потребности, абстрагироваться по максимуму и допиливать по необходимости, так что сохраняй свой шлейф, а частицы перерисовывай
если тебе так важно сохранить шлейф, то это уже не совсем задача под чистицы. Они же просто дешёвые эффектики. Если что то своё нужно -- пиши своё, это не костыли а простая логика. Тем более что почти везде под свои нужды делается своя система партиклов.
Только позицию конкретных отдельных частиц не получить никак. И не восстановить ее.
Но партикли вообще для такого не предназначены. Они созданы как короткоживущий визуальный эффект, не имеющий особой смысловой нагрузки. На другом устройстве (мобилке, например) твои партикли вообще могут не отрисоваться или отрисовываться иначе.
Кароч переделывай свой шлейф на чём-то более персистентном.
Щас будем посмотреть (18:28 МСК)
tool означает что скрипт работает в редакторе, а не только в самой запущенной игре.
Тул используется для того, чтобы прямо в редакторе менялись иконки предметов, когда ты им пикчи устанавливаешь.
Чтобы можно было вручную что-то редактировать прямо в редакторе визуально. Ну как пример расставил ты на уровне нескольких врагов, и меняешь одному из них спрайт с гоблина на орка.
Ты не понял. ТУЛ нужен, чтобы сразу в редакторе, во вьюпорте, видеть изменения, скрипт начинает работать прямо в редакторе, у него _процесс() работать начинает. Теперь понял?
2560x1440, 0:20
И все еще не понял. У меня как-то наоборот работает. Записал видео.
Код выглядит так:
@tool
extends Node2D
@export var texture_of_item : Texture
@onready var Item_sprite = $Sprite
func _ready():
if not Engine.is_editor_hint():
Item_sprite.texture = texture_of_item
func _process(delta):
if not Engine.is_editor_hint():
Item_sprite.texture = texture_of_item
Второй нот не нужен. Смотри туториалы внимательнее. В _реди ты делаешь иф нот, а в _процессе ты должен делать просто иф! Без нот!
И отучайся копипастить, да душно, но пиши ручками код ,а не копипасть бездумно.
>>931045 (OP)
Нет, от английского persistent. В великомогучем нет слова, которым можно было бы однозначно это перевести.
Стабильное, постоянное, существующее. Антоним - эфемерное.
ну так стабильное скорее тоже хорошо попадёт. размытые аналогии в программировании ни к чему(читай: я ненавижу англицизмы).
Это все решается обычным двумерным графом с кастомной функцией определения соседей, зачем ты высрал трехосевые координаты абсолютно непонятно.
Вы видите копию треда, сохраненную 12 сентября в 07:35.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.