Sphinx-MathEasing

Sphinx-MathEasing

Comme tous mes plugins, ce script est publié sous licence CC BY 4.0.

Ce plugin tout simple réunit au sein d’un même « namespace » (l’objet Math.easing) des fonctions d’accélération diverses.

//=============================================================================
// Sphinx-MathEasing.js
//=============================================================================

/*:
 * @plugindesc Fonctions d'accélération
 * @author Sphinx
 *
 * @help
 * //==========================================================================
 * // Plugin : Sphinx-MathEasing
 * // Date   : 29 décembre 2019
 * // Auteur : Sphinx
 * //==========================================================================
 * Fonctions d'accélérations. Retourne la valeur de la propriété à un instant T
 * d'une animation
 * 
 * Ces équations de ont été trouvées sur le site http://www.gizma.com/easing/
 * et ont été assemblées dans un plugin par moi-même.
 * Vous pouvez bien entendu rajouter vos propres équations en enrichissant
 * l'objet Math.
 * 
 * Chacune de ces fonctions prend 4 arguments en paramètres, dans cet ordre :
 *  - t : temps écoulé (depuis le début de l'animation)
 *  - b : valeur au début de l'animation
 *  - c : décallage à la fin de l'animation par rapport à la valeur au début
 *  - d : durée totale de l'animation
 * 
 * Liste des fonctions d'accélération disponibles :
 *  - Math.easing.linearTween
 *  - Math.easing.easeInQuad
 *  - Math.easing.easeOutQuad
 *  - Math.easing.easeInOutQuad
 *  - Math.easing.easeInCubic
 *  - Math.easing.easeOutCubic
 *  - Math.easing.easeInOutCubic
 *  - Math.easing.easeInQuart
 *  - Math.easing.easeOutQuart
 *  - Math.easing.easeInOutQuart
 *  - Math.easing.easeInQuint
 *  - Math.easing.easeOutQuint
 *  - Math.easing.easeInOutQuint
 *  - Math.easing.easeInSine
 *  - Math.easing.easeOutSine
 *  - Math.easing.easeInOutSine
 *  - Math.easing.easeInExpo
 *  - Math.easing.easeOutExpo
 *  - Math.easing.easeInOutExpo
 *  - Math.easing.easeInCirc
 *  - Math.easing.easeOutCirc
 *  - Math.easing.easeInOutCirc
 * 
 * Ce plugin n'a pas beaucoup d'effet seul, il a vocation à être utilisé dans
 * d'autres plugins utilisant des animations, par exemple.
 * 
 * Dépendances :
 *     Aucune
 */
Math.easing = {};

Math.easing.linearTween = function (t, b, c, d) {
    return c*t/d + b;
};

Math.easing.easeInQuad = function (t, b, c, d) {
    t /= d;
    return c*t*t + b;
};

Math.easing.easeOutQuad = function (t, b, c, d) {
    t /= d;
    return -c * t*(t-2) + b;
};

Math.easing.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
};

Math.easing.easeInCubic = function (t, b, c, d) {
    t /= d;
    return c*t*t*t + b;
};

Math.easing.easeOutCubic = function (t, b, c, d) {
    t /= d;
    t--;
    return c*(t*t*t + 1) + b;
};

Math.easing.easeInOutCubic = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t*t + b;
    t -= 2;
    return c/2*(t*t*t + 2) + b;
};

Math.easing.easeInQuart = function (t, b, c, d) {
    t /= d;
    return c*t*t*t*t + b;
};

Math.easing.easeOutQuart = function (t, b, c, d) {
    t /= d;
    t--;
    return -c * (t*t*t*t - 1) + b;
};

Math.easing.easeInOutQuart = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t*t*t + b;
    t -= 2;
    return -c/2 * (t*t*t*t - 2) + b;
};

Math.easing.easeInQuint = function (t, b, c, d) {
    t /= d;
    return c*t*t*t*t*t + b;
};

