🎮ArcadeLab

Sprunki OC: Vomit - Interactive Stage

by AstroLegend76
323 lines11.0 KB
▶ Play
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sprunki OC: Vomit - Interactive Stage</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        
        body {
            background: #4A90E2; /* The solid blue sky from Axel's Frontier */
            overflow: hidden;
            font-family: 'Courier New', Courier, monospace;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }

        /* The minimalist spooky frontier world */
        #stage {
            position: relative;
            width: 800px;
            height: 500px;
            background: #5499C7;
            border: 4px solid #1A252C;
            overflow: hidden;
            border-radius: 12px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.4);
        }

        /* Scattered pale grass lumps */
        .grass-lump {
            position: absolute;
            bottom: 20px;
            width: 40px;
            height: 15px;
            background: #82E0AA;
            border-radius: 50% 50% 0 0;
            opacity: 0.7;
        }
        .gl1 { left: 15%; width: 50px; }
        .gl2 { left: 45%; height: 25px; }
        .gl3 { right: 20%; width: 60px; }

        /* Character Wrapper */
        #character-container {
            position: absolute;
            bottom: 60px;
            left: 50%;
            transform: translateX(-50%);
            cursor: pointer;
            display: flex;
            flex-direction: column;
            align-items: center;
            animation: float 3s ease-in-out infinite;
        }

        @keyframes float {
            0%, 100% { transform: translate(-50%, 0px); }
            50% { transform: translate(-50%, -15px); }
        }

        /* 2D Sprunki OC Geometric Construction */
        #head {
            width: 120px;
            height: 120px;
            background: #F4D03F;
            border: 5px solid #1A252C;
            border-radius: 50%;
            position: relative;
            transition: all 0.1s ease;
            z-index: 2;
        }

        #body-triangle {
            width: 0;
            height: 0;
            border-left: 70px solid transparent;
            border-right: 70px solid transparent;
            border-bottom: 130px solid #F4D03F;
            position: relative;
            margin-top: -10px;
            z-index: 1;
            filter: drop-shadow(0px 5px 0px #1A252C) drop-shadow(5px 0px 0px #1A252C) drop-shadow(-5px 0px 0px #1A252C);
        }

        /* Glowing Neon Headphones */
        .headphones {
            position: absolute;
            width: 140px;
            height: 140px;
            border: 8px solid #58D68D;
            border-bottom: transparent;
            border-radius: 50%;
            top: -10px;
            left: -10px;
            box-shadow: 0 0 15px #58D68D, inset 0 0 15px #58D68D;
            pointer-events: none;
        }

        /* Faces (Phase 1 Nausea vs Phase 2 Vomit) */
        .face {
            position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
        }

        /* Phase 1: Dizzy/Sick Eyes and Mouth */
        .p1-mouth {
            position: absolute;
            bottom: 25px;
            left: 50%;
            transform: translateX(-50%);
            width: 30px;
            height: 10px;
            border-top: 4px solid #1A252C;
            border-radius: 50%;
        }

        /* Inside Triangle Face */
        #inner-face {
            position: absolute;
            width: 50px;
            height: 50px;
            background: #D4AC0D;
            border: 3px solid #1A252C;
            border-radius: 50%;
            bottom: -110px;
            left: -25px;
            z-index: 3;
        }

        /* PHASE 2 ACTIVE STATES */
        .phase2 #head { background: #F1C40F; transform: scale(1.05); }
        .phase2 .p1-mouth { display: none; }
        
        /* Huge open vomit mouth */
        .p2-mouth {
            display: none;
            position: absolute;
            bottom: 15px;
            left: 50%;
            transform: translateX(-50%);
            width: 45px;
            height: 45px;
            background: #1A252C;
            border-radius: 50%;
        }
        .phase2 .p2-mouth { display: block; }

        /* ANIMATED PIXEL VOMIT STREAM */
        .vomit-stream {
            display: none;
            position: absolute;
            left: 60px;
            top: 55px;
            width: 250px;
            height: 40px;
            background: linear-gradient(90deg, #58D68D, #2ECC71);
            z-index: 10;
            transform-origin: left center;
            animation: puke-blast 0.15s infinite alternate;
            box-shadow: 0 0 20px #58D68D;
            clip-path: polygon(0 40%, 100% 0, 100% 100%, 0 60%);
        }
        .phase2 .vomit-stream { display: block; }

        /* Secondary stream from triangle body face */
        #v-stream-2 {
            top: 175px;
            left: 30px;
            width: 180px;
            height: 25px;
        }

        @keyframes puke-blast {
            0% { transform: scaleY(1) rotate(2deg); }
            100% { transform: scaleY(1.2) rotate(-2deg); }
        }

        /* Instructions Text */
        #prompt {
            position: absolute;
            top: 20px;
            width: 100%;
            text-align: center;
            color: #1A252C;
            font-weight: bold;
            font-size: 1.2rem;
            text-transform: uppercase;
            letter-spacing: 2px;
        }
    </style>
