7 Ease | Getting Started
jill edited this page 2021-09-26 18:39:01 +00:00

The Ease module is currently heavily unfinished. Features listed in this page aren't final. 100% accuracy to the current code isn't guaranteed.

Introduction

The best way to think about the Ease module is what would happen if you applied functional programming to NITG modding. With Mirin, to repeat a certain effect on every beat, or on every note, etc. you'd have to use a for loop. However, that takes extra syntax that often makes code longer and more complicated to type, especially when you want to do more complicated things.

Ease solves this issue by introducing the beatobj. It stores beats with which you can then automate modding. There's many ways to create a beatobj, but for simplicity's sake for now we'll use forl(). It acts as a for loop, letting you pick the same arguments to make an effect every x beats:

-- Standard Mirin
for b = 0, 32, 2 do
    -- ...
end

-- Mirinda
forl(0, 32, 2):...

Once you have a beatobj, you can now either use the beatobj to add mods or manipulate it. Let's start off with a very common mod you'll see in tons of files as a filler mod:

-- Standard Mirin
for b = 0, 32, 2 do
    ease {b - 0.5, 1, inOutCirc, 100 - get('tipsy'), 'tipsy'}
end

-- Mirinda
forl(0, 32, 2):onoff('tipsy')

This code will turn the tipsy mod on and off every 2 beats smoothly.

This is a lot to take in, so let's quickly break it down. onoff is one of the standard beatobj methods, which turns a mod on and off every beat. The mod in question is tipsy, with the assumed percentage of 100 since no percentage is given. If you were to want 50 tipsy instead, you'd run :onoff(50, 'tipsy').

Now you might be wondering, where is the length or ease function? In Mirinda, a lot of assumptions are made. The default ease that any beatobj is given is inOutCirc, and the default length is 1. There currently isn't a way to change the defaults. However, you can edit them after initializing a beatobj:

forl(0, 32, 2):setl(2):ease(inOutExpo)

This will make it so that any mods ran after this will be using the inOutExpo ease, and the length of 2. This is a pretty simple beatobj manipulation, and you'll likely be doing these a lot for more complicated effects.

If you want to then apply the same tipsy mod, you'd just append it at the end:

forl(0, 32, 2):setl(2):ease(inOutExpo):onoff('tipsy')

The onoff function will now use the length of 2 and the inOutExpo ease for easing. Hooray!

Example usages

onoff is one of the more simpler mod functions out there. Here are a few more examples you can use to replace more complicated bits of code, and to give more of an example on how Mirinda functions:

-- Standard Mirin
for b = 0, 16, 2 do
    local i = b/2
    local off = i%2*2-1
    ease {b - 1, 2, inOutCirc, 100 * off, 'tipsy'}
    set {b, 1, 'glitch2'}
    ease {b, 1, outCirc, 0, 'glitch2'}
end

-- Mirinda
forl(0, 16, 2):kick(1, 'glitch2'):setl(2):wiggle('tipsy')

wiggle is similar to onoff, except instead of switching a mod on and off, it wiggles it between 100 and -100.

kick sets the value to the percentage given at the beat, then eases it to 0. It creates a kind of "kick" effect, and works really well with glitchy shaders or mods for more aggressive songs.

The way the chaining is done in here is also potentially interesting: you'd think that the kick function's length would also be 2, but in reality it's 1 because setl is applied after kick. Chaining in Mirinda follows this same pattern for any beatobj manipulating function: changes to the object only apply after the function.

-- Standard Mirin
local notedata = P1:GetNoteData(135, 138.5)
for i,n in ipairs(notedata) do
    local off = i%2*2-1
    ease {n[1] - 0.5, 1, inOutCirc, 100 * off, 'tipsy'}
end

-- Mirinda
c2l(135, 138.5):wiggle('tipsy')

c2l is another way to create a beatobj. This one instead takes the player's notedata and uses that as the beats.

Ease Functions

Ease functions in Mirinda are complicated, due to trying to make more complex and customized eases easier to use.

The easings only use 3 different variables: ease, alignment and length. We've already covered length and ease, but alignment is a bit difficult to understand.

Think of it this way. Each ease function in Mirinda is an inOut function, meaning it contains its in function at the first half and its out function at the second half. The default alignment is 0.5, so the very middle.

inOutCirc with the align set to 0.5. White is the ease, and the light gray is the alignment point.

inOutCirc with the align set to 0.5. White is the ease, and the light gray is the alignment point.

Functions like wiggle or onoff use the whole thing, where kick or sharponoff trim off one end to create a sharper ease. This way, if you were to change the ease to an out or in ease, everything would break pretty badly unless you use :align() on it to change the alignment to the start or end:

outCirc with the align set to 0

outCirc with the align set to 0

This system works really well with eases that aren't aligned to the middle or start/end. For example, if you want an ease to have a long in part but a quick out part, you can use the :mixease(ease1, ease2, a) standard function to mix two eases and do the alignment stuff automatically. For example, here's approximately what :mixease(inCirc, outCirc, 0.75) would look like:

mixease(inCirc, outCirc, 0.75)

mixease(inCirc, outCirc, 0.75)

You'll notice the end is significantly sharper than the start, and the alignment point is still aligned with the middle. You can also mix different eases this way, and not specifically the same type of ease. This is what mixease(linear, outCirc, 0.75) would look like:

mixease(linear, outCirc, 0.75)

mixease(linear, outCirc, 0.75)