ページ 11

ステートに応じて「Battler/Enemy画像を流用した」エフェクトを背後に表示する方法について

Posted: 2024年11月01日(金) 19:46
by youtu
戦闘中にBattler/Enemyのステート状態に応じてその背後に「Battler/Enemy画像を流用した」エフェクトを表示する機能が欲しいと考え、現在プラグインを作成しているのですが、Spriteの表示順序にて問題を抱えています。

コード: 全て選択

(() => {
    const parameters = PluginManager.parameters('AuraEffectState');
    const stateIds = JSON.parse(parameters['対象ステートID']);
    const maxScale = Number(parameters['最大拡大サイズ']);
    const speed = Number(parameters['拡大・縮小のスピード']);
    const opacity = Number(parameters['エネミー画像の不透明度']);
    const color = parameters['背景画像の色相'];
    const blendMode = Number(parameters['背景画像のブレンドモード']);

    //override
    const _Sprite_Battler_update = Sprite_Battler.prototype.update;
    Sprite_Battler.prototype.update = function() {
        _Sprite_Battler_update.call(this);
        this.updateAuraEffect();
    };

    Sprite_Battler.prototype.updateAuraEffect = function() {
        if (this._battler && this.isAffectedAnyState(stateIds)) {
            if (!this._auraeffectSprite) {
                this._auraeffectSprite = new Sprite(this.bitmap);
                this._auraeffectSprite.blendMode = blendMode;
                this._auraeffectSprite.opacity = opacity;
                this._auraeffectSprite.tint = color;
                this.addChild(this._auraeffectSprite);
                this._auraeffectSprite.z = -1;
                this._scaleDirection = 1;
            }
            
            this._auraeffectSprite.scale.x += speed * this._scaleDirection;
            this._auraeffectSprite.scale.y += speed * this._scaleDirection;
            
            if (this._auraeffectSprite.scale.x >= maxScale || this._auraeffectSprite.scale.x <= 1) {
                this._scaleDirection *= -1;
            }

            this._auraeffectSprite.x = -this.bitmap.width / 2 - this.bitmap.width * ((this._auraeffectSprite.scale.x - 1) / 2);//位置調整…要修正
            this._auraeffectSprite.y = -this.bitmap.height - this.bitmap.height * ((this._auraeffectSprite.scale.y - 1) / 2);//位置調整…要修正
        
        } else if (this._auraeffectSprite) {
            this.removeChild(this._auraeffectSprite);
            this._auraeffectSprite = null;
        }
    };

    Sprite_Battler.prototype.isAffectedAnyState = function(stateIds) {
        return stateIds.some(stateId => this._battler.isStateAffected(Number(stateId)));
    };
})();
目的としてはBattler/Enemyの背面にthis._auraeffectSpriteを表示したいのですが、Spriteのz値を変更してもBattler/Enemyの前面にthis._auraeffectSpriteが表示されてしまいます。
おそらくクラスの親子関係が原因と推定しているのですが、あいにく戦闘シーンの構造がよくわかっていないため、どのように修正すべきか手も足も出せない状態にあります。
どなたかお力を貸していただけると幸いです。

備考として、類似プラグインにMOG_AuraEffectが既に存在しますが、下記の問題があるため利用していません。
①ステートに応じて表示の可否を設定できない。
②利用クラス(Spriteset_Battle)が他のプラグイン(例えば、TMBattleEx・BattleMist等-Sprite_Enemyを利用するもの)と競合を起こす。

Re: ステートに応じて「Battler/Enemy画像を流用した」エフェクトを背後に表示する方法について

Posted: 2024年11月01日(金) 21:16
by Plasma Dark
Sprite_Battlerインスタンスの子要素にしてしまうと、前面に表示されてしまいますね。
Sprite_Battlerよりも前にSpriteset_Battleの_battleFieldの子要素に追加しておいて、条件に応じて表示非表示を切り替えるのが良さそうです。

例えば、敵キャラであればこんな感じにできそうな気がします。

コード: 全て選択

const _createEnemies = Spriteset_Battle.prototype.createEnemies;
Spriteset_Battle.prototype.createEnemies = function () {
  const sprites = $gameTroop.members().map(enemy => new Sprite_EnemyAuraEffect(enemy)).sort((a, b) => this.compareEnemySprite(a, b));
  sprites.forEach(sprite => {
    sprite.hide();
    this._battleField.addChild(sprite);
  });
  _createEnemies.call(this);
};

class Sprite_EnemyAuraEffect extends Sprite_Enemy {
  update() {
    super.update();
    if (this._battler && stateIds.some(staetId => this._battler.isStateAffected(stateId))) {
      if (!this.visible) {
        this.show();
      }
    } else if (this.visible) {
      this.hide();
    }
  }
}

Re: ステートに応じて「Battler/Enemy画像を流用した」エフェクトを背後に表示する方法について

