Minefun Simple Virtual Keyboard

Hiển thị duy nhất cụm phím ảo điều khiển di chuyển (WASD + Space) trên màn hình minefun.io. Ấn phím [ . ] để mở menu cài đặt màu sắc và vị trí.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Minefun Simple Virtual Keyboard
// @namespace    http://tampermonkey.net
// @version      1.1
// @description  Hiển thị duy nhất cụm phím ảo điều khiển di chuyển (WASD + Space) trên màn hình minefun.io. Ấn phím [ . ] để mở menu cài đặt màu sắc và vị trí.
// @author       AI Assistant
// @match        https://minefun.io*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // --- 1. TẠO GIAO DIỆN BÀN PHÍM ẢO DI CHUYỂN ---
    const kbContainer = document.createElement('div');
    kbContainer.id = 'virtual-keyboard';
    kbContainer.style.cssText = `
        position: fixed;
        bottom: 30px;
        left: 50%;
        transform: translateX(-50%);
        background: rgba(0, 0, 0, 0.7);
        padding: 12px;
        border-radius: 10px;
        z-index: 99999;
        display: flex;
        flex-direction: column;
        gap: 6px;
        user-select: none;
        box-shadow: 0 4px 15px rgba(0,0,0,0.5);
    `;

    // Cấu trúc chỉ gồm cụm phím di chuyển cơ bản
    const rows = [
        ['W'],
        ['A', 'S', 'D'],
        ['Space']
    ];

    rows.forEach(rowKeys => {
        const rowDiv = document.createElement('div');
        rowDiv.style.cssText = 'display: flex; justify-content: center; gap: 6px;';
        
        rowKeys.forEach(key => {
            const keyBtn = document.createElement('div');
            keyBtn.innerText = key === 'Space' ? 'SPACE' : key;
            keyBtn.className = 'kb-key';
            keyBtn.dataset.key = key.toLowerCase();
            
            // Kiểu dáng tối giản cho phím ảo
            keyBtn.style.cssText = `
                width: ${key === 'Space' ? '150px' : '45px'};
                height: 45px;
                background: #2a2a2a;
                color: #ffffff;
                display: flex;
                align-items: center;
                justify-content: center;
                font-weight: bold;
                font-size: 14px;
                border-radius: 6px;
                border: 1px solid #444;
                font-family: 'Segoe UI', Arial, sans-serif;
                transition: background 0.1s, transform 0.1s, opacity 0.1s;
            `;
            rowDiv.appendChild(keyBtn);
        });
        kbContainer.appendChild(rowDiv);
    });
    document.body.appendChild(kbContainer);


    // --- 2. MENU ĐIỀU CHỈNH (ẨN/HIỆN BẰNG PHÍM DẤU CHẤM) ---
    const menu = document.createElement('div');
    menu.style.cssText = `
        position: fixed;
        top: 25%;
        left: 50%;
        transform: translate(-50%, -25%);
        background: #1e1e1e;
        color: #fff;
        padding: 20px;
        border-radius: 12px;
        border: 1px solid #444;
        z-index: 100000;
        display: none;
        flex-direction: column;
        gap: 15px;
        font-family: 'Segoe UI', Arial, sans-serif;
        box-shadow: 0 10px 25px rgba(0,0,0,0.7);
        width: 240px;
    `;
    menu.innerHTML = `
        <h4 style="margin: 0 0 5px 0; text-align: center; font-size: 16px; color: #4caf50;">Cài Đặt Bàn Phím Vỏ</h4>
        
        <label style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
            Màu nút:
            <input type="color" id="key-color-picker" value="#2a2a2a" style="border:none; background:none; cursor:pointer;">
        </label>
        
        <label style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
            Màu chữ:
            <input type="color" id="text-color-picker" value="#ffffff" style="border:none; background:none; cursor:pointer;">
        </label>

        <div style="border-top: 1px solid #333; padding-top: 10px;">
            <p style="margin: 0 0 8px 0; font-size: 13px; color: #aaa;">Di chuyển vị trí:</p>
            <div style="display: flex; gap: 4px; justify-content: space-between;">
                <button id="move-left" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Trái</button>
                <button id="move-right" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Phải</button>
                <button id="move-up" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Lên</button>
                <button id="move-down" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Xuống</button>
            </div>
        </div>
        <p style="margin: 5px 0 0 0; font-size: 11px; color: #777; text-align: center;">Ấn phím [ . ] để đóng menu này</p>
    `;
    document.body.appendChild(menu);


    // --- 3. LOGIC HOẠT ĐỘNG ---

    // Nhấn phím "." để mở menu
    window.addEventListener('keydown', (e) => {
        if (e.key === '.') {
            if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return;
            e.preventDefault();
            menu.style.display = menu.style.display === 'none' ? 'flex' : 'none';
        }
    });

    // Đồng bộ sáng/tối khi bạn bấm phím thật
    const toggleHighlight = (keyStr, isPressed) => {
        let targetKey = keyStr.toLowerCase();
        if (targetKey === ' ') targetKey = 'space';
        
        const keyVisual = kbContainer.querySelector(`.kb-key[data-key="${targetKey}"]`);
        if (keyVisual) {
            keyVisual.style.opacity = isPressed ? '0.5' : '1';
            keyVisual.style.transform = isPressed ? 'scale(0.92)' : 'scale(1)';
        }
    };
    window.addEventListener('keydown', (e) => toggleHighlight(e.key, true));
    window.addEventListener('keyup', (e) => toggleHighlight(e.key, false));

    // Đổi màu sắc từ Menu
    menu.querySelector('#key-color-picker').addEventListener('input', (e) => {
        kbContainer.querySelectorAll('.kb-key').forEach(k => k.style.background = e.target.value);
    });
    menu.querySelector('#text-color-picker').addEventListener('input', (e) => {
        kbContainer.querySelectorAll('.kb-key').forEach(k => k.style.color = e.target.value);
    });

    // Di chuyển cụm phím ảo độc lập bằng nút trong menu
    let currentLeft = window.innerWidth / 2;
    let currentBottom = 30;
    kbContainer.style.transform = 'none';
    kbContainer.style.left = `${currentLeft - 85}px`;

    const moveStep = 25; 
    menu.querySelector('#move-left').addEventListener('click', () => { currentLeft -= moveStep; kbContainer.style.left = `${currentLeft}px`; });
    menu.querySelector('#move-right').addEventListener('click', () => { currentLeft += moveStep; kbContainer.style.left = `${currentLeft}px`; });
    menu.querySelector('#move-up').addEventListener('click', () => { currentBottom += moveStep; kbContainer.style.bottom = `${currentBottom}px`; });
    menu.querySelector('#move-down').addEventListener('click', () => { currentBottom -= moveStep; kbContainer.style.bottom = `${currentBottom}px`; });

})();