RPG Maker Forums

If you aren't working on a custom transition, then this article may not hold much value for you. I'm also a new to MV, so take this with a grain of salt.


In other web projects, you might get your progress with some basic math. `durationElapsed / durationTotal = progress`. Animation is a pain, so maybe you have jQuery, D3, or Greensock doing some heavy lifting for you. So if we were running over the course of 24 frames, you might expect something like this:

Code:
| durationElapsed | durationTotal | progress | max | opacity |
| ---------------:| -------------:| --------:| ---:| -------:|
|               0 |            24 |    0.000 | 255 |   0.000 |
|               1 |            24 |    0.042 | 255 |  10.625 |
|               2 |            24 |    0.083 | 255 |  21.250 |
|               3 |            24 |    0.125 | 255 |  31.875 |
|               4 |            24 |    0.167 | 255 |  42.500 |
|               5 |            24 |    0.208 | 255 |  53.125 |
|               6 |            24 |    0.250 | 255 |  63.750 |
|               7 |            24 |    0.292 | 255 |  74.375 |
|               8 |            24 |    0.333 | 255 |  85.000 |
|               9 |            24 |    0.375 | 255 |  95.625 |
|              10 |            24 |    0.417 | 255 | 106.250 |
|              11 |            24 |    0.458 | 255 | 116.875 |
|              12 |            24 |    0.500 | 255 | 127.500 |
|              13 |            24 |    0.542 | 255 | 138.125 |
|              14 |            24 |    0.583 | 255 | 148.750 |
|              15 |            24 |    0.625 | 255 | 159.375 |
|              16 |            24 |    0.667 | 255 | 170.000 |
|              17 |            24 |    0.708 | 255 | 180.625 |
|              18 |            24 |    0.750 | 255 | 191.250 |
|              19 |            24 |    0.792 | 255 | 201.875 |
|              20 |            24 |    0.833 | 255 | 212.500 |
|              21 |            24 |    0.875 | 255 | 223.125 |
|              22 |            24 |    0.917 | 255 | 233.750 |
|              23 |            24 |    0.958 | 255 | 244.375 |
|              24 |            24 |    1.000 | 255 | 255.000 |


Since 0 is itself a frame, we actually have 25 frames here. `durationElapsed === 0` doesn't actually run in RPG Maker MV, and I haven't yet come across any event that looks like "durationDone", which could be used as that last frame. This makes sense, but it is clear as mud, so I'm going to try to clear the water here.


The math in `Scene_Base.prototype.updateFade` confused me when I first saw it. It looked like no timing function I had ever seen. There is no easing going on here. The math works out to be linear.


Scene_Base.prototype.updateFade = function() {
    if (this._fadeDuration > 0) {
        var d = this._fadeDuration;
        if (this._fadeSign > 0) {  //FadeIn = decrease opacity
            this._fadeSprite.opacity -= this._fadeSprite.opacity / d;
        } else { //FadeOut = increase opacity
            this._fadeSprite.opacity += (255 - this._fadeSprite.opacity) / d;
        }
        this._fadeDuration--;
    }
};




The change on every step equals `10.625`, despite the value of the numerator and denominator changing every time. I later found this to equal `(1/24) * 255` or the progress of one frame over the maximum duration, multiplied by the maximum value. In this case, the fade sprite clamps opacity between `0` and `255`.


# The wrong way


I thought I was _so_ smart. I would calculate progress in a way that was easier to follow.


Scene_Base.prototype.startFadeIn = function(duration, white) {
    this.createFadeSprite(white);
    this._fadeSign = 1;
    this._fadeDuration = duration || 30;
    this._fadeSprite.opacity = 255;
    this._transitionDuration = this._fadeDuration; // NEW //
};

Scene_Base.prototype.startFadeOut = function(duration, white) {
    this.createFadeSprite(white);
    this._fadeSign = -1;
    this._fadeDuration = duration || 30;
    this._fadeSprite.opacity = 0;
    this._transitionDuration = this._fadeDuration;  // NEW //
};

// NEW METHOD //
Scene_Base.prototype.fadeProgress = function(){
    var durationRemaining = this._fadeDuration;
    var durationTotal     = this._transitionDuration;
    var durationElapsed   = durationTotal - durationRemaining;
    var progress          = durationElapsed / durationTotal;
    return (Number.isFinite(progress))? progress : 0;
};

