//=============================================================================
// Simple_Breathing_Picture.js
//=============================================================================
/*:
 * @plugindesc 简单图片呼吸效果插件
 * @author 简化版修改者
 *
 * @help
 * 使用方法:
 * 1. 显示带有呼吸效果的图片
 *    SceneManager._scene.showBreathingPicture(imageName, x, y, breathSpeed);
 *    参数说明:
 *    imageName: 图片文件名(无需后缀,需放在 img/pictures 文件夹下,以 ^ 开头)
 *    x: 图片在屏幕上的 x 坐标
 *    y: 图片在屏幕上的 y 坐标
 *    breathSpeed: 呼吸效果的速度,值越大呼吸效果越明显
 *
 * 2. 删除带有呼吸效果的图片
 *    SceneManager._scene.removeBreathingPicture(spriteId);
 *    参数说明:
 *    spriteId: 图片文件名中 _ 后面的部分,例如 ^3_KYjoke 中的 KYjoke
 *
 * 3. 调节呼吸效果大小
 *    SceneManager._scene.adjustBreathSpeed(spriteId, newBreathSpeed);
 *    参数说明:
 *    spriteId: 图片文件名中 _ 后面的部分,例如 ^3_KYjoke 中的 KYjoke
 *    newBreathSpeed: 新的呼吸效果速度,值越大呼吸效果越明显
 */
(function() {
    const scenes = [Scene_Map];
    const imageCache = {};
    const spriteMap = new Map();
    let lastTime = performance.now();
    scenes.forEach(function(scene) {
        const originalUpdate = scene.prototype.update;
        scene.prototype.update = function() {
            originalUpdate.call(this);
            const currentTime = performance.now();
            const deltaTime = (currentTime - lastTime) / 1000; // 转换为秒
            lastTime = currentTime;
            this.updateBreathingSprites(deltaTime);
        };
        scene.prototype.updateBreathingSprites = function(deltaTime) {
            if (!this.sprites) return;
            for (const sprite of this.sprites) {
                if (sprite.breathing) {
                    sprite.breathTime = (sprite.breathTime || 0) + deltaTime;
                    const easeInOutSine = (time) => sprite.breathSpeed * Math.sin(Math.PI * time);
                    const breathEffectX = 0.005 * easeInOutSine(sprite.breathTime / 3) / (sprite.scale.x * sprite.scale.x);
                    const breathEffectY = 0.005 * easeInOutSine(sprite.breathTime / 1) / (sprite.scale.y * sprite.scale.y);
                    sprite.scale.x = 1 + breathEffectX;
                    sprite.scale.y = 1 + breathEffectY;
                }
            }
        };
        scene.prototype.showBreathingPicture = function(imageName, x, y, breathSpeed) {
            if (!this.sprites) {
                this.sprites = [];
            }
            const spriteId = imageName.split('^')[1].split('_')[1];
            if (spriteMap.has(spriteId)) {
                return; // 避免重复添加
            }
            const sprite = new Sprite();
            sprite.spriteId = spriteId;
            sprite.breathing = true;
            sprite.breathSpeed = breathSpeed;
            sprite.x = x;
            sprite.y = y;
            sprite.anchor.set(0.5, 0);
            if (!imageCache[imageName]) {
                imageCache[imageName] = ImageManager.loadBitmap('img/pictures/', imageName, 0, false);
            }
            sprite.bitmap = imageCache[imageName];
            this.addChild(sprite);
            this.sprites.push(sprite);
            spriteMap.set(spriteId, sprite);
            // 添加淡入效果
            sprite.opacity = 0;
            const fadeInDuration = 300; // 淡入时间(毫秒)
            const fadeInStart = performance.now();
            const fadeIn = () => {
                const elapsed = performance.now() - fadeInStart;
                if (elapsed < fadeInDuration) {
                    sprite.opacity = (elapsed / fadeInDuration) * 255;
                    requestAnimationFrame(fadeIn);
                } else {
                    sprite.opacity = 255;
                }
            };
            requestAnimationFrame(fadeIn);
        };
        scene.prototype.removeBreathingPicture = function(spriteId) {
            if (!spriteMap.has(spriteId)) return;
            const sprite = spriteMap.get(spriteId);
            const spriteIndex = this.sprites.indexOf(sprite);
            // 添加淡出效果
            const fadeOutDuration = 300; // 淡出时间(毫秒)
            const fadeOutStart = performance.now();
            const fadeOut = () => {
                const elapsed = performance.now() - fadeOutStart;
                if (elapsed < fadeOutDuration) {
                    sprite.opacity = 255 - (elapsed / fadeOutDuration) * 255;
                    requestAnimationFrame(fadeOut);
                } else {
                    sprite.opacity = 0;
                    this.removeChild(sprite);
                    this.sprites.splice(spriteIndex, 1);
                    spriteMap.delete(spriteId);
                    sprite.bitmap = null; // 释放位图资源
                    // 清理不再使用的图片缓存
                    const imageName = Object.keys(imageCache).find(key => key.includes(spriteId));
                    if (imageName) {
                        delete imageCache[imageName];
                    }
                }
            };
            requestAnimationFrame(fadeOut);
        };
        scene.prototype.adjustBreathSpeed = function(spriteId, newBreathSpeed) {
            const sprite = spriteMap.get(spriteId);
            if (sprite) {
                sprite.breathSpeed = newBreathSpeed;
            }
        };
    });
})();
使用示例
// 显示立绘(带呼吸效果)
SceneManager._scene.showBreathingPicture("^3_KYjoke", 320, 240, 0.05);
// 3秒后删除立绘
setTimeout(() => {
  SceneManager._scene.removeBreathingPicture("KYjoke");
}, 3000);
// 调节呼吸速度
SceneManager._scene.adjustBreathSpeed("KYjoke", 0.08);
参数说明:
spriteId:图片文件名中 _ 后面的部分,例如 ^3_KYjoke 中的 KYjoke。