Обзор некоторых системных выражений

tr0yQ:
102961341.138673094.1321089483.ddd194661313258c6149e9069864bb4d Итак, небольшой разбор некоторых system expressions и того, что можно сделать с ними. Сразу говорю, это не полноценный обзор, просто решил поделится некоторыми интересными фишками.
Начнем, пожалуй, с Lerp
Lerp(a, b, x)
Линейная интерполяция, высчитывает a + x(b - a), или, если проще, значение, равное x% от диапазона от а до b. Еще проще: lerp(0, 100, 0.5) даст результат 50, lerp(25, 100, 0.3) даст 47.5
В чем польза: lerp отлично подходит для плавных изменений значений.
Например, плавного следования одного спрайта за другим с эектом декселерации:
+always:
lerp(Sprite.x, Sprite2.x, 1-0.1^timedelta)
lerp(Sprite.y, Sprite2.y 1-0.1^timedelta)

Обратите внимание, что x мы прописываем как 1-0.x^timedelta.

Это для того, чтобы исключить влияние FPS. 1-0.1^timedelta даст большую скорость передвижения, 1-0.5^timedelta более медленную.
Пример плавного скроллинга камеры за объектом (с задержкой):
lerp scrolling.cap

Далее разберем Clamp
Clamp(Значение, нижний предел, верхний предел)
Clamp служит для ограничения установки значения. Значение никогда не будет ниже нижнего предела и выше верхнего.
Например:
-> System: Set global variable 'value' to clamp(global('value')-global('value2'), 0, 100)
В результате переменная value всегда будет не ниже 0 и не выше 100, чему бы не равна была value2
Примеры.
Ограниченное движение (невидимые стенки):
clamp move.cap

Ограничение изменения угла:
clamp angle.cap

Abs
abs(значение)
Возвращает абсолютное значение, иными словами - отрицательное значение станет положительным.
Пример использования: можно использовать для определения абсолютной скорости объектов, использующих основанное на векторах поведение, когда движение влево или вверх задается отрицательным числом (Platform movement, 8 dir movement и т.д.).
abs(Sprite[Platform].VectorX) - даст абсолютную скорость спрайта, независимо от того, вправо или влево он движется.
Sign
sign(значение)
Возвращает 1 если значение больше нуля, возвращает 0 если значение равно 0 и возвращает -1 если значение ниже нуля.
Допустим, у нас есть переменная "mov", которая должна быть равна 1, если объект движется по горизонтали, и равна 0 если стоит на месте.
Делаем это одним просты действием:
-> System: Set global variable 'mov' to abs(sign(Sprite[Platform].VectorX.
И, наконец, я расскажу о том, как воссоздать поведение Sine, но с большими возможностями с помощью sin и timer
timer запускается вместе с приложением и отсчитывает время работы приложения.
sin, помимо обычных геометрических расчетов с углами, позволяет создать синусоиду при взаимодействии с постоянно меняющимся значением.
Итак,
sin(timer)*x, или sin(timer/a)*x, или sin(timer*a)*x
Отличаются только скоростью.
a - умножая или деля таймер на это значение мы меняем скорость синусоиды.
x - Диапазон, аналог в поведении Sine - range
Пример:
Синусоидальный скроллинг изображения (+ бесконечный скроллинг изображения)
sin scroll.cap

На этом пока все

Enginer:
Отличный урок! Плюсую.

XPlay:
Узнал что то новенькое для себя.

Ilyko96:
Спасибо! Очень порадовали как статья, так и примеры.


daGamer:
Ну вот. Очень полезная информация.

T-Man:
Кстати, полезно будет посмотреть многим новичкам. Да и опытным ребятам поможет сократить список эвентов. В общем, спасибо большое!

Yani-X:
tr0yQ, а можешь сделать пример, на основе примера "ограничение изменения угла", но немного иначе. К примеру нас есть 2 объекта: корпус танка и турель, и чтобы турель была ограничена в повороте относительно корпуса танка. То есть корпус танка динамично меняет свой градус, в зависимости от поворота и турель соответственно так же должна иметь динамическое ограничение в повороте. Для турели ограничение должно быть локальным - корпус танка.
Я когда-то давно пытался подобное реализовать, но у меня не вышло нифига.

tr0yQ:
Что-то ничего не понял.
Турель должна поворачиваться в сторону танка или что?

Ilyko96:
Yani-X, тут будет сложнее, т.к. при движении танка верхний и нижний пределы перепутаются. Вообще по идее должно работать выражение:
clamp(angle(Puha.X, Puha.Y, MouseX, MouseY), Korpus.Angle-30, Korpus.Angle+30)
Но оно некорректно работает. Суток позже (если меня не опередят) я решу эту задачку

Ilyko96:
Значит я добился такого результата:
1) Выражение angle(x1, y1, x2, y2) выдает нам наименьшей угол (т.е. если угол превышает 180 градусов, оно высчитывает отрицательный угол) => ни о каком clamp'е с таким выражением речи быть не может (рассматривая вариант, предложенный яном)
2) Если сделать длинный тонкий спрайт, который будет всегда "следить" за курсором, то его угол будет всегда положительным (что нам и надо), значит это уже результат.
И последняя - плохая новость. При пересечении одного из пределов clamp'а с осью Х происходит полная путаница, т.к. угол у корпуса всегда положительный. Попробую объяснить.
Если у нас у корпуса угол 350 (представляйте себе), а отклонения - по 30 градусов (опять представляйте), то у нижнего предела значение - 320 (я рассматриваю вариант, когда нижний предел - ниже по оси Y, чем корпус, а верхний - выше), а у верхнего - 20, вот отсюда и путаница. (сравните минимальное и максимальное значения с пределами - для корректной работы выражения должно быть наоборот)
Если у корпуса угол 40 (отклонения те же), то нижний предел - 10, верхний - 70 - все правильно.
И третий пример: если у нас угол корпуса - 10 градусов, то нижний предел - 340, а верхний - 40 градусов - опять путаница
Что из этого следует: из этого следует, что используя дополнительный спрайт, у нас все равно остается "мертвая" зона. Границы этой мертвой зоны варьируются в зависимости от установленных пределов. Щас попробую вывести эти границы. Значит верхняя граница (по оси Y) этой зоны равна углу, между корпусом и нижним отклонением, а нижняя граница - равна углу между верхним пределом и углом корпуса, причем расположение этой зоны относительно корпуса - выше по оси Х.
Слова "выше" и "ниже" подразумевают под собой движения по встроенной координатной плоскости Construct'а.
Ну вот как-то так

