3D Solar System Simulation with Avatar for drawaria.online

Remake of Cosmic Galaxy this one Injects a 3D solar system simulation with your avatar

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         3D Solar System Simulation with Avatar for drawaria.online
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Remake of Cosmic Galaxy this one Injects a 3D solar system simulation with your avatar
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://drawaria.online/avatar/cache/86e33830-86ea-11ec-8553-bff27824cf71.jpg
// ==/UserScript==

(function() {
    'use strict';

    // Create a container for the canvas
    const container = document.createElement('div');
    container.id = 'canvas-container';
    container.style.width = '100%';
    container.style.height = '100%';
    container.style.position = 'fixed';
    container.style.top = '0';
    container.style.left = '0';
    container.style.zIndex = '9999'; // You may adjust z-index depending on Drawaria's layout
    document.body.appendChild(container);

    // Create an info div
    const info = document.createElement('div');
    info.className = 'info';
    info.style.position = 'absolute';
    info.style.top = '10px';
    info.style.left = '10px';
    info.style.color = '#fff';
    info.style.fontFamily = 'sans-serif';
    info.style.zIndex = '10000';
    info.textContent = '3D Solar System Simulation';
    document.body.appendChild(info);

    // Include Three.js library from CDN
    const script = document.createElement('script');
    script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js';
    script.onload = function() {
        // Create scene, camera, and renderer
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
        camera.position.set(0, 100, 250);

        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        container.appendChild(renderer.domElement);

        // Add ambient light and a point light to simulate the sun's light
        const ambientLight = new THREE.AmbientLight(0x222222);
        scene.add(ambientLight);

        const sunLight = new THREE.PointLight(0xffffff, 2, 1500);
        scene.add(sunLight);

        // Utility function to create a planet mesh
        function createPlanet(radius, segments, color, textureUrl) {
            const geometry = new THREE.SphereGeometry(radius, segments, segments);
            const materialOptions = { color: color };
            if (textureUrl) {
                const texture = new THREE.TextureLoader().load(textureUrl);
                materialOptions.map = texture;
            }
            const material = new THREE.MeshStandardMaterial(materialOptions);
            const mesh = new THREE.Mesh(geometry, material);
            return mesh;
        }

        // Create the Sun
        const sunGeometry = new THREE.SphereGeometry(16, 32, 32);
        const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xFDB813 });
        const sun = new THREE.Mesh(sunGeometry, sunMaterial);
        scene.add(sun);
        sunLight.position.copy(sun.position);

        // Array to hold each planet's pivot and orbital speed
        const planets = [];

        // Define planet parameters: name, distance from sun, radius, color, and orbital speed
        const planetData = [
            { name: "Mercury", distance: 30, radius: 3, color: 0x888888, speed: 0.04 },
            { name: "Venus",   distance: 45, radius: 4, color: 0xEEDC82, speed: 0.03 },
            { name: "Earth",   distance: 60, radius: 4.2, color: 0x2A75B3, speed: 0.02 },
            { name: "Mars",    distance: 75, radius: 3.5, color: 0xB22222, speed: 0.017 }
        ];

        planetData.forEach(data => {
            // Create a pivot object at the sun's position to simulate orbital rotation
            const pivot = new THREE.Object3D();
            scene.add(pivot);

            // Create the planet mesh and position it along the x-axis
            const planet = createPlanet(data.radius, 32, data.color);
            planet.position.x = data.distance;
            pivot.add(planet);

            // Save the pivot and orbital speed for animation
            planets.push({ pivot: pivot, speed: data.speed });

            // (Optional) Create a visual orbit path as a thin ring
            const orbitGeometry = new THREE.RingGeometry(data.distance - 0.2, data.distance + 0.2, 64);
            const orbitMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, side: THREE.DoubleSide, transparent: true, opacity: 0.3 });
            const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial);
            orbit.rotation.x = Math.PI / 2;
            scene.add(orbit);
        });

        // Create a starry background using a particle system
        function addStars() {
            const starGeometry = new THREE.BufferGeometry();
            const starCount = 10000;
            const starVertices = [];
            for (let i = 0; i < starCount; i++) {
                const x = THREE.MathUtils.randFloatSpread(2000);
                const y = THREE.MathUtils.randFloatSpread(2000);
                const z = THREE.MathUtils.randFloatSpread(2000);
                starVertices.push(x, y, z);
            }
            starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
            const starMaterial = new THREE.PointsMaterial({ color: 0xffffff });
            const stars = new THREE.Points(starGeometry, starMaterial);
            scene.add(stars);
        }
        addStars();

        // Handle responsiveness: resize renderer and update camera aspect ratio
        window.addEventListener("resize", () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // Avatar Properties
        const avatar = {
            position: { x: 0, y: 0, z: 0 },
            velocity: { x: 0, y: 0, z: 0 },
            maxSpeed: 15,
            acceleration: 0.25,
            friction: 0.985,
            angle: 0,
            element: createAvatarElement()
        };

        function createAvatarElement() {
            const img = new Image();
            img.style.position = 'absolute';
            img.style.width = '60px';
            img.style.height = '60px';
            img.style.transformOrigin = 'center';
            img.style.zIndex = '10000'; // High z-index to ensure it's above other elements
            document.body.appendChild(img);
            return img;
        }

        // Fetch the real avatar URL
        function fetchAvatarURL() {
            const avatarImageElement = document.querySelector('#selfavatarimage');
            if (avatarImageElement) {
                avatar.element.src = avatarImageElement.src;
            } else {
                console.error('Avatar image element not found.');
            }
        }

        // Call the function to fetch the avatar URL
        fetchAvatarURL();

        // Movement System
        const keys = {};
        window.addEventListener('keydown', e => keys[e.key] = true);
        window.addEventListener('keyup', e => keys[e.key] = false);

        function handleMovement() {
            // Acceleration
            if (keys.ArrowRight) avatar.velocity.x += avatar.acceleration;
            if (keys.ArrowLeft) avatar.velocity.x -= avatar.acceleration;
            if (keys.ArrowDown) avatar.velocity.y += avatar.acceleration;
            if (keys.ArrowUp) avatar.velocity.y -= avatar.acceleration;

            // Velocity limits
            avatar.velocity.x = Math.max(-avatar.maxSpeed, Math.min(avatar.velocity.x, avatar.maxSpeed));
            avatar.velocity.y = Math.max(-avatar.maxSpeed, Math.min(avatar.velocity.y, avatar.maxSpeed));

            // Apply friction
            avatar.velocity.x *= avatar.friction;
            avatar.velocity.y *= avatar.friction;

            // Update position
            avatar.position.x += avatar.velocity.x;
            avatar.position.y += avatar.velocity.y;

            // Update avatar display
            avatar.element.style.left = `${avatar.position.x}px`;
            avatar.element.style.top = `${avatar.position.y}px`;

            // Calculate rotation angle
            avatar.angle = Math.atan2(avatar.velocity.y, avatar.velocity.x);
            avatar.element.style.transform = `rotate(${avatar.angle}rad)`;
        }

        // Animation loop to render the scene and update orbital movements
        function animate() {
            requestAnimationFrame(animate);

            // Rotate each planet's pivot to simulate orbiting around the sun
            planets.forEach(item => {
                item.pivot.rotation.y += item.speed;
            });

            // Optional: slowly rotate the sun
            sun.rotation.y += 0.002;

            // Handle avatar movement
            handleMovement();

            renderer.render(scene, camera);
        }
        animate();
    };
    document.head.appendChild(script);
})();