Greasy Fork

Greasy Fork is available in English.

Drawaria Animation Library

Advanced drawing animation library for multiplayer drawing games

当前为 2025-08-17 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/546216/1643825/Drawaria%20Animation%20Library.js

// ==UserScript==
// @name         Drawaria Animation Library
// @namespace    drawaria-animations
// @version      1.0
// @description  Advanced drawing animation library for multiplayer drawing games
// @author       DrawArtist
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    
    // Core drawing animation functions
    const DRAWING_FUNCTIONS = {
        // Utility functions for drawing
        _delay: function(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        },
        
        _getRandomColor: function(saturation = 70, lightness = 50) {
            const hue = Math.floor(Math.random() * 360);
            return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
        },
        
        _sendDrawCmd: function(startPoint, endPoint, color, thickness) {
            try {
                if (!window.getGameSocket || !window.getGameSocket()) {
                    console.warn('Game socket not available');
                    return false;
                }
                
                const socket = window.getGameSocket();
                if (socket.readyState !== WebSocket.OPEN) {
                    console.warn('WebSocket not open');
                    return false;
                }
                
                // Simulate drawing command - adjust based on actual game API
                const drawData = {
                    type: 'draw',
                    from: startPoint,
                    to: endPoint,
                    color: color,
                    thickness: thickness
                };
                
                socket.send(JSON.stringify(drawData));
                return true;
            } catch (error) {
                console.error('Error sending draw command:', error);
                return false;
            }
        },
        
        _drawPixel: async function(x, y, size, color, delay = 0) {
            const result = this._sendDrawCmd([x, y], [x + size, y + size], color, Math.max(1, size * 1000));
            if (delay > 0) await this._delay(delay);
            return result;
        },
        
        notify: function(type, message) {
            console.log(`[${type.toUpperCase()}] ${message}`);
            // You can extend this to show actual notifications
        },
        
        // Initialize drawing state
        _drawingActive: false,
        _globalFrameCount: 0,
        _pixelFont: {
            'V': [['###', '###', ' # ', ' # ', ' # ']],
            'S': [['###', '#  ', '###', '  #', '###']],
            'M': [['# #', '###', '# #', '# #', '# #']],
            // Add more characters as needed
        },
        _charHeight: 5,

        // Main animation functions
        async pixelArtCharacters() {
            if (!window.getGameSocket || !window.getGameSocket() || window.getGameSocket().readyState !== WebSocket.OPEN) {
                this.notify("error", "Not connected to game. Please be in a room.");
                return;
            }
            
            this._drawingActive = true;
            this.notify("info", "Starting Enhanced Pixel Art Characters...");

            const Q_TOP_LEFT = { xMin: 0.0, yMin: 0.0, xMax: 0.5, yMax: 0.5 };
            const Q_TOP_RIGHT = { xMin: 0.5, yMin: 0.0, xMax: 1.0, yMax: 0.5 };
            const Q_BOTTOM_LEFT = { xMin: 0.0, yMin: 0.5, xMax: 0.5, yMax: 1.0 };
            const Q_BOTTOM_RIGHT = { xMin: 0.5, yMin: 0.5, xMax: 1.0, yMax: 1.0 };

            const marioSprite = {
                name: "MARIO", nameColor: "#FF0000", width: 12,
                data: ["____RRRRR___", "___RRRRRRR__", "___NNNYNY___", "__NSSYSYYN__", "__NSSYSYYYNN", "__NYYYYYYYYN", "____BBBB____", "__RBBBRBBR__", "_RBBRRRBBRR_", "RBBBBBRBBBB_", "BBBBBBRBBBBB", "BBBB__BBBB__", "NNN____NNN__", "_NN____NN___"],
                colors: { R: "#E60000", N: "#7A3D03", Y: "#FBD000", S: "#FFCC99", B: "#0040FF" },
                quadrant: Q_TOP_LEFT, textOffsetY: -0.08
            };

            const characters = [marioSprite];
            const pixelDrawDelay = 3;

            try {
                for (const char of characters) {
                    if (!this._drawingActive) break;
                    
                    const charHeightPx = char.data.length;
                    const charWidthPx = char.width;
                    const quadW = char.quadrant.xMax - char.quadrant.xMin;
                    const quadH = char.quadrant.yMax - char.quadrant.yMin;

                    const scaleFactor = 0.65;
                    const pixelSizeX = (quadW * scaleFactor) / charWidthPx;
                    const pixelSizeY = (quadH * scaleFactor) / charHeightPx;
                    const finalPixelSize = Math.min(pixelSizeX, pixelSizeY);

                    const totalSpriteW = charWidthPx * finalPixelSize;
                    const totalSpriteH = charHeightPx * finalPixelSize;
                    const startX = char.quadrant.xMin + (quadW - totalSpriteW) / 2;
                    const startY = char.quadrant.yMin + (quadH - totalSpriteH) / 2;

                    for (let y = 0; y < charHeightPx; y++) {
                        if (!this._drawingActive) break;
                        for (let x = 0; x < charWidthPx; x++) {
                            if (!this._drawingActive) break;
                            const colorChar = char.data[y][x];
                            if (colorChar !== "_" && char.colors[colorChar]) {
                                const dX = startX + x * finalPixelSize;
                                const dY = startY + y * finalPixelSize;
                                if (!await this._drawPixel(dX, dY, finalPixelSize, char.colors[colorChar], pixelDrawDelay)) {
                                    this._drawingActive = false;
                                    break;
                                }
                            }
                        }
                    }
                    if (!this._drawingActive) break;
                    await this._delay(200);
                }
                
                this._drawingActive = false;
                this.notify("success", "Enhanced Pixel Art Characters finished.");
            } catch (error) {
                this._drawingActive = false;
                this.notify("error", "Animation failed: " + error.message);
            }
        },

        async colorFestival() {
            if (!window.getGameSocket || !window.getGameSocket() || window.getGameSocket().readyState !== WebSocket.OPEN) {
                this.notify("error", "Not connected to game. Please be in a room.");
                return;
            }
            
            this._drawingActive = true;
            this.notify("info", "Starting Color Festival...");
            
            try {
                const numShapes = 120;
                const frameDelay = 60;
                const shapeDelay = 10;
                
                for (let i = 0; i < numShapes && this._drawingActive; i++) {
                    let x = Math.random() * 0.8 + 0.1;
                    let y = Math.random() * 0.8 + 0.1;
                    let size = Math.random() * 0.08 + 0.03;
                    let color = this._getRandomColor(90, 55);
                    let thickness = Math.floor(Math.random() * 10) + 4;
                    let shapeType = Math.floor(Math.random() * 4);
                    
                    let success = true;
                    
                    if (shapeType === 0) {
                        // Rectangle
                        success = this._sendDrawCmd([x - size/2, y - size/2], [x + size/2, y - size/2], color, thickness) &&
                                 this._sendDrawCmd([x + size/2, y - size/2], [x + size/2, y + size/2], color, thickness) &&
                                 this._sendDrawCmd([x + size/2, y + size/2], [x - size/2, y + size/2], color, thickness) &&
                                 this._sendDrawCmd([x - size/2, y + size/2], [x - size/2, y - size/2], color, thickness);
                    } else if (shapeType === 1) {
                        // Triangle
                        success = this._sendDrawCmd([x, y - size/2], [x + size/2, y + size/2], color, thickness) &&
                                 this._sendDrawCmd([x + size/2, y + size/2], [x - size/2, y + size/2], color, thickness) &&
                                 this._sendDrawCmd([x - size/2, y + size/2], [x, y - size/2], color, thickness);
                    } else if (shapeType === 2) {
                        // Star pattern
                        for (let k = 0; k < 8 && success && this._drawingActive; k++) {
                            const angle = (k / 8) * 2 * Math.PI;
                            success = this._sendDrawCmd([x, y], [x + size * Math.cos(angle), y + size * Math.sin(angle)], color, thickness);
                            if (shapeDelay > 0 && success) await this._delay(shapeDelay);
                        }
                    } else {
                        // Spiral
                        let lastX = x, lastY = y;
                        for (let k = 0; k <= 20 && success && this._drawingActive; k++) {
                            const angle = (k / 20) * 4 * Math.PI;
                            const radius = (k / 20) * size;
                            const currentX = x + radius * Math.cos(angle);
                            const currentY = y + radius * Math.sin(angle);
                            if (k > 0) success = this._sendDrawCmd([lastX, lastY], [currentX, currentY], color, thickness);
                            lastX = currentX;
                            lastY = currentY;
                            if (shapeDelay > 0 && success) await this._delay(shapeDelay);
                        }
                    }
                    
                    if (!success || !this._drawingActive) break;
                    if (frameDelay > 0) await this._delay(frameDelay);
                }
                
                this._drawingActive = false;
                this.notify("success", "Color Festival finished.");
            } catch (error) {
                this._drawingActive = false;
                this.notify("error", "Animation failed: " + error.message);
            }
        },

        async fireworks() {
            if (!window.getGameSocket || !window.getGameSocket() || window.getGameSocket().readyState !== WebSocket.OPEN) {
                this.notify("error", "Not connected to game. Please be in a room.");
                return;
            }
            
            this._drawingActive = true;
            this.notify("info", "Starting Fireworks...");
            
            try {
                const numFireworks = 8;
                const fireworkDelay = 600;
                
                for (let i = 0; i < numFireworks && this._drawingActive; i++) {
                    // Launch trail
                    let startX = Math.random() * 0.6 + 0.2;
                    let startY = 0.95;
                    let peakX = startX + (Math.random() - 0.5) * 0.3;
                    let peakY = Math.random() * 0.4 + 0.05;
                    let launchColor = this._getRandomColor(100, 70);
                    
                    // Draw launch trail
                    for (let step = 0; step < 25 && this._drawingActive; step++) {
                        let progress = step / 25;
                        let nextProgress = (step + 1) / 25;
                        let currentX = startX + (peakX - startX) * progress;
                        let currentY = startY + (peakY - startY) * progress;
                        let nextX = startX + (peakX - startX) * nextProgress;
                        let nextY = startY + (peakY - startY) * nextProgress;
                        
                        if (!this._sendDrawCmd([currentX, currentY], [nextX, nextY], launchColor, 6)) {
                            this._drawingActive = false;
                            break;
                        }
                        await this._delay(4);
                    }
                    
                    if (!this._drawingActive) break;
                    
                    // Explosion
                    const explosionHue = Math.random() * 360;
                    const particleCount = 40 + Math.floor(Math.random() * 40);
                    
                    for (let j = 0; j < particleCount && this._drawingActive; j++) {
                        const angle = Math.random() * 2 * Math.PI;
                        const distance = Math.random() * 0.20 + 0.05;
                        const endX = peakX + distance * Math.cos(angle);
                        const endY = peakY + distance * Math.sin(angle);
                        
                        const particleHue = (explosionHue + (Math.random() - 0.5) * 60 + 360) % 360;
                        if (!this._sendDrawCmd([peakX, peakY], [endX, endY], `hsl(${particleHue},100%,60%)`, 4)) {
                            this._drawingActive = false;
                            break;
                        }
                        await this._delay(8);
                    }
                    
                    if (!this._drawingActive) break;
                    if (fireworkDelay > 0) await this._delay(fireworkDelay);
                }
                
                this._drawingActive = false;
                this.notify("success", "Fireworks finished.");
            } catch (error) {
                this._drawingActive = false;
                this.notify("error", "Animation failed: " + error.message);
            }
        },

        stopDrawing() {
            this._drawingActive = false;
            this.notify("info", "Drawing stopped by user.");
        }
    };

    // Utility functions for the library
    window.DRAWARIA_ANIMATIONS = {
        // Get all available animation functions
        getAnimations: function() {
            try {
                return Object.keys(DRAWING_FUNCTIONS).filter(key => 
                    typeof DRAWING_FUNCTIONS[key] === 'function' && 
                    !key.startsWith('_') && 
                    key !== 'notify' && 
                    key !== 'stopDrawing'
                );
            } catch (error) {
                console.error('Error getting animations:', error);
                return [];
            }
        },

        // Execute a specific animation
        runAnimation: function(animationName) {
            try {
                if (typeof DRAWING_FUNCTIONS[animationName] === 'function') {
                    return DRAWING_FUNCTIONS[animationName].call(DRAWING_FUNCTIONS);
                } else {
                    console.error('Animation not found:', animationName);
                    return Promise.reject('Animation not found');
                }
            } catch (error) {
                console.error('Error running animation:', error);
                return Promise.reject(error);
            }
        },

        // Get a random animation
        getRandomAnimation: function() {
            try {
                const animations = this.getAnimations();
                if (animations.length === 0) return null;
                return animations[Math.floor(Math.random() * animations.length)];
            } catch (error) {
                console.error('Error getting random animation:', error);
                return null;
            }
        },

        // Stop current animation
        stop: function() {
            try {
                DRAWING_FUNCTIONS.stopDrawing();
            } catch (error) {
                console.error('Error stopping animation:', error);
            }
        },

        // Check if drawing is active
        isDrawing: function() {
            return DRAWING_FUNCTIONS._drawingActive;
        },

        // Direct access to drawing functions
        animations: DRAWING_FUNCTIONS
    };

    // Make drawing functions available globally
    window.DRAWING_FUNCTIONS = DRAWING_FUNCTIONS;
    
    console.log('🎨 Drawaria Animation Library loaded with', 
                Object.keys(DRAWING_FUNCTIONS).filter(k => typeof DRAWING_FUNCTIONS[k] === 'function').length, 
                'functions');
    console.log('Available animations:', window.DRAWARIA_ANIMATIONS.getAnimations());

})();