tr0yQ:
Блин, так и надо было писать "башня танка" а не "турель".
Мда. Как я теперь жалею, что забивал в школе на математику и особенно на тригонометрию.
Полюбуйтесь только на эту монструозную формулу, которая все равно не работает, когда танк разворачивается влево.
Надо придумать, как заставить угол в максимальном значении клампа всегда быть положительным, при этом не теряя актуального значения.
А у меня голова уже не варит

this fckn angle.cap

Ilyko96:
х, название порадовало!

Yani-X:
tr0yQ, классно! Но присутствуют рывки (резкая смена градуса в противоположную сторону), когда встречается курсор с обратной стороны, ну ты понял, да? Сейчас ты начнешь говорить, что я этого не просил).

tr0yQ:
Я скажу, что это не главная проблема, сделать бы во все стороны поворот сначала

gamer:
делал для своей игры, но решил с вами поделится

angle by gamer.cap

OldChivas:
Я уже писал что проблема решена. На мой взгляд, там все проще.

Rafl:
А как сделать плавное вращение и остановку объекта, с помощью Lerp?


Ну вот, разобрался вроде как плавно останавливать в одну сторону, а как сделать так же, только в другую?

Lerp_rotate.cap

Samodelkin:
Мне подсказали всего парочку выражений (round и abs) и это избавило от лишней головной боли.
Действие с round занимало одну строку, а аналог без него я пытался сделать раз в 15 больше с переменными, кучей условий и воспоминаниями из курса геометрии и тригонометрии.
Суперполезная тема.
У меня вопрос, а каким символом выражается значение по модулю? Ну тоесть (Х1-Х2) может быть как положительным так и отрицательным. А мне нужна именно разница, положительное число.
(Гуглавнй геройл при сочитании слов "Python" и "модуль" совсем о других модулях начинает выдавать ссылки)

bulbasaur:

abs tr0yQ написал об этом вначале.

Samodelkin:
И правда, как неловко

OldChivas:

Можно сделать на этом примере, так чтобы камера не запаздывала, а наоборот, находилось чуть впереди по движению объекта?

tr0yQ:
Что-то я не очень понял. "Запаздывание" и дает плавность. Если надо, что камера была впереди объекта, нужно скролить не на сам объект, а на точку впереди его (например, sprite.x+50)

OldChivas:

К сожалению такой метод не работает. Наверно придется впереди главнй герой привязывать спрайт и к нему экран.

tr0yQ:
Если можешь привязать спрайт, то почему нельзя скроллинг?
Игра платформер или TDS?

OldChivas:
Не TDS, но суть как у TDS. главнй герой двигается вверх-вниз, лево-право в приделах экрана.
Нужно чтоб (к примеру) главнй герой начал движение вверх, при этом камера должна поехать вверх быстрее чем главнй герой, как бы показывая дорогу.

tr0yQ:
Так пойдет?

lerp+sincos.cap

OldChivas:

Да, спасибо!
(Вчера не мог посмотреть)