Posted: 2024年11月02日(土) 20:08
by youtu
やはりSprite_BattlerやEnemyだと前面表示になってしまうのですね...。
MOGプラグイン同様、Spriteset_Battleを利用するのがこの機能を実現する上で最適であるとして、問題なのは、TMBattleEx.jsなどのSprite_Battler/Enemyを利用した敵グラフィック改変プラグインと連携ができないという点ですね。
実際にDarkPlasmaさんの提案したコードを参考にした以下のプラグインは、確かにそれ単体としては狙った通りに機能するのですが、TMBattleExと組み合わせても敵グラフィック反転や伸長が反映されず、それぞれ独立してグラフィックを表示してしまいます。

コード: 全て選択

//=============================================================================
// AuraEffectState.js
// ----------------------------------------------------------------------------
// @Public Domain
// ----------------------------------------------------------------------------
// Version
// 1.0.0 2024/11/02 初版
//----------------------------------------------------------------------------
//=============================================================================

/*:ja
 * @plugindesc オーラエフェクトステート
 * @target MZ
 * @help
 * 特定ステートのエネミーに対し、その画像を周期的に拡大・縮小する形で、背後に表示します。
 * このプラグインにプラグインコマンドはありません。
 * 営利・非営利を問わず、自由に使用、変更、再配布が可能です。クレジットは必要ありません。
 *
 * @param 対象ステートID
 * @desc 対象ステートIDを設定します。(複数指定可) 
 * @type number[]
 * @default [0]
 * 
 * @param 最大拡大倍率
 * @desc 拡大時の最大倍率を設定します。
 * @default 1.1
 * 
 * @param 拡大・縮小のスピード
 * @desc 拡大・縮小のスピードを設定します。
 * @default 3
 * 
 * @param エネミー画像の不透明度
 * @desc エネミー画像の不透明度を設定します。(0~255)
 * @default 120
 * 
 * @param 背景画像の色相
 * @desc 背景画像の色相を設定します。(カラーコード)
 * @type string
 * @default 0xFFEC50
 *
 * @param 背景画像のブレンドモード
 * @desc 背景画像のブレンドモードを設定します。(0:通常 1:加算 2:乗算 3:スクリーン)
 * @default 0
 *  
 */
(() => {
    const parameters = PluginManager.parameters('AuraEffectState');
    const stateIds = JSON.parse(parameters['対象ステートID']);
    const maxscale = Number(parameters['最大拡大倍率'] || 1.1);
    const speed = Number(parameters['拡大・縮小のスピード'] || 3);
    const opacity = Number(parameters['エネミー画像の不透明度'] || 120);
    const color = String(parameters['背景画像の色相'] || 0xFFEC50);
    const blendMode = Number(parameters['背景画像のブレンドモード'] || 0);

    const _createEnemies = Spriteset_Battle.prototype.createEnemies;
    Spriteset_Battle.prototype.createEnemies = function () {
        const sprites = $gameTroop.members().map(enemy => new Sprite_EnemyAuraEffect(enemy)).sort((a, b) => this.compareEnemySprite(a, b));
        sprites.forEach(sprite => {
            sprite.scale.set(1, 1);
            sprite.opacity = opacity;
            sprite.blendMode = blendMode;
            sprite.tint = color;
            sprite.hide();
            this._battleField.addChild(sprite);
        });
        _createEnemies.call(this);
    };

    class Sprite_EnemyAuraEffect extends Sprite_Enemy {
        constructor() {
            super(...arguments);
            this._animationFrame = 0;
        }

        update() {
            super.update();
            this._animationFrame += speed / 100 
            this._animateScale();
            
            if (this._battler && stateIds.some(stateId => this._isStateAffected(this._battler, stateId))) {
                if (!this.visible) {
                    this.show();
                }
            } else if (this.visible) {
                this.hide();
            }
        }

        _isStateAffected(battler, stateId) {
            return battler.states().some(state => state.id == stateId);//緩くしないとisStateAffectedが機能しない?
           
        }

        _animateScale() {
            const scale = 1 + Math.abs(Math.sin(this._animationFrame) * (maxscale - 1));
            this.scale.set(scale, scale);
        }
        show() {
            super.show();
            this.opacity = opacity;//不透明度上書き対策
        }

        hide() {
            super.hide();
            this.opacity = opacity;//不透明度上書き対策
        }
    }
})();
以下の画像の通り、左側の敵キャラクター画像はTMBattleExの反転機能によって左右反転状態で表示されています。しかし、その背後にあるオーラエフェクトは元の画像通りに表示されてしまうのです。
a.jpg

Re: ステートに応じて「Battler/Enemy画像を流用した」エフェクトを背後に表示する方法について

Posted: 2024年11月03日(日) 03:05
by Plasma Dark
問題なのは、TMBattleEx.jsなどのSprite_Battler/Enemyを利用した敵グラフィック改変プラグインと連携ができないという点ですね。
ここまでわかっているのであれば、連携したいプラグインを読んで、対応する設計を考えるだけですね。
Sprite_Enemyインスタンスに対して何らかの処理を行っているのであれば、それを真似してみるのが手っ取り早そうですが、いかがでしょう。