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 เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey to install this script.

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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`; });

})();