Scene_Base.prototype.updateFade = function() {
    if (this._fadeDuration > 0) {
        var opacityChange = this.fadeProgress() * 255; // MODIFIED //
        if (0 < this._fadeSign) {  // MODIFIED // I reversed the order of the comparison, because it made sense to me. It still has the same meaning.
            this._fadeSprite.opacity = 255 - opacityChange; // MODIFIED // Notice the subtraction changed locations.
        } else {
            this._fadeSprite.opacity = opacityChange; // MODIFIED //
        }
        this._fadeDuration--;
    }
};




`_transitionDuration` doesn't change, so it gives me a maximum value I can compare `_fadeDuration` against. I use the term "transition" because not all transitions need to involve a fade, even if a fade is the most common kind of transition and it is what RPG Maker uses by default.


Clever right? Not so much. The final step ends up being:

Code:
| _fadeDuration | Fade Type | Change | New Math | RPG MV  |
| -------------:| --------- | ------:| --------:| -------:|
|            24 | FADEOUT   | 10.625 |    0.000 |  10.625 |
|            23 | FADEOUT   | 10.625 |   10.625 |  21.250 |
|            22 | FADEOUT   | 10.625 |   21.250 |  31.875 |
|           ... | ...       |    ... |      ... |     ... |
|             3 | FADEOUT   | 10.625 |  223.125 | 233.750 |
|             2 | FADEOUT   | 10.625 |  233.750 | 244.375 |
|             1 | FADEOUT   | 10.625 |  244.375 | 255.000 |


Remember, `_fadeDuration === 0` never triggers `updateFade`.


Do you see my mistake? I was considering the first execution of `updateFade` to be the initialization, or zero progress, frame. Both sets of math always incremented by the same number. But zero progress happens in `startFadeIn` and `startFadeOut`. My math leaves the final value one step behind and the transition itself is not quite complete.


RPG Maker MV accomplishes this in much fewer lines of code. What if the numerator and denominator for the next property I want to work with doesn't happen to line up so conveniently? Is this the reason 255 was chosen instead of a value between 0 and 1? The fadeSprite converts the 0-255 number to a 0-1 number automatically. 


I'm still not convinced the MV way is the best or most flexible way, so I revisit my code.


# A better way


Scene_Base.prototype.fadeProgress = function(){
    return (this._transitionDuration - this._fadeDuration + 1 ) / this._transitionDuration;
};




Now our progress is based on the amount of time that has passed relative to the total amount of time. This feels far more reliable than numerators and denominators that (happen to?) play nice at any given step. I'm not going to dissect MV's math and try to say it is right or wrong. I'm just saying it didn't work for me.


The zero progress step (`startFadeIn` or `startFadeOut`) IS our first frame and it gives us our floor, where the `+1` allows our ceiling to reach 100% and is effectively the same as MV's math.


I'm down to a single line of code and just a couple more math operations than MV's native code. I could get rid of a couple operations, but that would mean changing more of the code base which relies on `_fadeDuration` being `0` to indicate busy-ness. Its important to other parts of RPG Maker MV. I'll take the tiny performance hit for the increased flexibility in developing a custom transition and having code that is easier for me to understand and maintain.


If I really wanted to, it would probably be simple enough to add support for an easing function from here. It gets you thinking ... "what could I do next?"

Latest Threads

Latest Posts

Latest Profile Posts

Our latest feature is an interview with... me?!

People4_2 (Capelet off and on) added!

Just beat the last of us 2 last night and starting jedi: fallen order right now, both use unreal engine & when I say i knew 80% of jedi's buttons right away because they were the same buttons as TLOU2 its ridiculous, even the same narrow hallway crawl and barely-made-it jump they do. Unreal Engine is just big budget RPG Maker the way they make games nearly identical at its core lol.
Can someone recommend some fun story-heavy RPGs to me? Coming up with good gameplay is a nightmare! I was thinking of making some gameplay platforming-based, but that doesn't work well in RPG form*. I also was thinking of removing battles, but that would be too much like OneShot. I don't even know how to make good puzzles!
one bad plugin combo later and one of my followers is moonwalking off the screen on his own... I didn't even more yet on the new map lol.

Forum statistics

Threads
106,035
Messages
1,018,455
Members
137,821
Latest member
Capterson
Top