Math.easing.easeOutQuint = function (t, b, c, d) {
    t /= d;
    t--;
    return c*(t*t*t*t*t + 1) + b;
};

Math.easing.easeInOutQuint = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t*t*t*t + b;
    t -= 2;
    return c/2*(t*t*t*t*t + 2) + b;
};

Math.easing.easeInSine = function (t, b, c, d) {
    return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
};

Math.easing.easeOutSine = function (t, b, c, d) {
    return c * Math.sin(t/d * (Math.PI/2)) + b;
};

Math.easing.easeInOutSine = function (t, b, c, d) {
    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};

Math.easing.easeInExpo = function (t, b, c, d) {
    return c * Math.pow( 2, 10 * (t/d - 1) ) + b;
};

Math.easing.easeOutExpo = function (t, b, c, d) {
    return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b;
};

Math.easing.easeInOutExpo = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
    t--;
    return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
};

Math.easing.easeInCirc = function (t, b, c, d) {
    t /= d;
    return -c * (Math.sqrt(1 - t*t) - 1) + b;
};

Math.easing.easeOutCirc = function (t, b, c, d) {
    t /= d;
    t--;
    return c * Math.sqrt(1 - t*t) + b;
};

Math.easing.easeInOutCirc = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
    t -= 2;
    return c/2 * (Math.sqrt(1 - t*t) + 1) + b;
};

Vous pouvez, bien entendu, ajouter vos propres formules. La seule contrainte à respecter est la suivante. Votre fonction doit prendre ces 4 paramètres et dans l’ordre :

  • Le temps écoulé
  • La valeur de départ
  • La modification totale
  • Et la durée totale de l’animation

Votre fonction vous retournera la valeur actuelle. Il est évident que ces 4 paramètres sont nécessairement des nombres, entiers ou décimaux, positifs ou négatifs. Mais allons-y dans l’ordre.

Le temps écoulé et la durée totale de l’animation

C’est le ratio du temps écoulé par rapport à la durée totale qui détermine le pourcentage de l’animation écoulée. Et c’est ce qui permettra de déterminer la valeur actuelle en fonction d’une courbe déterminée par l’équation correspondant à la méthode.

La valeur de départ et la modification totale

La modification totale correspond à la valeur attendue à la fin de l’animation moins la valeur de départ.

L’usage que vous ferez de ces fonctions dépend de la valeur de départ que vous passerez à la fonction. Moi je me suis servi de ces méthodes pour créer les animations des Sphinx-Chart2. Je me suis aussi servi de ces méthodes pour mon script Sphinx-GameClock, pour actualiser la teinte de l’écran en fonction de l’heure.

Les courbes d’accélération incluses

Voici la liste des courbes d’accélération que j’ai agrégé dans ce plugin :

  • linearTween
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInQuint
  • easeOutQuint
  • easeInOutQuint
  • easeInSine
  • easeOutSine
  • easeInOutSine
  • easeInExpo
  • easeOutExpo
  • easeInOutExpo
  • easeInCirc
  • easeOutCirc
  • easeInOutCirc

Pour bien visualiser les courbes correspondant à chacune de ces méthodes, j’ai créé une scène assez basique :

//=============================================================================
// Sphinx-Chart2EasingScene.js
//=============================================================================

/*:
 * @plugindesc Scène de démonstration du plugin Sphinx-MathEasing
 * @author Sphinx
 *
 * @help
 * //==========================================================================
 * // Plugin : Sphinx-Chart2EasingScene
 * // Date   : 30 décembre 2019
 * // Auteur : Sphinx
 * //==========================================================================
 * 
 * Dépendances :
 *     - Sphinx-Chart2
 * @param background
 * @text Image d'arrière plan de la scène
 * @type file
 * @dir img/titles1/
 * @require 1
 */
//-----------------------------------------------------------------------------
// Game_Interpreter
//
// Commandes de plugin
Sphinx_ChartEasing_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
    Sphinx_ChartEasing_Game_Interpreter_pluginCommand.call(this, command, args);
    if(command === "DEMO_EASING_GRAPH") {
        SceneManager.push(Scene_EasingChart2);
    }
};

