图片序号范围动画插件



/*:
* @target MZ
* @plugindesc 图片序号范围动画插件
* @author Doubao
* @help
* 插件功能:支持按图片序号范围定义多个动画
*
* 使用方法:
* 1. 将图片放入img/animations/目录,命名为anim_序号.png
* 2. 在事件脚本中调用:
* startRangeAnimation(动画ID, 起始帧, 结束帧, 图层, 位置X, 位置Y, 帧率, 循环次数)
*
* @param defaultFps
* @text 默认帧率
* @desc 动画的默认播放速度(帧/秒)
* @type number
* @default 5
*
* @param defaultLoop
* @text 默认循环次数
* @desc 0为无限循环,默认1次
* @type number
* @default 1
*/
(function() {
'use strict';

const parameters = PluginManager.parameters('RangeAnimation');
const DEFAULT_FPS = Number(parameters['defaultFps'] || 5);
const DEFAULT_LOOP = Number(parameters['defaultLoop'] || 1);

// 存储所有活跃动画
const activeAnimations = [];

// 动画对象定义
class AnimationInstance {
constructor(id, startFrame, endFrame, z, x, y, fps, loopCount) {
this.id = id;
this.startFrame = startFrame;
this.endFrame = endFrame;
this.z = z;
this.x = x;
this.y = y;
this.fps = fps || DEFAULT_FPS;
this.loopCount = loopCount !== undefined ? loopCount : DEFAULT_LOOP;

this.frames = [];
this.currentFrame = 0;
this.frameCount = 0;
this.loopCounter = 0;
this.isPlaying = true;

this.loadFrames();
}

// 加载动画帧
loadFrames() {
for (let frameIndex = this.startFrame; frameIndex <= this.endFrame; frameIndex++) { const fileName = `anim_${frameIndex}`; const bitmap = ImageManager.loadAnimation(fileName); if (bitmap.width === 0) { console.error(`未找到动画图片: ${fileName}`); continue; } const sprite = new Sprite(); sprite.bitmap = bitmap; sprite.visible = frameIndex === this.startFrame; sprite.z = this.z; sprite.x = this.x; sprite.y = this.y; SceneManager._scene.addChild(sprite); this.frames.push(sprite); } if (this.frames.length === 0) { console.error(`动画 ${this.id} 没有有效帧`); } } // 更新动画状态 update() { if (!this.isPlaying || this.frames.length === 0) return; this.frameCount++; if (this.frameCount >= 60 / this.fps) {
this.frameCount = 0;

// 隐藏当前帧
this.frames[this.currentFrame].visible = false;

// 显示下一帧
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
this.frames[this.currentFrame].visible = true;

// 检查循环
if (this.currentFrame === 0) {
this.loopCounter++;
if (this.loopCount > 0 && this.loopCounter >= this.loopCount) {
this.stop();
}
}
}
}

// 停止动画
stop() {
this.isPlaying = false;
this.frames.forEach(sprite => {
if (sprite.parent) sprite.parent.removeChild(sprite);
});
this.frames = [];

// 从活跃列表中移除
const index = activeAnimations.findIndex(anim => anim.id === this.id);
if (index !== -1) {
activeAnimations.splice(index, 1);
}
}
}

// 开始动画
function startRangeAnimation(animationId, startFrame, endFrame, z = 1000, x = 0, y = 0, fps, loopCount) {
// 停止同名动画(避免重复)
stopAnimation(animationId);

const anim = new AnimationInstance(animationId, startFrame, endFrame, z, x, y, fps, loopCount);
activeAnimations.push(anim);
return anim;
}

// 停止单个动画
function stopAnimation(animationId) {
const anim = activeAnimations.find(anim => anim.id === animationId);
if (anim) anim.stop();
}

// 停止所有动画
function stopAllAnimations() {
activeAnimations.forEach(anim => anim.stop());
activeAnimations.length = 0;
}

// 更新所有动画
const _Scene_Map_update = Scene_Map.prototype.update;
Scene_Map.prototype.update = function() {
_Scene_Map_update.call(this);
activeAnimations.forEach(anim => anim.update());
};

// 地图切换时清理
const _Scene_Map_terminate = Scene_Map.prototype.terminate;
Scene_Map.prototype.terminate = function() {
_Scene_Map_terminate.call(this);
stopAllAnimations();
};

// 导出全局函数
window.startRangeAnimation = startRangeAnimation;
window.stopAnimation = stopAnimation;
window.stopAllAnimations = stopAllAnimations;
})();

使用方法

// 示例1:播放1-5帧作为一个动画
startRangeAnimation("walk", 1, 5, 1000, 100, 100, 5, 0);

// 示例2:播放6-10帧作为另一个动画
startRangeAnimation("attack", 6, 10, 1001, 100, 100, 8, 1);

// 示例3:同时播放多个动画
startRangeAnimation("fire", 11, 15, 900, 200, 200, 6, 0);
startRangeAnimation("smoke", 16, 20, 800, 200, 200, 4, 0);

// 停止特定动画
stopAnimation("walk");

// 停止所有动画
stopAllAnimations();

核心功能
序号范围控制:
通过 startFrame 和 endFrame 参数指定图片序号范围
支持不连续的动画片段(如 1-5, 11-15)
多动画并行:
每个动画有独立的 ID、位置和播放参数
支持任意数量的动画同时播放
灵活控制:
可单独停止特定动画或全部动画
返回动画实例,支持更细粒度的控制(如暂停、调速)
注意事项
图片命名:
图片必须位于 img/animations/ 目录
命名格式必须为 anim_序号.png(如 anim_1.png, anim_2.png)
性能优化:
同时播放过多动画可能导致性能下降
建议控制活跃动画数量(通常不超过 10 个)
调试方法:
检查控制台输出,确认图片加载情况
确保 startFrame 和 endFrame 在有效范围内
这个版本通过序号范围机制,实现了同一组图片的灵活复用,适合需要从大动画集中拆分独立动作的场景。


发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注