</head>
<body>

    <div id="stage">
        <div id="prompt">Click Character to Trigger Phase 2</div>
        
        <!-- Frontier Grass -->
        <div class="grass-lump gl1"></div>
        <div class="grass-lump gl2"></div>
        <div class="grass-lump gl3"></div>

        <!-- Sprunki Character Structure -->
        <div id="character-container" onclick="togglePhase()">
            <!-- Head Segment -->
            <div id="head">
                <div class="headphones"></div>
                <div class="face">
                    <!-- Sick Eyes -->
                    <div style="position:absolute; left:25px; top:35px; width:12px; height:12px; background:#1A252C; border-radius:50%;"></div>
                    <div style="position:absolute; right:25px; top:35px; width:12px; height:12px; background:#1A252C; border-radius:50%;"></div>
                    <!-- Mouths -->
                    <div class="p1-mouth"></div>
                    <div class="p2-mouth"></div>
                </div>
            </div>

            <!-- Body Triangle Segment -->
            <div id="body-triangle">
                <!-- Duplicate Inner Face inside body -->
                <div id="inner-face">
                    <div style="position:absolute; left:10px; top:12px; width:6px; height:6px; background:#1A252C; border-radius:50%;"></div>
                    <div style="position:absolute; right:10px; top:12px; width:6px; height:6px; background:#1A252C; border-radius:50%;"></div>
                    <div class="p1-mouth" style="bottom:10px; width:15px;"></div>
                    <div class="p2-mouth" style="bottom:5px; width:20px; height:20px;"></div>
                </div>
            </div>

            <!-- Vomit Streams (Triggered in Phase 2) -->
            <div class="vomit-stream" id="v-stream-1"></div>
            <div class="vomit-stream" id="v-stream-2"></div>
        </div>
    </div>

    <script>
        // Setup Web Audio API to create the custom rhythm synth and notes synthetically
        const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        let isPlaying = false;
        let loopInterval;

        function togglePhase() {
            const char = document.getElementById('character-container');
            char.classList.toggle('phase2');
            
            if(!isPlaying) {
                audioCtx.resume();
                playMusicSequence();
                isPlaying = true;
                document.getElementById('prompt').innerText = "PHASE 2 ACTIVE: SPIRALING OUT";
            } else {
                clearInterval(loopInterval);
                isPlaying = false;
                char.classList.remove('phase2');
                document.getElementById('prompt').innerText = "Click Character to Trigger Phase 2";
            }
        }

        // Synthesizes the custom beatbox and the beautiful piano-2026-05-31-17-15.mp3 melodic notes
        function playMusicSequence() {
            let beatStep = 0;
            
            loopInterval = setInterval(() => {
                // Section 1 & 2: "Huh? Huh?" + "Bzzzzzz" + "Ding Ding"
                if (beatStep % 8 === 0 || beatStep % 8 === 2) {
                    // "Huh?" Synth Vocal Punch
                    playTone(120, "sawtooth", 0.15);
                }
                if (beatStep % 8 === 4) {
                    // "Ding!" Chime
                    playTone(880, "sine", 0.1); 
                    playTone(1200, "sine", 0.08); 
                }
                if (beatStep % 8 > 4) {
                    // "Bzzzzzzz / T-t-t-t" Glitch Drum Roll
                    playTone(80, "triangle", 0.05);
                }

                // Section 3: Transitioning into the beautiful piano notes of piano-2026-05-31-17-15.mp3
                // Melodic piano note progression triggers every half measure
                if (beatStep === 0) playPianoNote(261.63); // C4 Note
                if (beatStep === 4) playPianoNote(329.63); // E4 Note
                if (beatStep === 8) playPianoNote(392.00); // G4 Note
                if (beatStep === 12) playPianoNote(493.88); // B4 Note (Melancholy shift)

                beatStep = (beatStep + 1) % 16;
            }, 180); // Corresponds to a fast electronic tempo
        }

        function playTone(freq, type, duration) {
            let osc = audioCtx.createOscillator();
            let gain = audioCtx.createGain();
            osc.type = type;
            osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
            gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
            gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
            osc.connect(gain);
            gain.connect(audioCtx.destination);
            osc.start();
            osc.stop(audioCtx.currentTime + duration);
        }

        // Simulates an echoing acoustic piano note
        function playPianoNote(freq) {
            let osc = audioCtx.createOscillator();
            let gain = audioCtx.createGain();
            osc.type = "sine";
            osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
            gain.gain.setValueAtTime(0.4, audioCtx.currentTime);
            // Long decay tail to mimic standard piano reverb
            gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 1.2);
            osc.connect(gain);
            gain.connect(audioCtx.destination);
            osc.start();
            osc.stop(audioCtx.currentTime + 1.2);
        }
    </script>
</body>
</html>

Game Source: Sprunki OC: Vomit - Interactive Stage

Creator: AstroLegend76

Libraries: none

Complexity: complex (323 lines, 11.0 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: sprunki-oc-vomit-interactive-stage-astrolegend76-mpu002k5" to link back to the original. Then publish at arcadelab.ai/publish.