Drawaria Physics Engine Basketball🏀

Advanced physics-based basketball engine with professional NBA court and possession system!

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Drawaria Physics Engine Basketball🏀
// @namespace    http://tampermonkey.net/
// @version      6.1.0
// @description  Advanced physics-based basketball engine with professional NBA court and possession system!
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    /* ---------- SHARED SYSTEM COMPONENTS ---------- */
    let drawariaSocket = null;
    let drawariaCanvas = null;
    let drawariaCtx = null;

    // Optimized command queue
    const commandQueue = [];
    let batchProcessor = null;
    const BATCH_SIZE = 12;
    const BATCH_INTERVAL = 45;

    const positionCache = new Map();
    const MOVEMENT_THRESHOLD = 3;

    // Basketball-specific constants
    const PHYSICS_CONSTANTS = {
        GRAVITY: 400,
        BALL_MASS: 0.2,
        BALL_RADIUS: 25,
        TIMESTEP: 1/60,
        MAX_VELOCITY: 600,
        AIR_RESISTANCE: 0.005,
        RESTITUTION_BALL: 0.85,
        RESTITUTION_WALL: 0.7,
        FRICTION_COURT: 0.75,
        PLAYER_INTERACTION_FORCE: 250,
        PLAYER_PUSH_MULTIPLIER: 1.8,
        PLAYER_RESTITUTION: 0.9,
        PLAYER_DETECTION_INTERVAL: 1000 / 60,
        PLAYER_DETECTION_RADIUS_MULTIPLIER: 2.0,
        DRIBBLE_FORCE: 150,
        POSSESSION_DISTANCE: 80,
        BALL_COLOR: '#FF8C00',
        STEAL_COOLDOWN: 1000,
    };

    // Professional NBA Court Constants (from first script)
    const NBA_COURT_CONSTANTS = {
        COURT_COLOR: '#D2691E',      // Madera de cancha
        LINE_COLOR: '#FF4555',       // Líneas blancas oficiales
        RIM_COLOR: '#787878',        // Aros grises metálicos
        BACKBOARD_COLOR: '#787878',  // Tableros blancos
        KEY_COLOR: '#FF4500',        // Área restringida naranja
        TEXT_COLOR: '#000000',       // Texto negro
        POLE_COLOR: '#696969',       // Postes grises
        NET_COLOR: '#787878',        // Red blanca
        RIM_THICKNESS: 8,
        LINE_THICKNESS_MULTIPLIER: 0.008
    };

    const MATCH_CONSTANTS = {
        MAX_BASKETS: 5,
        PLAY_AREA_REDUCTION: {
            SIDES: 0.1,
            TOP: 0.4
        }
    };

    // WebSocket interception
    const originalWebSocketSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function (...args) {
        if (!drawariaSocket && this.url && this.url.includes('drawaria')) {
            drawariaSocket = this;
            console.log('🔗 Drawaria WebSocket captured for basketball engine.');
            startBatchProcessor();
        }
        return originalWebSocketSend.apply(this, args);
    };

    function startBatchProcessor() {
        if (batchProcessor) return;
        batchProcessor = setInterval(() => {
            if (!drawariaSocket || drawariaSocket.readyState !== WebSocket.OPEN || commandQueue.length === 0) {
                return;
            }
            const batch = commandQueue.splice(0, BATCH_SIZE);
            batch.forEach(cmd => {
                try { drawariaSocket.send(cmd); } catch (e) { console.warn('Failed to send command:', e); }
            });
        }, BATCH_INTERVAL);
    }

    function enqueueDrawCommand(x1, y1, x2, y2, color, thickness) {
        if (!drawariaCanvas || !drawariaSocket) return;

        const normX1 = (x1 / drawariaCanvas.width).toFixed(4);
        const normY1 = (y1 / drawariaCanvas.height).toFixed(4);
        const normX2 = (x2 / drawariaCanvas.width).toFixed(4);
        const normY2 = (y2 / drawariaCanvas.height).toFixed(4);

        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-Math.abs(thickness)},"${color}",0,0,{}]]`;
        commandQueue.push(cmd);

        if (drawariaCtx) {
            drawariaCtx.strokeStyle = color;
            drawariaCtx.lineWidth = thickness;
            drawariaCtx.lineCap = 'round';
            drawariaCtx.lineJoin = 'round';
            drawariaCtx.beginPath();
            drawariaCtx.moveTo(x1, y1);
            drawariaCtx.lineTo(x2, y2);
            drawariaCtx.stroke();
        }
    }

    // Helper functions
    function clamp(value, min, max) { return Math.min(Math.max(value, min), max); }
    function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }

    /* ---------- ADVANCED BASKETBALL PHYSICS ENGINE ---------- */
    class AdvancedDrawariaBasketball {
        constructor() {
            this.initialized = false;
            this.isActive = false;
            this.physicsObjects = new Map();
            this.objectIdCounter = 0;
            this.lastRenderTime = 0;
            this.renderInterval = 1000 / 30;

            // Sistema de posesión de baloncesto
            this.possessionSystem = {
                ballOwner: null,
                lastStealTime: 0,
                dribbleInterval: null,
                possessionDistance: PHYSICS_CONSTANTS.POSSESSION_DISTANCE
            };

            // Match mode system
            this.matchMode = {
                active: false,
                scores: { p1: 0, p2: 0 },
                playArea: null,
                lastScorePositions: { p1: null, p2: null },
                goalCooldown: false
            };

            this.gameStats = {
                totalCollisions: 0,
                maxVelocityReached: 0,
                objectsCreated: 0,
                totalBaskets: 0
            };

            this.controls = {
                showTrails: false,
                showDebug: false,
                rainbowModeActive: false,
                defaultObjectColor: PHYSICS_CONSTANTS.BALL_COLOR,
                alternatePhysics: 'normal'
            };

            this.rainbowHue = 0;
            this.rainbowInterval = null;

            this.playerTracker = {
                players: new Map(),
                detectionRadius: PHYSICS_CONSTANTS.BALL_RADIUS * PHYSICS_CONSTANTS.PLAYER_DETECTION_RADIUS_MULTIPLIER,
                lastUpdateTime: 0
            };

            this.fieldDrawing = { isDrawing: false, isStopped: false };

            this.init();
        }

        init() {
            if (this.initialized) return;

            const checkGameReady = () => {
                const gameCanvas = document.getElementById('canvas');
                if (gameCanvas) {
                    this.canvasElement = gameCanvas;
                    drawariaCanvas = gameCanvas;
                    this.canvasContext = gameCanvas.getContext('2d');
                    drawariaCtx = gameCanvas.getContext('2d');

                    this.initialized = true;
                    this.createAdvancedPanel();
                    console.log('✅ Advanced Basketball Physics Engine v6.1 initialized with Professional NBA Court');
                } else {
                    setTimeout(checkGameReady, 100);
                }
            };
            checkGameReady();
        }

        createAdvancedPanel() {
            const existingPanel = document.getElementById('advanced-physics-panel');
            if (existingPanel) existingPanel.remove();

            const panel = document.createElement('div');
            panel.id = 'advanced-physics-panel';
            panel.style.cssText = `
                position: fixed !important;
                top: 20px !important;
                right: 20px !important;
                width: 380px !important;
                z-index: 2147483647 !important;
                background: linear-gradient(135deg, #0f0f23, #1a1a3a) !important;
                border: 2px solid #FF8C00 !important;
                border-radius: 15px !important;
                color: white !important;
                font-family: 'Segoe UI', Arial, sans-serif !important;
                overflow: hidden !important;
                box-shadow: 0 0 30px rgba(255,140,0,0.4) !important;
            `;

            // Header draggable
            const header = document.createElement('div');
            header.id = 'panel-header';
            header.style.cssText = `
                background: linear-gradient(45deg, #FF8C00, #FF6347) !important;
                padding: 12px 20px !important;
                font-weight: bold !important;
                text-align: center !important;
                font-size: 14px !important;
                cursor: move !important;
                user-select: none !important;
                display: flex !important;
                justify-content: space-between !important;
                align-items: center !important;
            `;

            const title = document.createElement('div');
            title.innerHTML = '🏀 NBA BASKETBALL ENGINE v6.1';
            title.style.flex = '1';

            const buttonContainer = document.createElement('div');
            buttonContainer.style.cssText = `display: flex !important; gap: 8px !important;`;

            // Botón minimizar
            const minimizeBtn = document.createElement('button');
            minimizeBtn.id = 'minimize-btn';
            minimizeBtn.innerHTML = '−';
            minimizeBtn.style.cssText = `
                width: 25px !important; height: 25px !important;
                background: rgba(255,255,255,0.2) !important;
                border: none !important; border-radius: 4px !important;
                color: white !important; cursor: pointer !important;
                font-size: 16px !important; line-height: 1 !important; padding: 0 !important;
            `;

            // Botón cerrar
            const closeBtn = document.createElement('button');
            closeBtn.id = 'close-btn';
            closeBtn.innerHTML = '×';
            closeBtn.style.cssText = `
                width: 25px !important; height: 25px !important;
                background: rgba(255,0,0,0.6) !important;
                border: none !important; border-radius: 4px !important;
                color: white !important; cursor: pointer !important;
                font-size: 18px !important; line-height: 1 !important; padding: 0 !important;
            `;

            buttonContainer.appendChild(minimizeBtn);
            buttonContainer.appendChild(closeBtn);
            header.appendChild(title);
            header.appendChild(buttonContainer);

            // Contenido del panel
            const content = document.createElement('div');
            content.id = 'panel-content';
            content.style.cssText = `padding: 20px !important;`;
            content.innerHTML = `
                <!-- CREATE PROFESSIONAL NBA COURT BUTTON -->
                <div style="margin-bottom: 15px; text-align: center;">
                    <button id="create-court-btn" style="
                        width: 100%;
                        padding: 12px;
                        background: linear-gradient(135deg, ${NBA_COURT_CONSTANTS.COURT_COLOR}, #CD853F);
                        color: white;
                        border: none;
                        border-radius: 8px;
                        cursor: pointer;
                        font-size: 14px;
                        font-weight: bold;
                        margin-bottom: 10px;
                    ">🏀 Create Professional NBA Court</button>
                </div>

                <!-- LAUNCH PHYSICS BUTTON -->
                <div style="margin-bottom: 15px; text-align: center;">
                    <button id="toggle-physics" style="
                        width: 100%;
                        padding: 12px;
                        background: linear-gradient(135deg, #FF8C00, #FF6347);
                        color: white;
                        border: none;
                        border-radius: 8px;
                        cursor: pointer;
                        font-size: 14px;
                        font-weight: bold;
                    ">🚀 Launch Basketball Engine</button>
                </div>

                <!-- OBJECT CREATION BUTTONS -->
                <div style="display: flex; gap: 10px; margin-bottom: 15px;">
                    <button id="add-basketball-btn" style="
                        flex: 1;
                        padding: 8px;
                        background: linear-gradient(135deg, #FF8C00, #FF6347);
                        color: white;
                        border: none;
                        border-radius: 6px;
                        cursor: pointer;
                        font-size: 12px;
                        font-weight: bold;
                    ">🏀 Basketball</button>
                </div>

                <!-- ACTION BUTTONS -->
                <div style="display: flex; gap: 8px; margin-bottom: 15px;">
                    <button id="reset-all-btn" style="
                        flex: 1;
                        padding: 8px;
                        background: linear-gradient(135deg, #74b9ff, #0984e3);
                        color: white;
                        border: none;
                        border-radius: 6px;
                        cursor: pointer;
                        font-weight: bold;
                        font-size: 11px;
                    ">🔄 Reset</button>
                </div>

                <!-- ADVANCED MODES -->
                <div style="margin-bottom: 15px;">
                    <h4 style="margin: 0 0 10px 0; font-size: 13px; color: #FF8C00; text-align: center;">🌟 Basketball Modes</h4>
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
                        <button id="match-mode-toggle" class="mode-toggle" style="
                            padding: 8px;
                            background: linear-gradient(135deg, #444, #666);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-size: 10px;
                            font-weight: bold;
                        ">🏆 Match Mode</button>
                        <button id="clean-canvas-btn" style="
                            padding: 8px;
                            background: linear-gradient(135deg, #e17055, #d63031);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-size: 10px;
                            font-weight: bold;
                        ">🧹 Clean Canvas</button>
                    </div>
                </div>

                <!-- PHYSICS SELECTION -->
                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-size: 12px; color: #FF8C00;">
                        🔬 Physics Mode:
                    </label>
                    <select id="physics-mode" style="
                        width: 100%;
                        padding: 8px;
                        border: 1px solid #FF8C00;
                        border-radius: 6px;
                        background: #1a1a3a;
                        color: white;
                        font-size: 12px;
                    ">
                        <option value="normal">🏀 Normal</option>
                        <option value="moon">🌙 Moon Gravity</option>
                        <option value="underwater">🌊 Underwater</option>
                        <option value="magnetic">🧲 Magnetic Court</option>
                    </select>
                </div>

                <!-- CLEAR ALL -->
                <div style="margin-bottom: 15px;">
                    <button id="clear-all-btn" style="
                        width: 100%;
                        padding: 10px;
                        background: linear-gradient(135deg, #990000, #cc0000);
                        color: white;
                        border: none;
                        border-radius: 8px;
                        cursor: pointer;
                        font-weight: bold;
                    ">🗑️ Clear All Basketballs</button>
                </div>

                <!-- MATCH MODE SCOREBOARD -->
                <div id="match-scoreboard" style="
                    display: none;
                    background: rgba(0,0,0,0.4);
                    padding: 15px;
                    border-radius: 8px;
                    text-align: center;
                    margin-bottom: 15px;
                    border: 2px solid #ffd700;
                ">
                    <h4 style="margin: 0 0 10px 0; color: #ffd700; font-size: 14px;">🏀 NBA SCORE</h4>
                    <div style="display: flex; justify-content: space-between; font-size: 18px; font-weight: bold;">
                        <span>P1: <span id="score-p1" style="color: #ff6b6b;">0</span></span>
                        <span style="color: #666;">vs</span>
                        <span>P2: <span id="score-p2" style="color: #74b9ff;">0</span></span>
                    </div>
                </div>

                <!-- NBA COURT SPECS -->
                <div style="
                    background: rgba(210,105,30,0.2);
                    padding: 10px;
                    border-radius: 6px;
                    font-size: 10px;
                    margin-bottom: 15px;
                    border: 1px solid ${NBA_COURT_CONSTANTS.COURT_COLOR};
                ">
                    <div style="color: #FF8C00; font-weight: bold; margin-bottom: 8px; text-align: center;">🏀 NBA COURT SPECS</div>
                    <div style="line-height: 1.4; color: #FFE6D1;">
                        ✅ Official court dimensions<br>
                        🏀 3-point lines & free throw areas<br>
                        ⚪ Center circle & court lines<br>
                        🗼 Support poles with nets<br>
                        🏟️ Hardwood parquet floor
                    </div>
                </div>

                <!-- STATS -->
                <div id="stats" style="
                    background: rgba(0,0,0,0.3);
                    padding: 10px;
                    border-radius: 6px;
                    font-size: 10px;
                    text-align: center;
                    border: 1px solid rgba(255,140,0,0.3);
                ">
                    <div>Basketballs: <span id="object-count">0</span> | Baskets: <span id="goals-count">0</span></div>
                    <div>Collisions: <span id="collision-count">0</span> | Max Speed: <span id="max-speed">0</span></div>
                    <div>Queue: <span id="queue-count">0</span> | Performance: <span id="performance">Optimal</span></div>
                </div>

                <!-- HELP TEXT -->
                <div style="
                    text-align: center;
                    margin-top: 15px;
                    font-size: 9px;
                    color: rgba(255,255,255,0.6);
                    border-top: 1px solid rgba(255,255,255,0.1);
                    padding-top: 10px;
                ">
                    Professional NBA court with physics<br>
                    <span style="color: #FF8C00;">Possession system & official dimensions</span>
                </div>
            `;

            panel.appendChild(header);
            panel.appendChild(content);
            document.body.appendChild(panel);

            this.makePanelDraggable();
            this.setupPanelButtons();
            this.setupAdvancedEventListeners();
            this.startAdvancedStatsMonitoring();
        }

        setupAdvancedEventListeners() {
            // Court and physics controls
            document.getElementById('create-court-btn')?.addEventListener('click', () => this.createProfessionalNBACourt());
            document.getElementById('toggle-physics')?.addEventListener('click', () => this.togglePhysics());

            // Object creation
            document.getElementById('add-basketball-btn')?.addEventListener('click', () => this.addRandomBasketball());

            // Actions
            document.getElementById('reset-all-btn')?.addEventListener('click', () => this.resetAllObjects());
            document.getElementById('clear-all-btn')?.addEventListener('click', () => this.clearAllObjects());

            // Advanced controls
            document.getElementById('match-mode-toggle')?.addEventListener('click', () => this.toggleMatchMode());
            document.getElementById('clean-canvas-btn')?.addEventListener('click', () => this.cleanCanvas());

            // Physics mode selection
            document.getElementById('physics-mode')?.addEventListener('change', (e) => {
                this.controls.alternatePhysics = e.target.value;
                this.showFeedback(`🔬 Physics Mode: ${e.target.options[e.target.selectedIndex].text}`, '#FF8C00');
            });

            // Canvas click for basketball creation
            if (this.canvasElement) {
                this.canvasElement.addEventListener('click', (e) => this.createBasketball(e.clientX - this.canvasElement.getBoundingClientRect().left, e.clientY - this.canvasElement.getBoundingClientRect().top));
            }
        }

        /* ---------- NBA PIXEL TEXT DRAWING (CORREGIDO) ---------- */
        NBA_PIXEL_LETTERS = {
            'B': [[1,1,1,1],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,1,1,1]],
            'A': [[0,1,1,0],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,0,0,1]],
            'S': [[1,1,1,1],[1,0,0,0],[1,1,1,1],[0,0,0,1],[1,1,1,1]],
            'K': [[1,0,0,1],[1,0,1,0],[1,1,0,0],[1,0,1,0],[1,0,0,1]],
            'E': [[1,1,1,1],[1,0,0,0],[1,1,1,0],[1,0,0,0],[1,1,1,1]],
            'T': [[1,1,1,1,1],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0]],
            'L': [[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,1,1,1]],
            'O': [[1,1,1,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,1,1]],
            'P': [[1,1,1,1],[1,0,0,1],[1,1,1,1],[1,0,0,0],[1,0,0,0]]
        };

        NUMBER_PATTERNS = {
            0: [[1,1,1],[1,0,1],[1,0,1],[1,0,1],[1,1,1]],
            1: [[0,1,0],[1,1,0],[0,1,0],[0,1,0],[1,1,1]],
            2: [[1,1,1],[0,0,1],[1,1,1],[1,0,0],[1,1,1]],
            3: [[1,1,1],[0,0,1],[1,1,1],[0,0,1],[1,1,1]],
            4: [[1,0,1],[1,0,1],[1,1,1],[0,0,1],[0,0,1]],
            5: [[1,1,1],[1,0,0],[1,1,1],[0,0,1],[1,1,1]]
        };

        // FUNCIÓN PRINCIPAL PARA DIBUJAR "BASKETBALL" (CORREGIDA)
        async drawNBAMainText(text, coords) {
            if (this.fieldDrawing.isStopped) return;

            const letterSpacing = coords.text.pixelSize * 7;
            const textWidth = text.length * letterSpacing;
            let currentX = coords.text.x - (textWidth / 2);

            for (let i = 0; i < text.length; i++) {
                if (this.fieldDrawing.isStopped) break;
                const letter = text[i].toUpperCase();
                if (letter === ' ') {
                    currentX += letterSpacing;
                    continue;
                }
                const pattern = this.NBA_PIXEL_LETTERS[letter];
                if (!pattern) continue;

                for (let row = 0; row < pattern.length; row++) {
                    for (let col = 0; col < pattern[row].length; col++) {
                        if (pattern[row][col] === 1) {
                            const pixelX = currentX + (col * coords.text.pixelSize);
                            const pixelY = coords.text.y + (row * coords.text.pixelSize);
                            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
                            if (pixelX >= 0 && pixelX < canvasSize.width && pixelY >= 0 && pixelY < canvasSize.height) {
                                await this.drawNBAPixel(pixelX, pixelY, NBA_COURT_CONSTANTS.TEXT_COLOR, coords.text.pixelSize);
                            }
                        }
                    }
                }
                currentX += letterSpacing;
                await sleep(120);
            }
        }

        // FUNCIÓN PARA TEXTOS PEQUEÑOS (SCOREBOARDS)
        async drawNBASmallText(text, x, y, color, pixelSize) {
            let currentX = x;
            for (let i = 0; i < text.length; i++) {
                const letter = text[i];
                const pattern = this.NBA_PIXEL_LETTERS[letter];
                if (pattern) {
                    for (let row = 0; row < pattern.length; row++) {
                        for (let col = 0; col < pattern[row].length; col++) {
                            if (pattern[row][col] === 1) {
                                const pixelX = currentX + (col * pixelSize);
                                const pixelY = y + (row * pixelSize);
                                await this.drawNBAPixel(pixelX, pixelY, color, pixelSize);
                            }
                        }
                    }
                }
                currentX += pixelSize * 4;
            }
        }

        // FUNCIÓN PARA NÚMEROS
        async drawPixelNumber(number, x, y, color, pixelSize) {
            const pattern = this.NUMBER_PATTERNS[number];
            if (!pattern) return;

            for (let row = 0; row < pattern.length; row++) {
                for (let col = 0; col < pattern[row].length; col++) {
                    if (pattern[row][col] === 1) {
                        const pixelX = x + (col * pixelSize);
                        const pixelY = y + (row * pixelSize);
                        await this.drawNBAPixel(pixelX, pixelY, color, pixelSize);
                    }
                }
            }
        }

        async drawNBAPixel(x, y, color, size = 2) {
            if (this.fieldDrawing.isStopped) return;
            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
            x = clamp(x, 0, canvasSize.width - size);
            y = clamp(y, 0, canvasSize.height - size);
            enqueueDrawCommand(x, y, x + 1, y + 1, color, size);
            await sleep(20);
        }


        /* ---------- PROFESSIONAL NBA COURT CREATION (from first script) ---------- */
        calculateProfessionalBasketballCoordinates() {
            const size = { width: drawariaCanvas.width, height: drawariaCanvas.height };
            return {
                // Aros de baloncesto con dimensiones profesionales
                leftBasket: {
                    x: Math.floor(size.width * 0.08),
                    y: Math.floor(size.height * 0.25),
                    rimWidth: Math.floor(size.width * 0.06),
                    rimHeight: Math.floor(size.height * 0.04),
                    backboardWidth: Math.floor(size.width * 0.1),
                    backboardHeight: Math.floor(size.height * 0.12)
                },
                rightBasket: {
                    x: Math.floor(size.width * 0.92),
                    y: Math.floor(size.height * 0.25),
                    rimWidth: Math.floor(size.width * 0.06),
                    rimHeight: Math.floor(size.height * 0.04),
                    backboardWidth: Math.floor(size.width * 0.1),
                    backboardHeight: Math.floor(size.height * 0.12)
                },
                // Líneas de la cancha
                centerLine: {
                    x: Math.floor(size.width * 0.5),
                    y1: Math.floor(size.height * 0.05),
                    y2: Math.floor(size.height * 0.95)
                },
                // Círculo central
                centerCircle: {
                    x: Math.floor(size.width * 0.5),
                    y: Math.floor(size.height * 0.5),
                    radius: Math.floor(size.width * 0.08)
                },
                // Líneas de tres puntos
                threePointLine: {
                    leftArc: {
                        centerX: Math.floor(size.width * 0.08),
                        centerY: Math.floor(size.height * 0.5),
                        radius: Math.floor(size.width * 0.18)
                    },
                    rightArc: {
                        centerX: Math.floor(size.width * 0.92),
                        centerY: Math.floor(size.height * 0.5),
                        radius: Math.floor(size.width * 0.18)
                    }
                },
                // Área restringida (key/paint)
                leftKey: {
                    x: Math.floor(size.width * 0.02),
                    y: Math.floor(size.height * 0.35),
                    width: Math.floor(size.width * 0.18),
                    height: Math.floor(size.height * 0.3)
                },
                rightKey: {
                    x: Math.floor(size.width * 0.8),
                    y: Math.floor(size.height * 0.35),
                    width: Math.floor(size.width * 0.18),
                    height: Math.floor(size.height * 0.3)
                },
                // Texto centrado
                text: {
                    x: Math.floor(size.width * 0.5),
                    y: Math.floor(size.height * 0.08),
                    pixelSize: Math.max(3, Math.floor(size.width * 0.006)) // Aumenté el tamaño mínimo
                }

            };
        }

        async createProfessionalNBACourt() {
            if (this.fieldDrawing.isDrawing) {
                this.showFeedback('⚠️ NBA Court creation already in progress!', '#ed8936');
                return;
            }
            if (!drawariaSocket || !drawariaCanvas || !drawariaCtx) {
                this.showFeedback('❌ Canvas or WebSocket connection not detected!', '#f56565');
                return;
            }

            this.fieldDrawing.isDrawing = true;
            this.fieldDrawing.isStopped = false;

            try {
                const coords = this.calculateProfessionalBasketballCoordinates();
                const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };

                this.showFeedback(`🏀 Creating Professional NBA Court: ${canvasSize.width}x${canvasSize.height}`, NBA_COURT_CONSTANTS.COURT_COLOR);
                await sleep(800);

                // === 1. PISO DE PARQUET ===
                this.showFeedback("🏀 PHASE 1: Hardwood parquet floor...", NBA_COURT_CONSTANTS.COURT_COLOR);
                await this.drawProfessionalBasketballFloor();
                await sleep(300);
                if (this.fieldDrawing.isStopped) return;

                // === 2. LÍNEAS OFICIALES ===
                this.showFeedback("⚪ PHASE 2: Official NBA court lines...", NBA_COURT_CONSTANTS.LINE_COLOR);
                await this.drawProfessionalCourtLines(coords);
                await sleep(300);
                if (this.fieldDrawing.isStopped) return;

                // === 3. AROS PROFESIONALES ===
                this.showFeedback("🏀 PHASE 3: Installing left NBA rim...", NBA_COURT_CONSTANTS.RIM_COLOR);
                await this.drawProfessionalBasketballRim(coords.leftBasket, 'left');
                this.showFeedback("🏀 PHASE 3: Installing right NBA rim...", NBA_COURT_CONSTANTS.RIM_COLOR);
                await this.drawProfessionalBasketballRim(coords.rightBasket, 'right');
                await sleep(300);
                if (this.fieldDrawing.isStopped) return;

                // === 4. TEXTO "BASKETBALL" ===
                this.showFeedback("🎮 PHASE 4: Drawing 'BASKETBALL' text...", NBA_COURT_CONSTANTS.TEXT_COLOR);
                await this.drawNBAMainText("BASKETBALL", coords);

                // === CANCHA COMPLETA ===
                this.showFeedback("🏆 PROFESSIONAL NBA COURT COMPLETE! 🏀🎯", "#006400");
                setTimeout(() => {
                    const statusDiv = document.querySelector('.feedback-div');
                    if (statusDiv) {
                        statusDiv.style.opacity = 0;
                        setTimeout(() => statusDiv.remove(), 500);
                    }
                }, 4000);

                // Si match mode está activo, configurar área de juego
                if (this.matchMode.active) {
                    this.setupReducedPlayArea();
                    await this.drawNBAScoreboards(coords);
                }

            } catch (error) {
                console.error("Error creating NBA court:", error);
                this.showFeedback(`❌ Error: ${error.message}`, "#B22222");
            } finally {
                this.fieldDrawing.isDrawing = false;
            }
        }

        // Piso de parquet profesional
        async drawProfessionalBasketballFloor() {
            if (this.fieldDrawing.isStopped) return;
            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };

            // Base de madera
            await this.drawLineLocalAndServer(0, canvasSize.height - 5, canvasSize.width, canvasSize.height - 5, NBA_COURT_CONSTANTS.COURT_COLOR, 8, 40);

            // Líneas de madera horizontales para simular tablones
            for (let y = 25; y < canvasSize.height - 10; y += 30) {
                await this.drawLineLocalAndServer(0, y, canvasSize.width, y, '#8B4513', 1, 20);
                if (this.fieldDrawing.isStopped) break;
            }
        }

        // Líneas oficiales de cancha NBA
        async drawProfessionalCourtLines(coords) {
            if (this.fieldDrawing.isStopped) return;
            const lineThickness = Math.max(4, Math.floor(drawariaCanvas.width * NBA_COURT_CONSTANTS.LINE_THICKNESS_MULTIPLIER));

            // Línea central
            await this.drawLineLocalAndServer(
                coords.centerLine.x, coords.centerLine.y1,
                coords.centerLine.x, coords.centerLine.y2,
                NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, 80
            );

            // Bordes de la cancha
            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
            await this.drawLineLocalAndServer(0, 0, canvasSize.width, 0, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, 60);
            await this.drawLineLocalAndServer(canvasSize.width, 0, canvasSize.width, canvasSize.height, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, 60);
            await this.drawLineLocalAndServer(canvasSize.width, canvasSize.height, 0, canvasSize.height, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, 60);
            await this.drawLineLocalAndServer(0, canvasSize.height, 0, 0, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, 60);

            // Círculo central
            await this.drawProfessionalCircle(
                coords.centerCircle.x,
                coords.centerCircle.y,
                coords.centerCircle.radius,
                NBA_COURT_CONSTANTS.LINE_COLOR,
                lineThickness
            );

            // Áreas restringidas
            await this.drawProfessionalRectangleOutline(coords.leftKey, NBA_COURT_CONSTANTS.KEY_COLOR, lineThickness);
            await this.drawProfessionalRectangleOutline(coords.rightKey, NBA_COURT_CONSTANTS.KEY_COLOR, lineThickness);

            // Líneas de tres puntos
            await this.drawProfessionalArc(coords.threePointLine.leftArc, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, Math.PI/4, 3*Math.PI/4);
            await this.drawProfessionalArc(coords.threePointLine.rightArc, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness, Math.PI/4, 3*Math.PI/4);

            // Líneas de tiro libre
            await this.drawProfessionalFreeThrowLines(coords, NBA_COURT_CONSTANTS.LINE_COLOR, lineThickness);
        }

        // Aros NBA con postes de soporte profesionales
        async drawProfessionalBasketballRim(basketCoords, side = 'left') {
            if (this.fieldDrawing.isStopped) return;

            // Tablero rectangular
            const boardX = basketCoords.x - basketCoords.backboardWidth/2;
            const boardY = basketCoords.y - basketCoords.backboardHeight/2;

            await this.drawProfessionalRectangleOutline({
                x: boardX,
                y: boardY,
                width: basketCoords.backboardWidth,
                height: basketCoords.backboardHeight
            }, NBA_COURT_CONSTANTS.BACKBOARD_COLOR, 5);

            // Relleno del tablero (líneas horizontales)
            for (let y = boardY + 5; y < boardY + basketCoords.backboardHeight - 5; y += 3) {
                await this.drawLineLocalAndServer(boardX + 5, y, boardX + basketCoords.backboardWidth - 5, y, NBA_COURT_CONSTANTS.BACKBOARD_COLOR, 1, 20);
                if (this.fieldDrawing.isStopped) break;
            }

            // === POSTE DE SOPORTE PROFESIONAL ===
            const poleWidth = Math.floor(basketCoords.backboardWidth * 0.15);
            const poleHeight = Math.floor(drawariaCanvas.height * 0.15);
            const poleX = basketCoords.x - poleWidth/2;
            const poleY = boardY + basketCoords.backboardHeight;

            this.showFeedback(`🏗️ Installing ${side} NBA support pole...`, NBA_COURT_CONSTANTS.POLE_COLOR);

            // Dibujar poste vertical
            await this.drawProfessionalRectangleOutline({
                x: poleX,
                y: poleY,
                width: poleWidth,
                height: poleHeight
            }, NBA_COURT_CONSTANTS.POLE_COLOR, 4);

            // Rellenar el poste con líneas verticales para textura metálica
            for (let x = poleX + 2; x < poleX + poleWidth - 2; x += 3) {
                await this.drawLineLocalAndServer(x, poleY + 2, x, poleY + poleHeight - 2, '#808080', 1, 15);
                if (this.fieldDrawing.isStopped) break;
            }

            // Aro circular NBA
            const rimY = basketCoords.y + basketCoords.backboardHeight/3;
            await this.drawProfessionalCircle(
                basketCoords.x,
                rimY,
                basketCoords.rimWidth/2,
                NBA_COURT_CONSTANTS.RIM_COLOR,
                6
            );

            // Red del aro (líneas colgantes)
            const netLines = 8; // Más líneas para red más realista
            for (let i = 0; i < netLines; i++) {
                const angle = (Math.PI * 2 * i) / netLines;
                const startX = basketCoords.x + Math.cos(angle) * (basketCoords.rimWidth/2);
                const startY = rimY;
                const endX = startX + Math.cos(angle) * 8;
                const endY = startY + 20;

                await this.drawLineLocalAndServer(startX, startY, endX, endY, NBA_COURT_CONSTANTS.NET_COLOR, 2, 35);
                if (this.fieldDrawing.isStopped) break;
            }
        }

        // === FUNCIONES AUXILIARES GEOMÉTRICAS PROFESIONALES ===
        async drawProfessionalCircle(centerX, centerY, radius, color, thickness) {
            const steps = 24;
            for (let i = 0; i <= steps; i++) {
                if (this.fieldDrawing.isStopped) break;
                const angle1 = (Math.PI * 2 * i) / steps;
                const angle2 = (Math.PI * 2 * (i + 1)) / steps;
                const x1 = centerX + Math.cos(angle1) * radius;
                const y1 = centerY + Math.sin(angle1) * radius;
                const x2 = centerX + Math.cos(angle2) * radius;
                const y2 = centerY + Math.sin(angle2) * radius;
                await this.drawLineLocalAndServer(x1, y1, x2, y2, color, thickness, 30);
            }
        }

        async drawProfessionalArc(arcCoords, color, thickness, startAngle = 0, endAngle = Math.PI) {
            const steps = 16;
            for (let i = 0; i < steps; i++) {
                if (this.fieldDrawing.isStopped) break;
                const progress1 = i / steps;
                const progress2 = (i + 1) / steps;
                const angle1 = startAngle + (endAngle - startAngle) * progress1;
                const angle2 = startAngle + (endAngle - startAngle) * progress2;
                const x1 = arcCoords.centerX + Math.cos(angle1) * arcCoords.radius;
                const y1 = arcCoords.centerY + Math.sin(angle1) * arcCoords.radius;
                const x2 = arcCoords.centerX + Math.cos(angle2) * arcCoords.radius;
                const y2 = arcCoords.centerY + Math.sin(angle2) * arcCoords.radius;
                await this.drawLineLocalAndServer(x1, y1, x2, y2, color, thickness, 40);
            }
        }

        async drawProfessionalRectangleOutline(rectCoords, color, thickness) {
            await this.drawLineLocalAndServer(rectCoords.x, rectCoords.y,
                rectCoords.x + rectCoords.width, rectCoords.y, color, thickness, 50);
            await this.drawLineLocalAndServer(rectCoords.x + rectCoords.width, rectCoords.y,
                rectCoords.x + rectCoords.width, rectCoords.y + rectCoords.height, color, thickness, 50);
            await this.drawLineLocalAndServer(rectCoords.x + rectCoords.width, rectCoords.y + rectCoords.height,
                rectCoords.x, rectCoords.y + rectCoords.height, color, thickness, 50);
            await this.drawLineLocalAndServer(rectCoords.x, rectCoords.y + rectCoords.height,
                rectCoords.x, rectCoords.y, color, thickness, 50);
        }

        async drawProfessionalFreeThrowLines(coords, color, thickness) {
            // Línea de tiro libre izquierda
            const freeThrowX = coords.leftKey.x + coords.leftKey.width;
            await this.drawLineLocalAndServer(
                freeThrowX, coords.leftKey.y,
                freeThrowX, coords.leftKey.y + coords.leftKey.height,
                color, thickness, 60
            );
            // Línea de tiro libre derecha
            await this.drawLineLocalAndServer(
                coords.rightKey.x, coords.rightKey.y,
                coords.rightKey.x, coords.rightKey.y + coords.rightKey.height,
                color, thickness, 60
            );
            // Semicírculos de tiro libre
            await this.drawProfessionalArc({
                centerX: freeThrowX,
                centerY: coords.leftKey.y + coords.leftKey.height/2,
                radius: coords.leftKey.height/2
            }, color, thickness, -Math.PI/2, Math.PI/2);
            await this.drawProfessionalArc({
                centerX: coords.rightKey.x,
                centerY: coords.rightKey.y + coords.rightKey.height/2,
                radius: coords.rightKey.height/2
            }, color, thickness, Math.PI/2, 3*Math.PI/2);
        }

        /* ---------- BASKETBALL POSSESSION SYSTEM ---------- */
        handleBasketballPossession() {
            const players = this.getPlayerPositions();
            if (players.length === 0) return;

            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'basketball') return;

                let closestPlayer = null;
                let closestDistance = Infinity;

                // Encontrar jugador más cercano
                players.forEach(player => {
                    const dx = ball.x - player.x;
                    const dy = ball.y - player.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    if (distance < closestDistance) {
                        closestDistance = distance;
                        closestPlayer = player;
                    }
                });

                // Sistema de posesión
                if (closestPlayer && closestDistance < this.possessionSystem.possessionDistance) {
                    const currentTime = performance.now();

                    // Si no tiene dueño o es un robo válido
                    if (!ball.owner || (ball.owner.id !== closestPlayer.id &&
                        currentTime - ball.lastStealAttempt > PHYSICS_CONSTANTS.STEAL_COOLDOWN)) {

                        // Cambio de posesión
                        if (ball.owner && ball.owner.id !== closestPlayer.id) {
                            ball.lastStealAttempt = currentTime;
                            this.showFeedback(`🏀 ${closestPlayer.type === 'self' ? 'YOU' : 'OPPONENT'} STOLE THE BALL!`, '#FF4500');
                        }

                        ball.owner = closestPlayer;
                        ball.isBeingDribbled = true;
                    }

                    // Efecto de dribleo
                    if (ball.owner && ball.owner.id === closestPlayer.id) {
                        this.applyDribblePhysics(ball, closestPlayer);
                    }
                } else {
                    // Pelota libre
                    ball.owner = null;
                    ball.isBeingDribbled = false;
                }
            });
        }

        // Física de dribleo
        applyDribblePhysics(ball, player) {
            const dx = player.x - ball.x;
            const dy = player.y - ball.y;
            const distance = Math.sqrt(dx * dx + dy * dy);

            if (distance > 0) {
                // Fuerza magnética suave hacia el jugador
                const magneticForce = PHYSICS_CONSTANTS.DRIBBLE_FORCE / (distance * 0.5);
                ball.vx += (dx / distance) * magneticForce * PHYSICS_CONSTANTS.TIMESTEP;
                ball.vy += (dy / distance) * magneticForce * PHYSICS_CONSTANTS.TIMESTEP;

                // Transferir velocidad del jugador
                if (player.vx || player.vy) {
                    ball.vx += (player.vx || 0) * 0.3;
                    ball.vy += (player.vy || 0) * 0.3;
                }

                // Dribleo automático cada 800ms
                if (performance.now() - ball.lastDribbleTime > 800) {
                    ball.lastDribbleTime = performance.now();
                    ball.vy -= 100; // Pequeño rebote hacia arriba
                }
            }
        }

        /* ---------- NBA SCORING SYSTEM ---------- */
        checkBasketballScoring() {
            if (!this.matchMode.active || !this.canvasElement) return;

            const coords = this.calculateProfessionalBasketballCoordinates();
            const currentTime = performance.now();

            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'basketball') return;
                if (currentTime - ball.lastGoalTime < 2000) return;

                // Detección de canasta más precisa para aros NBA
                const basketDetection = PHYSICS_CONSTANTS.BALL_RADIUS + 15;

                // Canasta izquierda (P2 anota) - usando coordenadas del aro
                const leftRimY = coords.leftBasket.y + coords.leftBasket.backboardHeight/3;
                if (ball.x >= coords.leftBasket.x - basketDetection &&
                    ball.x <= coords.leftBasket.x + basketDetection &&
                    ball.y >= leftRimY - basketDetection &&
                    ball.y <= leftRimY + basketDetection) {

                    ball.lastGoalTime = currentTime;
                    this.scoreBasket('p2', ball);
                }

                // Canasta derecha (P1 anota) - usando coordenadas del aro
                const rightRimY = coords.rightBasket.y + coords.rightBasket.backboardHeight/3;
                if (ball.x >= coords.rightBasket.x - basketDetection &&
                    ball.x <= coords.rightBasket.x + basketDetection &&
                    ball.y >= rightRimY - basketDetection &&
                    ball.y <= rightRimY + basketDetection) {

                    ball.lastGoalTime = currentTime;
                    this.scoreBasket('p1', ball);
                }
            });
        }

        // Anotar canasta con rebote hacia adentro
        async scoreBasket(player, basketball) {
            if (this.matchMode.goalCooldown) return;
            this.matchMode.goalCooldown = true;

            // Rebote hacia adentro de la canasta
            const bounceForce = 80;
            basketball.vx *= -0.2;
            basketball.vy = -bounceForce;

            this.matchMode.scores[player]++;
            this.gameStats.totalBaskets++;

            this.updateScoreboard();
            await this.updateNBAScoreDisplay();

            this.showFeedback(`🏀 NBA BASKET! ${player.toUpperCase()} SCORES!`, '#FFD700');

            // NO eliminar la pelota, solo liberar posesión
            basketball.owner = null;
            basketball.isBeingDribbled = false;

            setTimeout(() => {
                this.matchMode.goalCooldown = false;
            }, 1500);

            if (this.matchMode.scores[player] >= MATCH_CONSTANTS.MAX_BASKETS) {
                await this.endMatch(player);
            }
        }

        /* ---------- MATCH MODE WITH NBA COURT ---------- */
        toggleMatchMode() {
            const button = document.getElementById('match-mode-toggle');
            const scoreboard = document.getElementById('match-scoreboard');

            this.matchMode.active = !this.matchMode.active;

            if (this.matchMode.active) {
                button.style.background = 'linear-gradient(135deg, #ffd700, #ffb347)';
                scoreboard.style.display = 'block';
                this.setupMatchMode();
                this.showFeedback('🏆 NBA MATCH MODE ACTIVATED!', '#ffd700');
            } else {
                button.style.background = 'linear-gradient(135deg, #444, #666)';
                scoreboard.style.display = 'none';
                this.resetMatch();
                this.showFeedback('🏆 Match Mode Deactivated', '#666');
            }
        }

        async setupMatchMode() {
            await this.createProfessionalNBACourt();
            this.matchMode.scores = { p1: 0, p2: 0 };
            this.updateScoreboard();
            this.setupReducedPlayArea();

            setTimeout(() => {
                this.addRandomBasketball(true);
            }, 500);
        }

        async drawNBAScoreboards(coords) {
            if (!this.canvasElement) return;

            // P1 scoreboard (cerca del aro derecho)
            const p1X = coords.rightBasket.x;
            const p1Y = coords.rightBasket.y - 60;

            // P2 scoreboard (cerca del aro izquierdo)
            const p2X = coords.leftBasket.x;
            const p2Y = coords.leftBasket.y - 60;

            await this.drawNBASmallText("P1", p1X - 20, p1Y - 30, NBA_COURT_CONSTANTS.TEXT_COLOR, 3);
            await this.drawNBASmallText("P2", p2X - 20, p2Y - 30, NBA_COURT_CONSTANTS.TEXT_COLOR, 3);

            this.matchMode.lastScorePositions = {
                p1: { x: p1X, y: p1Y },
                p2: { x: p2X, y: p2Y }
            };

            await this.updateNBAScoreDisplay();
        }

        async updateNBAScoreDisplay() {
            if (!this.matchMode.lastScorePositions.p1) return;

            const { p1, p2 } = this.matchMode.lastScorePositions;
            const pixelSize = 4;

            await this.clearScoreArea(p1.x, p1.y, pixelSize);
            await this.clearScoreArea(p2.x, p2.y, pixelSize);

            await this.drawPixelNumber(this.matchMode.scores.p1, p1.x, p1.y, NBA_COURT_CONSTANTS.TEXT_COLOR, pixelSize);
            await this.drawPixelNumber(this.matchMode.scores.p2, p2.x, p2.y, NBA_COURT_CONSTANTS.TEXT_COLOR, pixelSize);
        }

        /* ---------- PHYSICS ENGINE ---------- */
        togglePhysics() {
            const toggleBtn = document.getElementById('toggle-physics');
            if (!this.isActive) {
                this.startPhysics();
                if (toggleBtn) {
                    toggleBtn.textContent = '🛑 Stop Basketball Engine';
                    toggleBtn.style.background = 'linear-gradient(135deg, #f56565, #e53e3e)';
                }
            } else {
                this.stopPhysics();
                if (toggleBtn) {
                    toggleBtn.textContent = '🚀 Launch Basketball Engine';
                    toggleBtn.style.background = 'linear-gradient(135deg, #FF8C00, #FF6347)';
                }
            }
        }

        startPhysics() {
            if (this.isActive) return;
            this.isActive = true;
            this.startGameLoop();
            this.showFeedback('🚀 NBA Basketball Engine Started!', '#FF8C00');
        }

        stopPhysics() {
            this.isActive = false;
            this.showFeedback('🛑 Basketball Engine Stopped', '#f56565');
        }

        startGameLoop() {
            if (!this.isActive) return;
            const currentTime = performance.now();
            if (currentTime - this.lastRenderTime >= this.renderInterval) {
                this.updateAdvancedPhysics();
                this.renderOptimized();
                this.lastRenderTime = currentTime;
            }
            requestAnimationFrame(() => this.startGameLoop());
        }

        updateAdvancedPhysics() {
            const dt = PHYSICS_CONSTANTS.TIMESTEP;

            // Apply physics mode modifications
            let gravityMultiplier = 1;
            let airResistanceMultiplier = 1;

            switch(this.controls.alternatePhysics) {
                case 'moon':
                    gravityMultiplier = 0.16;
                    break;
                case 'underwater':
                    airResistanceMultiplier = 15;
                    gravityMultiplier = 0.3;
                    break;
                case 'magnetic':
                    break;
            }

            // Update all basketballs
            this.physicsObjects.forEach(obj => {
                // Apply air resistance
                obj.vx *= (1 - PHYSICS_CONSTANTS.AIR_RESISTANCE * airResistanceMultiplier * dt);
                obj.vy *= (1 - PHYSICS_CONSTANTS.AIR_RESISTANCE * airResistanceMultiplier * dt);

                // Apply gravity
                obj.vy += PHYSICS_CONSTANTS.GRAVITY * gravityMultiplier * dt;

                // Magnetic field effects
                if (this.controls.alternatePhysics === 'magnetic') {
                    this.physicsObjects.forEach(otherObj => {
                        if (otherObj.id !== obj.id) {
                            const dx = otherObj.x - obj.x;
                            const dy = otherObj.y - obj.y;
                            const distance = Math.sqrt(dx * dx + dy * dy);

                            if (distance > 0 && distance < 200) {
                                const magneticForce = 50 / (distance * distance);
                                const forceX = (dx / distance) * magneticForce;
                                const forceY = (dy / distance) * magneticForce;

                                obj.vx += forceX * dt;
                                obj.vy += forceY * dt;
                            }
                        }
                    });
                }

                // Update position
                obj.x += obj.vx * dt;
                obj.y += obj.vy * dt;

                // Boundary collisions
                this.handleBoundaryCollisions(obj);

                // Track maximum velocity
                const speed = Math.sqrt(obj.vx * obj.vx + obj.vy * obj.vy);
                if (speed > this.gameStats.maxVelocityReached) {
                    this.gameStats.maxVelocityReached = speed;
                }

                // Limit maximum velocity
                if (speed > PHYSICS_CONSTANTS.MAX_VELOCITY) {
                    obj.vx = (obj.vx / speed) * PHYSICS_CONSTANTS.MAX_VELOCITY;
                    obj.vy = (obj.vy / speed) * PHYSICS_CONSTANTS.MAX_VELOCITY;
                }
            });

            // Handle collisions
            this.handleObjectCollisions();
            this.handleBallPlayerCollisions();

            // Handle basketball possession system
            this.handleBasketballPossession();

            // Check for basketball scoring
            if (this.matchMode.active) {
                this.checkBasketballScoring();
            }
        }

        /* ---------- OBJECT CREATION ---------- */
        addRandomBasketball(spawnAtCenterForScore = false) {
            if (!this.canvasElement) return;

            let x, y;
            if (spawnAtCenterForScore) {
                x = this.canvasElement.width / 2;
                y = this.canvasElement.height / 2;
            } else {
                const padding = 100;
                x = Math.random() * (this.canvasElement.width - 2 * padding) + padding;
                y = Math.random() * (this.canvasElement.height * 0.4 - 2 * padding) + padding;
            }

            this.createBasketball(x, y);
        }

        createBasketball(x, y) {
            const id = `basketball_${this.objectIdCounter++}`;
            const ball = {
                id: id,
                type: 'basketball',
                x: x, y: y, vx: 0, vy: 0,
                radius: PHYSICS_CONSTANTS.BALL_RADIUS,
                color: PHYSICS_CONSTANTS.BALL_COLOR,
                mass: PHYSICS_CONSTANTS.BALL_MASS,
                restitution: PHYSICS_CONSTANTS.RESTITUTION_BALL,
                friction: PHYSICS_CONSTANTS.FRICTION_COURT,
                lastRenderX: -9999, lastRenderY: -9999,
                creationTime: performance.now(),
                lastCollisionTime: 0,
                lastGoalTime: 0,

                // Propiedades de baloncesto
                owner: null,
                lastDribbleTime: 0,
                isBeingDribbled: false,
                lastStealAttempt: 0
            };

            this.physicsObjects.set(id, ball);
            this.gameStats.objectsCreated++;
            return ball;
        }

        /* ---------- COLLISION HANDLING ---------- */
        handleBoundaryCollisions(obj) {
            if (!this.canvasElement) return;

            let objHalfSize = obj.radius;

            let boundaries;
            if (this.matchMode.active && this.matchMode.playArea) {
                boundaries = {
                    left: this.matchMode.playArea.left + objHalfSize,
                    right: this.matchMode.playArea.right - objHalfSize,
                    top: this.matchMode.playArea.top + objHalfSize,
                    bottom: this.matchMode.playArea.bottom - objHalfSize
                };
            } else {
                boundaries = {
                    left: objHalfSize,
                    right: this.canvasElement.width - objHalfSize,
                    top: objHalfSize,
                    bottom: this.canvasElement.height - objHalfSize
                };
            }

            if (obj.x < boundaries.left) {
                obj.x = boundaries.left;
                obj.vx = -obj.vx * PHYSICS_CONSTANTS.RESTITUTION_WALL;
            } else if (obj.x > boundaries.right) {
                obj.x = boundaries.right;
                obj.vx = -obj.vx * PHYSICS_CONSTANTS.RESTITUTION_WALL;
            }

            if (obj.y < boundaries.top) {
                obj.y = boundaries.top;
                obj.vy = -obj.vy * PHYSICS_CONSTANTS.RESTITUTION_WALL;
            } else if (obj.y > boundaries.bottom) {
                obj.y = boundaries.bottom;
                obj.vy = -obj.vy * PHYSICS_CONSTANTS.RESTITUTION_WALL;
                obj.vx *= obj.friction;
            }
        }

        handleObjectCollisions() {
            const objectsArray = Array.from(this.physicsObjects.values());
            for (let i = 0; i < objectsArray.length; i++) {
                const objA = objectsArray[i];
                for (let j = i + 1; j < objectsArray.length; j++) {
                    const objB = objectsArray[j];

                    if (objA.type === 'basketball' && objB.type === 'basketball') {
                        if (this.handleBasketballCollision(objA, objB)) {
                            this.gameStats.totalCollisions++;
                            objA.lastCollisionTime = performance.now();
                            objB.lastCollisionTime = performance.now();
                        }
                    }
                }
            }
        }

        handleBasketballCollision(ball1, ball2) {
            const dx = ball2.x - ball1.x;
            const dy = ball2.y - ball1.y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            const minDistance = ball1.radius + ball2.radius;

            if (distance < minDistance && distance !== 0) {
                const normalX = dx / distance;
                const normalY = dy / distance;

                const overlap = minDistance - distance;
                ball1.x -= normalX * overlap * 0.5;
                ball1.y -= normalY * overlap * 0.5;
                ball2.x += normalX * overlap * 0.5;
                ball2.y += normalY * overlap * 0.5;

                const rvX = ball2.vx - ball1.vx;
                const rvY = ball2.vy - ball1.vy;
                const velAlongNormal = rvX * normalX + rvY * normalY;

                if (velAlongNormal > 0) return false;

                const e = (ball1.restitution + ball2.restitution) * 0.5;
                let j = -(1 + e) * velAlongNormal;
                j /= (1 / ball1.mass) + (1 / ball2.mass);

                const impulseX = j * normalX;
                const impulseY = j * normalY;

                ball1.vx -= impulseX / ball1.mass;
                ball1.vy -= impulseY / ball1.mass;
                ball2.vx += impulseX / ball2.mass;
                ball2.vy += impulseY / ball2.mass;

                return true;
            }
            return false;
        }

        /* ---------- PLAYER COLLISION SYSTEM ---------- */
        getPlayerPositions() {
            const currentTime = performance.now();
            const players = [];
            if (!drawariaCanvas) return players;

            const canvasRect = drawariaCanvas.getBoundingClientRect();
            const deltaTime = currentTime - this.playerTracker.lastUpdateTime;

            const selfPlayer = document.querySelector('div.spawnedavatar.spawnedavatar-self');
            if (selfPlayer) {
                const rect = selfPlayer.getBoundingClientRect();
                const currentPos = {
                    type: 'self',
                    id: selfPlayer.dataset.playerid || 'self',
                    x: rect.left - canvasRect.left + rect.width / 2,
                    y: rect.top - canvasRect.top + rect.height / 2,
                    width: rect.width,
                    height: rect.height,
                    radius: Math.max(rect.width, rect.height) / 2,
                    vx: 0,
                    vy: 0
                };

                const prevPlayer = this.playerTracker.players.get('self');
                if (prevPlayer && deltaTime > 0) {
                    currentPos.vx = (currentPos.x - prevPlayer.x) / (deltaTime / 1000);
                    currentPos.vy = (currentPos.y - prevPlayer.y) / (deltaTime / 1000);
                }

                players.push(currentPos);
                this.playerTracker.players.set('self', currentPos);
            }

            const otherPlayers = document.querySelectorAll('div.spawnedavatar.spawnedavatar-otherplayer');
            otherPlayers.forEach((player, index) => {
                const rect = player.getBoundingClientRect();
                const playerId = player.dataset.playerid || `other_${index}`;
                const currentPos = {
                    type: 'other',
                    id: playerId,
                    x: rect.left - canvasRect.left + rect.width / 2,
                    y: rect.top - canvasRect.top + rect.height / 2,
                    width: rect.width,
                    height: rect.height,
                    radius: Math.max(rect.width, rect.height) / 2,
                    vx: 0,
                    vy: 0
                };

                const prevPlayer = this.playerTracker.players.get(playerId);
                if (prevPlayer && deltaTime > 0) {
                    currentPos.vx = (currentPos.x - prevPlayer.x) / (deltaTime / 1000);
                    currentPos.vy = (currentPos.y - prevPlayer.y) / (deltaTime / 1000);
                }

                players.push(currentPos);
                this.playerTracker.players.set(playerId, currentPos);
            });

            this.playerTracker.lastUpdateTime = currentTime;

            return players.filter(p =>
                p.x >= -this.playerTracker.detectionRadius &&
                p.x <= drawariaCanvas.width + this.playerTracker.detectionRadius &&
                p.y >= -this.playerTracker.detectionRadius &&
                p.y <= drawariaCanvas.height + this.playerTracker.detectionRadius
            );
        }

        handleBallPlayerCollisions() {
            const players = this.getPlayerPositions();
            if (players.length === 0) return;

            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'basketball') return;

                players.forEach(player => {
                    const dx = ball.x - player.x;
                    const dy = ball.y - player.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const detectionDistance = this.playerTracker.detectionRadius;

                    if (distance < detectionDistance && distance > 0) {
                        const intensity = Math.max(0, (detectionDistance - distance) / detectionDistance);

                        if (distance < ball.radius + player.radius) {
                            this.resolveBasketballPlayerCollision(ball, player, dx, dy, distance, 'collision');
                        } else if (intensity > 0.3) {
                            this.resolveBasketballPlayerCollision(ball, player, dx, dy, distance, 'push', intensity);
                        }
                    }
                });
            });
        }

        resolveBasketballPlayerCollision(ball, player, dx, dy, distance, interactionType = 'collision', intensity = 1.0) {
            const normalX = dx / distance;
            const normalY = dy / distance;

            if (interactionType === 'collision') {
                const overlap = (ball.radius + player.radius) - distance;
                ball.x += normalX * overlap * 1.1;
                ball.y += normalY * overlap * 1.1;

                const relativeVelX = ball.vx - (player.vx || 0);
                const relativeVelY = ball.vy - (player.vy || 0);
                const velAlongNormal = relativeVelX * normalX + relativeVelY * normalY;

                if (velAlongNormal > 0) return;

                const restitution = PHYSICS_CONSTANTS.PLAYER_RESTITUTION;
                const impulse = -(1 + restitution) * velAlongNormal;

                ball.vx += impulse * normalX;
                ball.vy += impulse * normalY;

                if (player.vx || player.vy) {
                    const transferFactor = 0.7;
                    ball.vx += (player.vx || 0) * transferFactor;
                    ball.vy += (player.vy || 0) * transferFactor;
                }

                const additionalForce = PHYSICS_CONSTANTS.PLAYER_INTERACTION_FORCE * 1.5;
                ball.vx += normalX * additionalForce * PHYSICS_CONSTANTS.TIMESTEP;
                ball.vy += normalY * additionalForce * PHYSICS_CONSTANTS.TIMESTEP;

            } else if (interactionType === 'push') {
                const pushForce = PHYSICS_CONSTANTS.PLAYER_INTERACTION_FORCE *
                                 PHYSICS_CONSTANTS.PLAYER_PUSH_MULTIPLIER *
                                 intensity * intensity;

                ball.vx += normalX * pushForce * PHYSICS_CONSTANTS.TIMESTEP;
                ball.vy += normalY * pushForce * PHYSICS_CONSTANTS.TIMESTEP;

                if (player.vx || player.vy) {
                    const playerSpeed = Math.sqrt((player.vx || 0) ** 2 + (player.vy || 0) ** 2);
                    if (playerSpeed > 50) {
                        const moveTransfer = intensity * 0.4;
                        ball.vx += (player.vx || 0) * moveTransfer;
                        ball.vy += (player.vy || 0) * moveTransfer;
                    }
                }
            }

            const maxSpeed = PHYSICS_CONSTANTS.MAX_VELOCITY * 1.2;
            const currentSpeed = Math.sqrt(ball.vx ** 2 + ball.vy ** 2);
            if (currentSpeed > maxSpeed) {
                ball.vx = (ball.vx / currentSpeed) * maxSpeed;
                ball.vy = (ball.vy / currentSpeed) * maxSpeed;
            }
        }

        /* ---------- RENDERING ---------- */
        renderOptimized() {
            this.physicsObjects.forEach(obj => {
                if (obj.type !== 'basketball') return;

                const dx = Math.abs(obj.x - obj.lastRenderX);
                const dy = Math.abs(obj.y - obj.lastRenderY);

                const needsServerRedraw = dx > MOVEMENT_THRESHOLD || dy > MOVEMENT_THRESHOLD;

                if (needsServerRedraw) {
                    // Erase old position
                    if (obj.lastRenderX !== -9999 || obj.lastRenderY !== -9999) {
                        this.drawBasketball(obj.lastRenderX, obj.lastRenderY, obj.radius, '#FFFFFF');
                    }

                    // Draw at new position
                    this.drawBasketball(obj.x, obj.y, obj.radius, obj.color);

                    obj.lastRenderX = obj.x;
                    obj.lastRenderY = obj.y;
                }
            });
        }

        drawBasketball(x, y, radius, color) {
            const effectiveThickness = radius * 2.5;
            enqueueDrawCommand(x, y, x + 0.1, y + 0.1, color, effectiveThickness);
        }

        /* ---------- UTILITY FUNCTIONS ---------- */
        clearAllObjects(showFeedback = true) {
            this.physicsObjects.clear();
            positionCache.clear();

            if (drawariaCtx && drawariaCanvas) {
                drawariaCtx.clearRect(0, 0, drawariaCanvas.width, drawariaCanvas.height);
            }
            if (showFeedback) {
                this.showFeedback('🗑️ ALL BASKETBALLS CLEARED!', '#cc0000');
            }
        }

        resetAllObjects() {
            if (this.canvasElement) {
                this.physicsObjects.forEach(obj => {
                    obj.x = this.canvasElement.width / 2 + (Math.random() - 0.5) * 100;
                    obj.y = this.canvasElement.height / 2 + (Math.random() - 0.5) * 100;
                    obj.vx = 0; obj.vy = 0;
                    obj.lastRenderX = -9999; obj.lastRenderY = -9999;
                    obj.lastGoalTime = 0;
                    obj.owner = null;
                    obj.isBeingDribbled = false;
                });

                this.showFeedback('🔄 All basketballs reset!', '#74b9ff');
            }
        }

        setupReducedPlayArea() {
            if (!this.canvasElement) return;

            const reductionSides = this.canvasElement.width * MATCH_CONSTANTS.PLAY_AREA_REDUCTION.SIDES;
            const reductionTop = this.canvasElement.height * MATCH_CONSTANTS.PLAY_AREA_REDUCTION.TOP;

            this.matchMode.playArea = {
                left: reductionSides,
                right: this.canvasElement.width - reductionSides,
                top: reductionTop,
                bottom: this.canvasElement.height
            };
        }

        updateScoreboard() {
            document.getElementById('score-p1').textContent = this.matchMode.scores.p1;
            document.getElementById('score-p2').textContent = this.matchMode.scores.p2;
        }

                async endMatch(winner) {
            this.showFeedback(`🏆 ${winner.toUpperCase()} WINS THE NBA MATCH!`, '#ffd700');

            setTimeout(() => {
                this.resetMatch();
            }, 3000);
        }

        resetMatch() {
            this.matchMode.scores = { p1: 0, p2: 0 };
            this.updateScoreboard();
            if (this.matchMode.active) {
                this.clearAllObjects(false);
                this.createProfessionalNBACourt().then(() => {
                    this.addRandomBasketball(true);
                });
            }
        }

        /* ---------- NBA PIXEL TEXT DRAWING ---------- */
        NBA_PIXEL_LETTERS = {
            'B': [[1,1,1,1],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,1,1,1]],
            'A': [[0,1,1,0],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,0,0,1]],
            'S': [[1,1,1,1],[1,0,0,0],[1,1,1,1],[0,0,0,1],[1,1,1,1]],
            'K': [[1,0,0,1],[1,0,1,0],[1,1,0,0],[1,0,1,0],[1,0,0,1]],
            'E': [[1,1,1,1],[1,0,0,0],[1,1,1,0],[1,0,0,0],[1,1,1,1]],
            'T': [[1,1,1,1,1],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0],[0,0,1,0,0]],
            'L': [[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,1,1,1]],
            'O': [[1,1,1,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,1,1]],
            'P': [[1,1,1,1],[1,0,0,1],[1,1,1,1],[1,0,0,0],[1,0,0,0]],
            '1': [[0,1,0],[1,1,0],[0,1,0],[0,1,0],[1,1,1]],
            '2': [[1,1,1],[0,0,1],[1,1,1],[1,0,0],[1,1,1]]
        };

        NUMBER_PATTERNS = {
            0: [[1,1,1],[1,0,1],[1,0,1],[1,0,1],[1,1,1]],
            1: [[0,1,0],[1,1,0],[0,1,0],[0,1,0],[1,1,1]],
            2: [[1,1,1],[0,0,1],[1,1,1],[1,0,0],[1,1,1]],
            3: [[1,1,1],[0,0,1],[1,1,1],[0,0,1],[1,1,1]],
            4: [[1,0,1],[1,0,1],[1,1,1],[0,0,1],[0,0,1]],
            5: [[1,1,1],[1,0,0],[1,1,1],[0,0,1],[1,1,1]]
        };

        async drawNBAPixelText(text, coords) {
            if (this.fieldDrawing.isStopped) return;
            const letterSpacing = coords.text.pixelSize * 7;
            const textWidth = text.length * letterSpacing;
            let currentX = coords.text.x - (textWidth / 2);

            for (let i = 0; i < text.length; i++) {
                if (this.fieldDrawing.isStopped) break;
                const letter = text[i].toUpperCase();
                if (letter === ' ') {
                    currentX += letterSpacing;
                    continue;
                }
                const pattern = this.NBA_PIXEL_LETTERS[letter];
                if (!pattern) continue;

                for (let row = 0; row < pattern.length; row++) {
                    for (let col = 0; col < pattern[row].length; col++) {
                        if (pattern[row][col] === 1) {
                            const pixelX = currentX + (col * coords.text.pixelSize);
                            const pixelY = coords.text.y + (row * coords.text.pixelSize);
                            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
                            if (pixelX >= 0 && pixelX < canvasSize.width && pixelY >= 0 && pixelY < canvasSize.height) {
                                await this.drawNBAPixel(pixelX, pixelY, NBA_COURT_CONSTANTS.TEXT_COLOR, coords.text.pixelSize);
                            }
                        }
                    }
                }
                currentX += letterSpacing;
                await sleep(120);
            }
        }

        async drawNBAPixelText(text, x, y, color, pixelSize) {
            let currentX = x;
            for (let i = 0; i < text.length; i++) {
                const letter = text[i];
                const pattern = this.NBA_PIXEL_LETTERS[letter];
                if (pattern) {
                    for (let row = 0; row < pattern.length; row++) {
                        for (let col = 0; col < pattern[row].length; col++) {
                            if (pattern[row][col] === 1) {
                                const pixelX = currentX + (col * pixelSize);
                                const pixelY = y + (row * pixelSize);
                                await this.drawNBAPixel(pixelX, pixelY, color, pixelSize);
                            }
                        }
                    }
                }
                currentX += pixelSize * 4;
            }
        }

        async drawPixelNumber(number, x, y, color, pixelSize) {
            const pattern = this.NUMBER_PATTERNS[number];
            if (!pattern) return;

            for (let row = 0; row < pattern.length; row++) {
                for (let col = 0; col < pattern[row].length; col++) {
                    if (pattern[row][col] === 1) {
                        const pixelX = x + (col * pixelSize);
                        const pixelY = y + (row * pixelSize);
                        await this.drawNBAPixel(pixelX, pixelY, color, pixelSize);
                    }
                }
            }
        }

        async drawNBAPixel(x, y, color, size = 2) {
            if (this.fieldDrawing.isStopped) return;
            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
            x = clamp(x, 0, canvasSize.width - size);
            y = clamp(y, 0, canvasSize.height - size);
            enqueueDrawCommand(x, y, x + 1, y + 1, color, size);
            await sleep(20);
        }

        async clearScoreArea(x, y, size) {
            const clearWidth = size * 5 + 10;
            const clearHeight = size * 7 + 10;
            const startX = x - 5;
            const startY = y - 5;

            await sleep(10);
        }

        /* ---------- DRAWING FUNCTIONS ---------- */
        async drawLineLocalAndServer(startX, startY, endX, endY, color, thickness, delay = 60) {
            if (this.fieldDrawing.isStopped) {
                this.fieldDrawing.isDrawing = false;
                return;
            }
            const canvasSize = { width: drawariaCanvas.width, height: drawariaCanvas.height };
            startX = clamp(startX, -100, canvasSize.width + 100);
            startY = clamp(startY, 0, canvasSize.height);
            endX = clamp(endX, -100, canvasSize.width + 100);
            endY = clamp(endY, 0, canvasSize.height);
            enqueueDrawCommand(startX, startY, endX, endY, color, thickness);
            await sleep(delay);
        }

        // Clean Canvas functionality
        async cleanCanvas() {
            if (!drawariaCanvas) return;

            this.showFeedback('🧹 Cleaning NBA Court...', '#e17055');

            const canvasWidth = drawariaCanvas.width;
            const canvasHeight = drawariaCanvas.height;

            for (let y = 0; y < canvasHeight; y += 100) {
                for (let x = 0; x < canvasWidth; x += 100) {
                    const width = Math.min(100, canvasWidth - x);
                    const height = Math.min(100, canvasHeight - y);
                    enqueueDrawCommand(x, y, x + width, y + height, '#FFFFFF', Math.max(width, height));
                    await sleep(5);
                }
            }

            if (drawariaCtx) {
                drawariaCtx.clearRect(0, 0, canvasWidth, canvasHeight);
            }

            this.showFeedback('🧹 NBA Court Cleaned!', '#00d084');
        }

        /* ---------- PANEL FUNCTIONALITY ---------- */
        makePanelDraggable() {
            const panel = document.getElementById('advanced-physics-panel');
            const header = document.getElementById('panel-header');

            let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

            if (header) {
                header.onmousedown = dragMouseDown;
            } else {
                panel.onmousedown = dragMouseDown;
            }

            function dragMouseDown(e) {
                e = e || window.event;
                e.preventDefault();
                pos3 = e.clientX;
                pos4 = e.clientY;
                document.onmouseup = closeDragElement;
                document.onmousemove = elementDrag;
                panel.classList.add('panel-dragging');
            }

            function elementDrag(e) {
                e = e || window.event;
                e.preventDefault();
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;

                const newTop = panel.offsetTop - pos2;
                const newLeft = panel.offsetLeft - pos1;

                const maxLeft = window.innerWidth - panel.offsetWidth;
                const maxTop = window.innerHeight - panel.offsetHeight;

                panel.style.top = Math.min(Math.max(0, newTop), maxTop) + "px";
                panel.style.left = Math.min(Math.max(0, newLeft), maxLeft) + "px";
                panel.style.right = 'auto';
            }

            function closeDragElement() {
                document.onmouseup = null;
                document.onmousemove = null;
                panel.classList.remove('panel-dragging');
            }
        }

        setupPanelButtons() {
            const minimizeBtn = document.getElementById('minimize-btn');
            const closeBtn = document.getElementById('close-btn');
            const content = document.getElementById('panel-content');
            const panel = document.getElementById('advanced-physics-panel');

            let isMinimized = false;

            // BOTÓN MINIMIZAR
            minimizeBtn?.addEventListener('click', (e) => {
                e.stopPropagation();
                if (!panel) return;

                if (!isMinimized) {
                    content.style.display = 'none';
                    panel.style.height = 'auto';
                    minimizeBtn.innerHTML = '+';
                    isMinimized = true;
                    this.showFeedback('📱 NBA Panel Minimized', '#FF8C00');
                } else {
                    content.style.display = 'block';
                    panel.style.height = 'auto';
                    minimizeBtn.innerHTML = '−';
                    isMinimized = false;
                    this.showFeedback('📱 NBA Panel Restored', '#FF8C00');
                }
            });

            // BOTÓN CERRAR
            closeBtn?.addEventListener('click', (e) => {
                e.stopPropagation();
                if (!panel) return;

                if (confirm('¿Estás seguro de que quieres cerrar el panel de baloncesto NBA?')) {
                    if (this.isActive) {
                        this.stopPhysics();
                    }
                    panel.remove();
                    this.showFeedback('❌ NBA Basketball Panel Closed', '#ff4757');
                    console.log('🔴 NBA Basketball Panel closed by user');
                }
            });

            // Efectos hover
            [minimizeBtn, closeBtn].forEach(btn => {
                if (!btn) return;
                btn.addEventListener('mouseenter', () => btn.style.opacity = '0.8');
                btn.addEventListener('mouseleave', () => btn.style.opacity = '1');
            });
        }

        startAdvancedStatsMonitoring() {
            setInterval(() => {
                document.getElementById('object-count').textContent = this.physicsObjects.size;
                document.getElementById('goals-count').textContent = this.gameStats.totalBaskets;
                document.getElementById('collision-count').textContent = this.gameStats.totalCollisions;
                document.getElementById('max-speed').textContent = Math.round(this.gameStats.maxVelocityReached);
                document.getElementById('queue-count').textContent = commandQueue.length;

                const queueSize = commandQueue.length;
                const performanceElement = document.getElementById('performance');
                if (queueSize < 30) {
                    performanceElement.textContent = 'Optimal';
                    performanceElement.style.color = '#48bb78';
                } else if (queueSize < 150) {
                    performanceElement.textContent = 'Good';
                    performanceElement.style.color = '#ed8936';
                } else {
                    performanceElement.textContent = 'Overloaded';
                    performanceElement.style.color = '#f56565';
                }
            }, 1000);
        }

        showFeedback(message, color) {
            // Remove existing feedback
            const existingFeedback = document.querySelector('.feedback-div');
            if (existingFeedback) existingFeedback.remove();

            const feedback = document.createElement('div');
            feedback.className = 'feedback-div';
            feedback.style.cssText = `
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: ${color};
                color: white;
                padding: 15px 25px;
                border-radius: 10px;
                font-weight: bold;
                z-index: 2147483648;
                font-size: 16px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.3);
                opacity: 0;
                transition: opacity 0.3s ease-in-out;
                text-align: center;
                min-width: 300px;
                border: 2px solid rgba(255,255,255,0.3);
            `;
            feedback.innerHTML = message;

            document.body.appendChild(feedback);
            setTimeout(() => feedback.style.opacity = '1', 10);
            setTimeout(() => feedback.style.opacity = '0', 2500);
            setTimeout(() => feedback.remove(), 2800);
        }
    }

    /* ---------- GLOBAL INITIALIZATION ---------- */
    let basketballEngine = null;

    const initNBABasketballEngine = () => {
        if (!basketballEngine) {
            console.log('🏀 Initializing Advanced NBA Basketball Physics Engine v6.1...');
            basketballEngine = new AdvancedDrawariaBasketball();

            setTimeout(() => {
                const confirmMsg = document.createElement('div');
                confirmMsg.style.cssText = `
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: linear-gradient(45deg, #FF8C00, #FF6347);
                    color: white;
                    padding: 25px 35px;
                    border-radius: 20px;
                    font-size: 18px;
                    font-weight: bold;
                    z-index: 2147483648;
                    text-align: center;
                    box-shadow: 0 0 40px rgba(255,140,0,0.6);
                    opacity: 0;
                    transition: opacity 0.3s ease-in-out;
                    border: 3px solid #FFD700;
                `;
                confirmMsg.innerHTML = `
                    🏀 NBA BASKETBALL ENGINE v6.1 LOADED! 🏀<br>
                    <div style="font-size: 14px; margin-top: 10px; color: #FFE6D1;">
                        ✅ Professional NBA Court<br>
                        🏀 Advanced Physics System<br>
                        🎯 Match Mode & Possession<br>
                        🏗️ Support Poles & Official Lines<br>
                        🏆 Complete Scoring System
                    </div>
                `;

                document.body.appendChild(confirmMsg);
                setTimeout(() => confirmMsg.style.opacity = '1', 10);
                setTimeout(() => confirmMsg.style.opacity = '0', 4000);
                setTimeout(() => confirmMsg.remove(), 4300);
            }, 1000);
        }
    };

    // Enhanced CSS animations for NBA basketball
    const nbaBasketballStyle = document.createElement('style');
    nbaBasketballStyle.textContent = `
        @keyframes nba-bounce-effect {
            0% { transform: scale(0) rotate(0deg); opacity: 1; }
            50% { transform: scale(1.2) rotate(180deg); opacity: 0.8; }
            100% { transform: scale(0) rotate(360deg); opacity: 0; }
        }

        @keyframes nba-pulse-effect {
            0% { transform: scale(0.5); opacity: 0.8; }
            50% { transform: scale(1.3); opacity: 0.6; }
            100% { transform: scale(0); opacity: 0; }
        }

        @keyframes nba-dribble {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-10px); }
        }

        .toggle-btn[data-active="true"] {
            box-shadow: 0 0 15px rgba(255, 140, 0, 0.6) !important;
        }

        .mode-toggle[data-active="true"] {
            box-shadow: 0 0 15px rgba(255, 215, 0, 0.8) !important;
        }

        #advanced-physics-panel {
            transition: none !important;
        }

        #panel-header:hover {
            background: linear-gradient(45deg, #FF6347, #FF4500) !important;
        }

        #minimize-btn:hover {
            background: rgba(255,255,255,0.4) !important;
        }

        #close-btn:hover {
            background: rgba(255,0,0,0.8) !important;
        }

        .panel-dragging {
            user-select: none !important;
            pointer-events: none !important;
            opacity: 0.9;
        }

        /* NBA court styling */
        .nba-basketball-court {
            background: linear-gradient(45deg, ${NBA_COURT_CONSTANTS.COURT_COLOR}, #CD853F);
        }

        .basketball-possession {
            animation: nba-dribble 0.8s infinite ease-in-out;
        }

        /* NBA match mode styling */
        .nba-match-active {
            box-shadow: 0 0 20px rgba(255, 215, 0, 0.5);
        }

        /* NBA scoring animation */
        .nba-score-animation {
            animation: nba-pulse-effect 2s ease-out;
        }

        /* Professional NBA panel styling */
        .nba-professional-panel {
            background: linear-gradient(135deg, #0f0f23, #1a1a3a, #2a1810);
            border: 3px solid ${NBA_COURT_CONSTANTS.COURT_COLOR};
        }
    `;
    document.head.appendChild(nbaBasketballStyle);

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initNBABasketballEngine);
    } else {
        initNBABasketballEngine();
    }

    // Backup initialization
    setTimeout(initNBABasketballEngine, 2000);

    // Console welcome message
    console.log(`
    🏀============================================🏀
    🏆    NBA BASKETBALL PHYSICS ENGINE v6.1    🏆
    🏀============================================🏀

    ✅ Professional NBA Court Creation
    🏀 Advanced Physics System
    🎯 Match Mode with Scoring
    🏗️ Support Poles & Official Lines
    🏆 Complete Possession System

    Ready to play! Click the 🏀 button to start.
    🏀============================================🏀
    `);

})();