//-----------------------------------------------------------------------------
// Scene_EasingChart2
//
// Scène de démonstration du plugin Sphinx-Chart2
function Scene_EasingChart2() {
    this.initialize.apply(this, arguments);
};

Scene_EasingChart2.prototype = Object.create(Scene_Base.prototype);
Scene_EasingChart2.prototype.constructor = Scene_EasingChart2;

Scene_EasingChart2.prototype.initialize = function() {
    Scene_Base.prototype.initialize.call(this);
};

Scene_EasingChart2.prototype.create = function() {
    Scene_Base.prototype.create.call(this);
    this.createBackground();
    this.createTexts();
    this.createButtons();
    this.listEasing = Object.keys(Math.easing);
    this.easing = 0;
};

Scene_EasingChart2.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    this.drawGraph();
    this.startFadeIn(this.fadeSpeed(), false);
};

Scene_EasingChart2.prototype.terminate = function() {
    Scene_Base.prototype.terminate.call(this);
    SceneManager.goto(Scene_Map);
    this.startFadeOut(this.fadeSpeed(), false);
};

Scene_EasingChart2.prototype.update = function() {
    Scene_Base.prototype.update.call(this);
    if(Input.isTriggered("cancel")) {
        SoundManager.playCancel();
        this.terminate();
    }
};

Scene_EasingChart2.prototype.createBackground = function() {
    this._background = new Sprite_Base();
    background = PluginManager.parameters("Sphinx-Chart2EasingScene")["background"];
    this._background.bitmap = ImageManager.loadTitle1(background);
    this.addChildAt(this._background, 0);
};

Scene_EasingChart2.prototype.createTexts = function() {
    this._titleText = new Sprite_Base();
    this._titleText.x = 0;
    this._titleText.y = 0;
    this._titleText.width = Graphics.boxWidth;
    this._titleText.height = (Graphics.boxHeight - 480) / 2;
    this._titleText.bitmap = new Bitmap(Graphics.boxWidth, (Graphics.boxHeight - 480) / 2);
    this._titleText.bitmap.drawText("Méthodes d'accélération - Math.easing", 0, 16, Graphics.boxWidth - 32, 40, "center");
    this.addChildAt(this._titleText, 1);
    
    this._explicationText1 = new Sprite_Base();
    this._explicationText1.x = 0;
    this._explicationText1.y = Graphics.boxHeight - ((Graphics.boxHeight - 480) / 2);
    this._explicationText1.width = Graphics.boxWidth;
    this._explicationText1.height = (Graphics.boxHeight - 480) / 4;
    this._explicationText1.bitmap = new Bitmap(Graphics.boxWidth, (Graphics.boxHeight - 480) / 4);
    this._explicationText1.bitmap.fontSize = 18;
    this._explicationText1.bitmap.drawText("Naviguez entre les graphiques grâce aux flèches.", 0, 8, Graphics.boxWidth - 32, 20, "center");
    this.addChildAt(this._explicationText1, 2);
    
    this._explicationText2 = new Sprite_Base();
    this._explicationText2.x = 0;
    this._explicationText2.y = Graphics.boxHeight - ((Graphics.boxHeight - 480) / 4);
    this._explicationText2.width = Graphics.boxWidth;
    this._explicationText2.height = (Graphics.boxHeight - 480) / 4;
    this._explicationText2.bitmap = new Bitmap(Graphics.boxWidth, (Graphics.boxHeight - 480) / 4);
    this._explicationText2.bitmap.fontSize = 18;
    this._explicationText2.bitmap.drawText("gauche et droite de votre clavier.", 0, 8, Graphics.boxWidth - 32, 20, "center");
    this.addChildAt(this._explicationText2, 3);
};

