Drawaria Sky Sanctuary Zone

Professional recreation of Sky Sanctuary Zone with detailed elements

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Drawaria Sky Sanctuary Zone
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Professional recreation of Sky Sanctuary Zone with detailed elements
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    function waitForCanvas() {
        if (document.querySelector('canvas')) {
            initSkySanctuary();
        } else {
            setTimeout(waitForCanvas, 1000);
        }
    }

    function initSkySanctuary() {
        const canvas = document.querySelector('canvas');
        const ctx = canvas.getContext('2d');

        const colors = {
            skyTop: '#4080c0',        // Darker, more realistic sky
            skyBottom: '#80b0e0',     // Lighter blue
            clouds: '#ffffff',
            cloudShadow: '#e0e0e0',   // Grayer shadow
            pillarLight: '#f0e68c',    // Khaki
            pillarMid: '#d4c4a8',     // Light Brown
            pillarShade: '#a08060',    // Darker Brown
            pillarDark: '#604020',    // Very Dark Brown
            grass: '#30a040',         // Darker, richer green
            grassShade: '#208030',    // Even darker green
            stone: '#c0c0c0',        // Silver
            stoneDark: '#808080',     // Gray
            decorGold: '#ffd700',
            ruins: '#b0a080',        // More muted ruins
            vineGreen: '#2e8b57',     // Sea Green
            vineDark: '#196127',      // Darker Sea Green
            castleLight: 'rgba(200, 190, 170, 0.4)',  // Slightly more opaque
            castleDark: 'rgba(150, 140, 120, 0.3)',   // Darker and more opaque
            leaves: '#388e3c',       // Darker Green
            flowerGold: '#ffd700',
            flowerWhite: '#ffffff',
            particle: 'rgba(255, 255, 255, 0.6)' // White with some opacity
        };

        // Utility function for creating gradients
        function createVerticalGradient(ctx, topColor, bottomColor, startY, endY) {
            const gradient = ctx.createLinearGradient(0, startY, 0, endY);
            gradient.addColorStop(0, topColor);
            gradient.addColorStop(1, bottomColor);
            return gradient;
        }



        class ParallaxElement {
            constructor(x, y, speed, depth) {
                this.x = x;
                this.y = y;
                this.speed = speed;
                this.depth = depth;
                this.originalX = x;  // Store original X for resetting
                this.originalY = y;  // Store original Y for parallax relative to the canvas bottom.
            }

            update(deltaTime, cameraX = 0) {
                // Parallax scrolling.
                this.x = this.originalX - cameraX * this.depth;

                // Wrap around when going off-screen.
                if (this.x + 1000 < cameraX * this.depth ) {
                    this.x = this.originalX + canvas.width;  // Reset at the far right.
                    this.originalX = this.x;  // *Important*: Update originalX
                }
            }

            reset() {
              this.x = this.originalX;
              this.y = this.originalY;
            }
        }



        class DetailedPillar extends ParallaxElement {
            constructor(x, y, width, height, depth) {
                super(x, y, 0.04, depth); // Increased speed slightly
                this.width = width;
                this.height = height;
                this.decorations = this.generateDecorations();
                this.cracks = this.generateCracks(); // Add cracks
            }

            generateDecorations() {
                const decorations = [];
                const numDecorations = Math.floor(5 + Math.random() * 5); // More decorations
                for (let i = 0; i < numDecorations; i++) {
                    decorations.push({
                        x: Math.random() * this.width,
                        y: Math.random() * this.height,
                        size: 7 + Math.random() * 8, // Slightly larger sizes
                        type: Math.random() < 0.7 ? 'circle' : 'square' // Different shapes
                    });
                }
                return decorations;
            }

            generateCracks() {
                const cracks = [];
                const numCracks = Math.floor(2 + Math.random() * 4); // Add a few cracks
                for (let i = 0; i < numCracks; i++) {
                    cracks.push({
                        startX: this.width * (0.2 + Math.random() * 0.6), // Random within pillar
                        startY: this.height * (0.1 + Math.random() * 0.8),
                        length: 20 + Math.random() * 40,
                        angle: (Math.random() - 0.5) * Math.PI / 4 // +/- 45 degrees
                    });
                }
                return cracks;
            }

            draw(ctx) {
                const perspective = 0.4 * this.depth; // Increased perspective
                const topWidth = this.width * (1 - perspective);

                this.drawPillarBody(ctx, topWidth);
                this.drawPillarDetails(ctx, topWidth);
                this.drawDecorations(ctx);
                this.drawCracks(ctx); // Draw cracks
                this.drawCapital(ctx, topWidth);
            }


            drawPillarBody(ctx, topWidth) {
              //  console.log(`Pillar: x=${this.x}, y=${this.y}, width=${this.width}, height=${this.height}`);
                ctx.beginPath();
                ctx.moveTo(this.x, this.y); // Start from the top-left
                ctx.lineTo(this.x + this.width, this.y); // Top-right
                ctx.lineTo(this.x + this.width/2 + topWidth/2, this.y - this.height); // Top perspective point
                ctx.lineTo(this.x + this.width/2 - topWidth/2, this.y- this.height); // Bottom perspective point
                ctx.closePath();


                const gradient = ctx.createLinearGradient(this.x, this.y - this.height, this.x, this.y);
                gradient.addColorStop(0, colors.pillarLight); // Lighter at the top
                gradient.addColorStop(0.5, colors.pillarMid);
                gradient.addColorStop(1, colors.pillarShade); // Darker at the bottom
                ctx.fillStyle = gradient;
                ctx.globalAlpha = 0.8; // Slightly more opaque
                ctx.fill();
                ctx.globalAlpha = 1;

                // Add shadow
                ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; // Dark, semi-transparent shadow
                ctx.beginPath();
                ctx.moveTo(this.x + this.width, this.y);
                ctx.lineTo(this.x + this.width * 1.1, this.y - 20); // Shadow extends slightly
                ctx.lineTo(this.x + this.width/2 + topWidth/2 + 20, this.y - this.height - 10);
                ctx.lineTo(this.x + this.width/2 + topWidth/2, this.y - this.height);
                ctx.closePath();
                ctx.fill();
            }

            drawPillarDetails(ctx, topWidth) {
                for (let i = 0.2; i <= 0.8; i += 0.2) {
                    ctx.fillStyle = colors.pillarShade;
                    ctx.beginPath();
                    ctx.moveTo(this.x + this.width * i, this.y);
                    ctx.lineTo(this.x + this.width * (i + 0.05), this.y);
                    ctx.lineTo(this.x + this.width/2 + topWidth * (i - 0.5) + topWidth * 0.025, this.y-this.height);
                    ctx.lineTo(this.x + this.width/2 + topWidth * (i - 0.5), this.y-this.height);
                    ctx.closePath();
                    ctx.fill();
                }
            }

            drawDecorations(ctx) {

                this.decorations.forEach(dec => {
                    ctx.fillStyle = colors.decorGold;
                    if (dec.type === 'circle') {
                        ctx.beginPath();
                        ctx.arc(this.x + dec.x, this.y - this.height + dec.y, dec.size, 0, Math.PI * 2);
                        ctx.fill();
                    } else { // Square
                        ctx.fillRect(this.x + dec.x - dec.size / 2, this.y - this.height + dec.y - dec.size / 2, dec.size, dec.size);
                    }
                });
            }


            drawCracks(ctx) {
                ctx.strokeStyle = colors.pillarDark;
                ctx.lineWidth = 2;
                this.cracks.forEach(crack => {
                    ctx.beginPath();
                    ctx.moveTo(this.x + crack.startX, this.y - this.height + crack.startY);
                    ctx.lineTo(this.x + crack.startX + Math.cos(crack.angle) * crack.length,
                               this.y - this.height + crack.startY + Math.sin(crack.angle) * crack.length);
                    ctx.stroke();
                });
            }

            drawCapital(ctx, topWidth) {
                const capitalHeight = this.height * 0.15; // Larger capital
                ctx.fillStyle = colors.stone;

                ctx.beginPath();
                ctx.moveTo(this.x - this.width * 0.3, this.y - this.height); // Wider
                ctx.lineTo(this.x + this.width * 1.3, this.y - this.height); // Wider
                ctx.lineTo(this.x + this.width / 2 + topWidth *1.2, this.y - this.height - capitalHeight);
                ctx.lineTo(this.x + this.width / 2 - topWidth*1.2, this.y - this.height - capitalHeight);
                ctx.closePath();
                ctx.fill();

                // Add detailed carvings to the capital
                ctx.fillStyle = colors.decorGold;
                for (let i = 0; i < 7; i++) { // More carvings
                    const carvingX = this.x + this.width * (-0.2 + i * 0.2);
                    const carvingY = this.y - this.height - capitalHeight / 2;
                    ctx.beginPath();

                    if(i % 2 === 0){
                        ctx.arc(carvingX, carvingY, capitalHeight / 5, 0, Math.PI * 2);
                    } else {
                        ctx.moveTo(carvingX - capitalHeight/6, carvingY);
                        ctx.lineTo(carvingX, carvingY - capitalHeight/4);
                        ctx.lineTo(carvingX + capitalHeight/6, carvingY);
                        ctx.closePath();

                    }
                    ctx.fill();
                }
            }
        }



        class Cloud extends ParallaxElement {
            constructor(x, y, size, depth) {
                super(x, y, 0.015, depth); // Slightly faster clouds
                this.size = size;
                this.segments = this.generateSegments();
            }

            generateSegments() {
                const segments = [];
                const numSegments = Math.floor(4 + Math.random() * 3); // Varying number of segments
                for (let i = 0; i < numSegments; i++) {
                    segments.push({
                        xOffset: (Math.random() - 0.5) * this.size * 2.5, // Wider spread
                        yOffset: (Math.random() - 0.5) * this.size * 1.5, // More vertical variation
                        size: this.size * (0.6 + Math.random() * 0.4) // Slightly larger segments
                    });
                }
                return segments;
            }

            draw(ctx) {
                // Shadow first (darker and offset)
                ctx.fillStyle = colors.cloudShadow;
                this.segments.forEach(seg => {
                    ctx.beginPath();
                    ctx.arc(this.x + seg.xOffset + 10, this.y + seg.yOffset + 15, // Shadow offset
                           seg.size * 1.1, 0, Math.PI * 2); // Slightly larger shadow
                    ctx.fill();
                });

                // Then the cloud itself
                ctx.fillStyle = colors.clouds;
                this.segments.forEach(seg => {
                    ctx.beginPath();
                    ctx.arc(this.x + seg.xOffset, this.y + seg.yOffset,
                           seg.size, 0, Math.PI * 2);
                    ctx.fill();
                });
            }
        }


       class BackgroundCastle extends ParallaxElement {
          constructor(x, y, width, height, depth) {
            super(x, y, 0.008, depth);  //Slightly increased speed
            this.width = width;
            this.height = height;
            this.towers = this.generateTowers(); // Generate towers
            this.windows = this.generateWindows();  // Generate windows
          }
          generateTowers() {
            const towers = [];
            const numTowers = Math.floor(4 + Math.random() * 3); // 4-6 towers
            for (let i = 0; i < numTowers; i++) {
              towers.push({
                x: this.width * (0.1 + i * 0.2 + (Math.random() - 0.5) * 0.1), // Some x variation
                height: this.height * (0.4 + Math.random() * 0.3), // Varying heights
                width: 20 + Math.random() * 20, // Varying widths
                roofType: Math.random() < 0.6 ? 'pointed' : 'flat' // Different roof types
              });
            }
              return towers;
          }

           generateWindows(){
              const windows = [];
              const numWindows = Math.floor(10 + Math.random() * 15);
               for(let i = 0; i < numWindows; i++){
                  windows.push({
                    x: this.width * Math.random(),
                    y: this.height * (0.2 + Math.random() * 0.6),
                    size: 4 + Math.random() * 4
                  });
               }
             return windows;
           }

          draw(ctx) {

            this.drawMainStructure(ctx);
            this.drawTowers(ctx);
            this.drawDetails(ctx);
            this.drawWindows(ctx);
          }


            drawMainStructure(ctx) {
              ctx.fillStyle = colors.castleLight;
              ctx.beginPath();
              ctx.moveTo(this.x, this.y);
              ctx.lineTo(this.x + this.width, this.y);
              ctx.lineTo(this.x + this.width, this.y - this.height * 0.7); // Increased height
              ctx.lineTo(this.x + this.width * 0.8, this.y - this.height * 0.8);
              ctx.lineTo(this.x + this.width * 0.6, this.y - this.height);  //Main point
              ctx.lineTo(this.x + this.width * 0.4, this.y - this.height * 0.9);
              ctx.lineTo(this.x + this.width * 0.2, this.y - this.height * 0.8);
              ctx.lineTo(this.x, this.y - this.height * 0.7);
              ctx.closePath();
              ctx.fill();


              // Add a subtle gradient for depth
              const gradient = ctx.createLinearGradient(this.x, this.y - this.height, this.x, this.y);
              gradient.addColorStop(0, 'rgba(255, 255, 255, 0.2)'); // Lighter at the top
              gradient.addColorStop(1, 'rgba(0, 0, 0, 0.1)');    // Darker at the bottom
              ctx.fillStyle = gradient;
              ctx.fill();
          }

          drawTowers(ctx) {
                ctx.fillStyle = colors.castleLight;
                this.towers.forEach(tower => {
                const towerX = this.x + tower.x;
                ctx.beginPath();
                ctx.moveTo(towerX, this.y);
                ctx.lineTo(towerX + tower.width, this.y);
                ctx.lineTo(towerX + tower.width, this.y - tower.height);
                if (tower.roofType === 'pointed') {
                    ctx.lineTo(towerX + tower.width / 2, this.y - tower.height * 1.2); // Pointed roof
                    ctx.lineTo(towerX, this.y - tower.height);
                } else {
                    ctx.lineTo(towerX, this.y - tower.height); // Flat roof
                    // Add battlements for flat roofs
                    for (let i = 0; i < tower.width; i += 10) {
                        ctx.fillRect(towerX + i, this.y - tower.height - 5, 5, 5);
                    }
                }

                ctx.closePath();
                ctx.fill();
            });
          }

          drawDetails(ctx) {
            ctx.fillStyle = colors.castleDark;
            for (let i = 0; i < this.width; i += 40) { // More details
              ctx.fillRect(this.x + i, this.y - this.height * 0.4, 30, this.height * 0.3);
            }
          }

           drawWindows(ctx){
              ctx.fillStyle = 'rgba(255, 255, 0, 0.4)'; // Yellowish glow
              this.windows.forEach(window => {
                  ctx.fillRect(this.x + window.x, this.y - window.y, window.size, window.size);
              });
           }
        }

        class Vegetation {
            constructor(x, y, type) {
                this.x = x;
                this.y = y;
                this.type = type;
                this.swayOffset = Math.random() * Math.PI * 2;
                this.leafDetails = this.generateLeafDetails(); // For vines
            }

            generateLeafDetails() {
                if (this.type !== 'vine') return [];
                return Array(5).fill().map(() => ({
                    offset: Math.random() * 20 - 10, // x offset for each leaf
                    size: 4 + Math.random() * 4 // Leaf size variation
                }));
            }

            draw(ctx, time) {
                switch(this.type) {
                    case 'vine':
                        this.drawVine(ctx, time);
                        break;
                    case 'flower':
                        this.drawFlower(ctx);
                        break;
                    case 'bush':
                        this.drawBush(ctx);
                        break;
                }
            }

            drawVine(ctx, time) {
                const sway = Math.sin(time * 0.0015 + this.swayOffset) * 8; // Increased sway
                ctx.strokeStyle = colors.vineGreen;
                ctx.lineWidth = 3;
                ctx.beginPath();
                ctx.moveTo(this.x, this.y);

                // More realistic vine curves
                for (let i = 0; i < 5; i++) {
                    const curveX = this.x + sway * (i % 2 ? 1.2 : -0.8); // More variation in sway
                    const curveY = this.y - i * 25; // Taller vines
                    ctx.quadraticCurveTo(
                        curveX, curveY,
                        this.x + sway * (i % 2 ? 0.5 : -0.3), this.y - (i + 1) * 25 // Vary next point
                    );
                }
                ctx.stroke();


                // Leaves with more detail
                 for (let i = 1; i < 5; i++) {
                    ctx.fillStyle = colors.leaves;
                    const leafX = this.x + sway * (i % 2 ? 1 : -1) + this.leafDetails[i-1].offset;
                    const leafY = this.y - i * 25;

                    ctx.beginPath();
                    ctx.ellipse(leafX, leafY,
                                8, this.leafDetails[i-1].size * 2, // Use generated size
                                Math.PI / 4 * (i % 2 ? 1 : -1), 0, Math.PI * 2);
                    ctx.fill();

                    // Add a small line for leaf vein
                    ctx.strokeStyle = colors.vineDark;
                    ctx.lineWidth = 1;
                    ctx.beginPath();
                    ctx.moveTo(leafX, leafY);
                    ctx.lineTo(leafX + 4 * (i % 2 ? 1 : -1), leafY - 4);
                    ctx.stroke();
                }
            }

            drawFlower(ctx) {
                // More detailed flower center
                ctx.fillStyle = colors.flowerGold;
                ctx.beginPath();
                ctx.arc(this.x, this.y, 6, 0, Math.PI * 2); // Larger center
                ctx.fill();

                // More detailed petals
                ctx.fillStyle = colors.flowerWhite;
                for (let i = 0; i < 8; i++) { // More petals
                    const angle = (i / 8) * Math.PI * 2; // Evenly spaced
                    ctx.beginPath();
                    ctx.ellipse(
                        this.x + Math.cos(angle) * 10, // Larger petals
                        this.y + Math.sin(angle) * 10,
                        8, 5, // More elongated petals
                        angle,
                        0, Math.PI * 2
                    );
                    ctx.fill();

                     // Add a small line for petal detail
                    ctx.strokeStyle = colors.vineDark;
                    ctx.lineWidth = 1;
                    ctx.beginPath();
                    ctx.moveTo(this.x + Math.cos(angle) * 10, this.y + Math.sin(angle) * 10);
                    ctx.lineTo(this.x + Math.cos(angle) * 15, this.y + Math.sin(angle) * 15);
                    ctx.stroke();
                }
            }

            drawBush(ctx) {
                ctx.fillStyle = colors.grass;
                for (let i = 0; i < 7; i++) { // More bush segments
                    ctx.beginPath();
                    ctx.arc(
                        this.x + (i - 3) * 12, // Wider bush
                        this.y - Math.abs(i - 3) * 6, // Taller
                        12, // Larger segments
                        0, Math.PI * 2
                    );
                    ctx.fill();
                }

                // Add darker spots for depth
                ctx.fillStyle = colors.grassShade;
                for (let i = 0; i < 3; i++) {
                    ctx.beginPath();
                    ctx.arc(
                        this.x + (Math.random() - 0.5) * 30,
                        this.y - Math.random() * 10,
                        5 + Math.random() * 5, // Random size and position
                        0, Math.PI * 2
                    );
                    ctx.fill();
                }
            }
        }

        class Particle {
            constructor(x, y, size, speed, depth) {
                this.x = x;
                this.y = y;
                this.size = size;
                this.speed = speed;
                this.depth = depth;
                this.alpha = 0.2 + Math.random() * 0.6;  // Random initial opacity.
            }

            update(deltaTime, cameraX) {
                this.x -= this.speed * deltaTime * this.depth;
                this.y += Math.sin(this.x * 0.01) * 0.5;  // Slight wavy movement.
                this.alpha -= 0.005 * deltaTime; // Fade out over time.

                if (this.x < cameraX - this.size || this.alpha <= 0) {
                    this.reset(cameraX);
                }
            }

            reset(cameraX) {
                this.x = cameraX + canvas.width + Math.random() * 200; // Reset beyond the right edge.
                this.y = Math.random() * canvas.height;
                this.size = 2 + Math.random() * 3;
                this.speed = 0.01 + Math.random() * 0.02;
                this.alpha = 0.2 + Math.random() * 0.6;
                this.depth = 0.5 + Math.random() * 0.8;
            }

            draw(ctx) {
              ctx.fillStyle = `rgba(255, 255, 255, ${this.alpha})`;  // Use dynamic alpha.
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
            }
        }



        const pillars = [];
        const clouds = [];
        const castles = [];
        const vegetation = [];
        const particles = [];
        let lastTime = 0;
        let cameraX = 0; // Camera position for parallax

        function initializeScene() {
           // Clear existing elements (important for reset)
            pillars.length = 0;
            clouds.length = 0;
            castles.length = 0;
            vegetation.length = 0;
            particles.length = 0;

            for (let i = 0; i < 8; i++) {
                const depth = 0.6 + Math.random() * 0.4; // Deeper pillars
                pillars.push(new DetailedPillar(
                    200 + i * 500,  // Wider spacing
                    canvas.height - 150, // Pillars anchored to a consistent y-position
                    150,          // Wider pillars
                    400 - depth * 50,
                    depth
                ));
            }

            for (let i = 0; i < 15; i++) { // More clouds
                const depth = 0.3 + Math.random() * 0.4; // Wider depth range
                clouds.push(new Cloud(
                    Math.random() * canvas.width,
                    50 + Math.random() * 250, // Taller cloud area
                    40 + Math.random() * 30, // Larger clouds
                    depth
                ));
            }

            for (let i = 0; i < 3; i++) {
              const depth = 0.2 + (i * 0.15); // Increased depth difference
              castles.push(new BackgroundCastle(
                300 + i * 1200, // Increased spacing
                canvas.height - 150,  // Consistent y-position for the castle base
                600,        // Much wider castles
                450,        // Taller castles
                depth
              ));
            }


            for (let i = 0; i < 40; i++) { // More vegetation
                vegetation.push(new Vegetation(
                    Math.random() * canvas.width,
                    canvas.height - 100 + Math.random() * 30, // Consistent y-range
                    ['vine', 'flower', 'bush'][Math.floor(Math.random() * 3)]
                ));
            }

            for (let i = 0; i < 50; i++) { // Add particles
                particles.push(new Particle(
                    Math.random() * canvas.width,
                    Math.random() * canvas.height,
                    2 + Math.random() * 3,
                    0.01 + Math.random() * 0.02,
                    0.5 + Math.random()* 0.8
                ));
            }
            // Reset camera
            cameraX = 0;
        }

       function drawBackground(ctx) {
            const gradient = createVerticalGradient(ctx, colors.skyTop, colors.skyBottom, 0, canvas.height);
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }

        function drawGround(ctx) {
            const platformHeight = 120; // Slightly taller
            const gradient = createVerticalGradient(ctx, colors.stone, colors.stoneDark, canvas.height - platformHeight, canvas.height);
            ctx.fillStyle = gradient;
            ctx.fillRect(0, canvas.height - platformHeight, canvas.width, platformHeight);

            // Ground details (more detailed and varied)
            for (let i = 0; i < canvas.width; i += 25) {
                ctx.fillStyle = colors.grass;
                ctx.beginPath();
                ctx.moveTo(i, canvas.height - platformHeight);
                ctx.lineTo(i + 15 + Math.random() * 10, canvas.height - platformHeight); // Varying widths
                ctx.lineTo(i + 7.5 + Math.random() * 5, canvas.height - platformHeight - (20 + Math.random() * 10)); // Varying heights
                ctx.closePath();
                ctx.fill();
            }

             // Add some cracks in the stone
            ctx.strokeStyle = colors.stoneDark;
            ctx.lineWidth = 2;
            for (let i = 0; i < canvas.width; i += 50 + Math.random() * 50) {
                ctx.beginPath();
                ctx.moveTo(i, canvas.height - platformHeight + 5);
                ctx.lineTo(i + (Math.random() - 0.5) * 20, canvas.height - platformHeight + 20 + Math.random() * 10);
                ctx.stroke();
            }
        }



        function drawScene(timestamp) {
            const deltaTime = timestamp - lastTime;
            lastTime = timestamp;

             // Camera movement (smooth)
            cameraX += deltaTime * 0.05;

            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // Background and elements, with parallax
            drawBackground(ctx);

             castles.forEach(castle => {
                castle.update(deltaTime, cameraX);
                castle.draw(ctx);
            });

            clouds.forEach(cloud => {
                cloud.update(deltaTime, cameraX);
                cloud.draw(ctx);
            });


            pillars.sort((a, b) => b.depth - a.depth); // Depth sorting
            pillars.forEach(pillar => {
                pillar.update(deltaTime, cameraX);  // Pass cameraX for parallax.
                pillar.draw(ctx);
            });

             drawGround(ctx);

             vegetation.forEach(plant => {
                plant.x = plant.x - cameraX * 0.1;
                plant.draw(ctx, timestamp);
                plant.x = plant.x + cameraX * 0.1;
            });


            particles.forEach(particle => {
                particle.update(deltaTime, cameraX);
                particle.draw(ctx);
            });


            requestAnimationFrame(drawScene);
        }


        // UI controls
        function createControls() {
            const controlPanel = document.createElement('div');
            controlPanel.style.cssText = `
                position: fixed;
                top: 10px;
                right: 10px;
                z-index: 9999;
                background: rgba(0, 0, 0, 0.7);
                padding: 10px;
                border-radius: 5px;
                color: white;
                font-family: sans-serif;
            `;

            const startButton = document.createElement('button');
            startButton.textContent = 'Draw Sky Sanctuary';
            startButton.style.cssText = 'padding: 8px 12px; margin-right: 5px; cursor: pointer;';
            startButton.onclick = () => {
                initializeScene();
                requestAnimationFrame(drawScene);
            };

            const resetButton = document.createElement('button');
            resetButton.textContent = 'Reset Scene';
            resetButton.style.cssText = 'padding: 8px 12px; cursor: pointer;';
            resetButton.onclick = () => {
              ctx.clearRect(0, 0, canvas.width, canvas.height);
              initializeScene(); // Re-initialize, don't just clear arrays.
              requestAnimationFrame(drawScene); // start drawing again

            };



            controlPanel.appendChild(startButton);
            controlPanel.appendChild(resetButton);
            document.body.appendChild(controlPanel);
        }

        createControls();
    }

    waitForCanvas();
})();