sakura-gozen/js/plugins/iii/iiiEnemyAnimation.js
2025-02-19 10:16:07 -06:00

220 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// iiiEnemyAnimation.js
//=============================================================================
/*: ja
* @target MZ
* @plugindesc エネミー画像のパタパタアニメ機能を提供します
* @author iii
*
* @help
* ■ 基本的な使い方
* 敵キャラのメモ欄に
* <enmAnim>
* と記載してください。パタパタアニメ対象として認識し、アニメ再生します。
*
* ■ 敵キャラ画像名の命名規則
* ファイル名_コマ番号.png の形式で命名してください。コマ番号は01から始めてください。
* 例Enemy1_01.png、Enemy_1_01.png
* コマ番号は連番になるように命名してください。
*
* ■ あるステートの時のみ画像ファイルを切り替えたい場合
* ファイル名_ステートID_コマ番号.png の形式で命名し、以下を敵キャラのメモ欄に記載してください。
* <enmAnim_states:41> // ステート番号・41のときに画像を切り替えたい場合
*
* ファイル名例Enemy1_41_01.png
*
* ■ 敵キャラ毎の個別設定
* 敵キャラのメモ欄に以下のように指定すると個別に設定ができます。
* 指定が無いものはプラグインパラメータの値を用います。
*
* <enmAnim_updateRate:30> // 30フレーム毎に画像を切り替えます
* <enmAnim_numOfFrame:3> // 最大フレーム数
* <enmAnim_framePattern:1,2,3,2> // アニメ再生のフレームパターン
*
* -----
*
* @param enemy_update_rate
* @desc デフォルトの画像切り替えフレーム数。この値毎に画像切り替えを行います。
* @type number
* @default 60
*
* @param enemy_num_of_frame
* @desc デフォルトの最大パターン数
* @type number
* @default 3
*
* @param enemy_frame_pattern
* @desc デフォルトのフレーム再生順。フレームの数は1から始まるように指定してください。
* 指定が無ければ [1, 2, 3, ... enemy_num_of_frame] でループします。
* @type number[]
* @default []
*
* @param glow_target_states
* @desc グローエフェクトを発現するステートIDを指定してください
* @type state[]
* @default []
*
*/
(() => {
"use strict";
const script = document.currentScript;
const pluginParam = PluginManagerEx.createParameter(script);
const glowTargetStates = pluginParam.glow_target_states;
// 外部からアニメ速度調整用
Sprite_Enemy.iiiDelayFrame = 0;
const _Sprite_Enemy_prototype_initialize = Sprite_Enemy.prototype.initialize;
Sprite_Enemy.prototype.initialize = function (battler) {
_Sprite_Enemy_prototype_initialize.call(this, battler);
this._enemyAnimEnable = false;
this._frameCount = 0;
this._updateRate = parseInt(pluginParam.enemy_update_rate, 10);
this._numOfFrame = parseInt(pluginParam.enemy_num_of_frame, 10);
this._animImages = [];
this._animPattern = [];
this._stateAnimImages = { 0: [] };
const enemyData = this._enemy.enemy();
const pluginMeta = enemyData.meta;
if (!pluginMeta || !pluginMeta.enmAnim) return; //アニメ指定無し
this._enemyAnimEnable = true;
if (pluginMeta.enmAnim_updateRate) {
this._updateRate = parseInt(pluginMeta.enmAnim_updateRate, 10);
}
if (pluginMeta.enmAnim_numOfFrame) {
this._numOfFrame = parseInt(pluginMeta.enmAnim_numOfFrame, 10);
}
let stateIds = [0];
let hasStateIds = false;
if (pluginMeta.enmAnim_states) {
hasStateIds = true;
let sids = pluginMeta.enmAnim_states
.split(",")
.map((s) => parseInt(s, 10));
sids.forEach((sid) => {
stateIds.push(sid);
});
}
// アニメ用の画像を前読み
let nameArray = battler.battlerName().split("_");
let defaultImageName = nameArray
.slice(0, Math.max(nameArray.length - 1, 1))
.join("_");
let hue = battler.battlerHue();
this._animImages = [];
for (var i = 0; i < this._numOfFrame; i++) {
let bitmap = null;
let animIdx = i;
let frameNo = i + 1;
stateIds.forEach((sid) => {
if (!this._stateAnimImages[sid]) {
this._stateAnimImages[sid] = [];
}
let imageName = "";
if (sid <= 0) {
//状態異常指定がない場合
imageName = defaultImageName + "_" + ("00" + frameNo).slice(-2);
} else {
imageName =
defaultImageName +
"_" +
("000" + sid).slice(-3) +
"_" +
("00" + frameNo).slice(-2);
}
if ($gameSystem.isSideView()) {
bitmap = ImageManager.loadSvEnemy(imageName, hue);
} else {
bitmap = ImageManager.loadEnemy(imageName, hue);
}
this._stateAnimImages[sid][animIdx] = bitmap;
}, this);
this._animPattern[animIdx] = frameNo; //デフォルトはコマ番号順
}
this._animImages = this._stateAnimImages[0];
//プラグインパラメータで指定があればそちらを利用
if (
pluginParam.enemy_frame_pattern &&
pluginParam.enemy_frame_pattern.length > 0
) {
this._animPattern = pluginParam.enemy_frame_pattern;
}
//敵キャラの個別指定があればそちらを利用
if (pluginMeta.enmAnim_framePattern) {
this._animPattern = pluginMeta.enmAnim_framePattern
.split(",")
.map((s) => parseInt(s, 10));
}
this._glowFilter = new PIXI.filters.GlowFilter({
distance: 15, // グロー距離。フィルタ作成後の変更不可
color: 0xdd0000,
innerStrength: 0, // 内側へのグロー強さ
outerStrength: 0, // 外側へのグロー強さ
});
this.filters = [this._glowFilter];
};
const _Sprite_Enemy_updateBitmap = Sprite_Enemy.prototype.updateBitmap;
Sprite_Enemy.prototype.updateBitmap = function () {
_Sprite_Enemy_updateBitmap.call(this);
if (!this._enemyAnimEnable) return;
//アニメ更新
if (
Sprite_Enemy.iiiDelayFrame > 0 &&
Graphics.frameCount % Sprite_Enemy.iiiDelayFrame != 0
) {
return;
}
this._frameCount++;
let anmIndex =
parseInt(this._frameCount / this._updateRate, 10) %
this._animPattern.length;
let imgIndex = (this._animPattern[anmIndex] - 1) % this._animImages.length;
// 状態異常時の画像変更指定があれば差し替え
if (Object.keys(this._stateAnimImages).length > 0) {
this._animImages = this._stateAnimImages[0]; //デフォルトは状態異常無しを指定
let len = this._enemy._states.length;
for (var i = 0; i < len; i++) {
let state = this._enemy._states[i];
if (this._stateAnimImages[state])
this._animImages = this._stateAnimImages[state];
}
}
this.bitmap = this._animImages[imgIndex];
};
const _Sprite_Enemy_prototype_update = Sprite_Enemy.prototype.update;
Sprite_Enemy.prototype.update = function () {
_Sprite_Enemy_prototype_update.call(this);
const enemyStates = this._enemy._states;
if (glowTargetStates && enemyStates) {
const glowEnable = enemyStates.find(
(s) => glowTargetStates.findIndex((t) => t == s) >= 0
);
this._glowFilter.enabled = glowEnable;
if (this._glowFilter.enabled) {
const maxStrength = 5;
const glowTime = Graphics.frameCount / 60;
const cosLen = Math.cos(glowTime);
this._glowFilter.outerStrength = maxStrength * Math.abs(cosLen);
}
}
};
})();