Scene_EasingChart2.prototype.createButtons = function() {
    var bitmap = ImageManager.loadSystem('ButtonSet');
    var buttonLeft = new Sprite_Button();
    buttonLeft.bitmap = bitmap;
    buttonLeft.setColdFrame(48, 0, 48, 48);
    buttonLeft.setHotFrame(48, 48, 48, 48);
    buttonLeft.rotation = 90 * Math.PI / 180;
    buttonLeft.anchor.x = 0.5;
    buttonLeft.anchor.y = 0.5;
    buttonLeft.x = 16 + 24;
    buttonLeft.y = (Graphics.boxHeight - 48) / 2;
    buttonLeft.setClickHandler(Scene_EasingChart2.prototype.goToLeft.bind(this));
    this.addChild(buttonLeft);
    
    var buttonRight = new Sprite_Button();
    buttonRight.bitmap = bitmap;
    buttonRight.setColdFrame(96, 0, 48, 48);
    buttonRight.setHotFrame(96, 48, 48, 48);
    buttonRight.rotation = 90 * Math.PI / 180;
    buttonRight.anchor.x = 0.5;
    buttonRight.anchor.y = 0.5;
    buttonRight.x = Graphics.boxWidth - 16 - 24;
    buttonRight.y = (Graphics.boxHeight - 48) / 2;
    buttonRight.setClickHandler(Scene_EasingChart2.prototype.goToRight.bind(this));
    this.addChild(buttonRight);
};

Scene_EasingChart2.prototype.goToLeft = function() {
    this.easing--;
    if(this.easing < 0) this.easing = this.listEasing.length - 1;
    this.drawGraph();
};

Scene_EasingChart2.prototype.goToRight = function() {
    this.easing++;
    if(this.easing >= this.listEasing.length) this.easing = 0;
    this.drawGraph();
};

Scene_EasingChart2.prototype.drawGraph = function() {
    categories = [ this.listEasing[this.easing] ];
    xLabels = [];
    datas = [ [] ];
    for(i = 0; i <= 150; ++i) {
        xLabels.push(i);
        datas[0].push(Math.easing[this.listEasing[this.easing]](i, 0, 150, 150));
    }
    if(this.chart) {
        this.chart.destroy();
    }
    console.log(this.listEasing[this.easing], datas);
    this.chart = new SphinxChart2({
        type: "line",
        title: "Easing - " + this.listEasing[this.easing].capitalize(),
        categoriesLabels: categories,
        xAxisLabels: xLabels,
        datas: datas,
        options: {
            easing: this.listEasing[this.easing],
            duration: 1,
            background: "transparent",
            forceMinToZero: false,
            position: {
                x: 88,
                y: (Graphics.boxHeight - 480) / 2,
                width: 640,
                height: 480,
            },
            padding: {
                top: 10,
                left: 25,
                right: 25,
                bottom: 25,
            }
        }
    });
    this.addChildAt(this.chart, 4);
};

Scene_EasingChart2.prototype.fastForwardRate = function() {
    return 3;
};

Scene_EasingChart2.prototype.isFastForward = function() {
    return (Input.isPressed('ok') || Input.isPressed('shift') || TouchInput.isPressed());
};

Scene_EasingChart2.prototype.updateFade = function() {
    if(this._fadeDuration > 0) {
        var d = this._fadeDuration;
        if(this.isFastForward()) {
            d -= this.fastForwardRate() - 1;
            this._fadeDuration -= this.fastForwardRate();
        } else {
            this._fadeDuration--;
        }
        if(this._fadeSign > 0) {
            this._fadeSprite.opacity -= this._fadeSprite.opacity / d;
        } else {
            this._fadeSprite.opacity += (255 - this._fadeSprite.opacity) / d;
        }
    }
};

Scene_EasingChart2.prototype.fadeSpeed = function(ignoreFast) {
    return 30;
};

Pour fonctionner, cette scène nécessite l’installation du script Sphinx-Chart2.

Pour ouvrir cette scène, qui permet de naviguer entre les méthodes d’easing, il suffit d’appeler cette commande de plugin : DEMO_EASING_GRAPH.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.