🎮ArcadeLab

Message from My Bias

by FlashStar31
464 lines17.5 KB
▶ Play
```html
<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Message from My Bias</title>
    <!-- Pixel Font Import -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Mali:wght@400;600;700&family=Press+Start+2P&display=swap" rel="stylesheet">
    
    <style>
        * {
            box-sizing: border-box;
            user-select: none;
            -webkit-user-select: none;
            font-family: 'Mali', cursive;
        }

        body {
            margin: 0;
            padding: 0;
            background-color: #fbcfe8;
            background-image: 
                radial-gradient(#f472b6 15%, transparent 16%),
                radial-gradient(#f472b6 15%, transparent 16%);
            background-size: 30px 30px;
            background-position: 0 0, 15px 15px;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow-x: hidden;
        }

        #game-container {
            width: 100%;
            max-width: 480px;
            min-height: 90vh;
            margin: 15px;
            background: #fff0f5;
            border: 6px solid #4a3e3d;
            border-radius: 20px;
            box-shadow: 0 10px 0 #4a3e3d, 0 15px 25px rgba(0,0,0,0.15);
            padding: 24px 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: space-between;
            position: relative;
        }

        .title-banner {
            font-family: 'Press Start 2P', cursive;
            font-size: 16px;
            color: #be185d;
            text-shadow: 2px 2px 0px #fbcfe8;
            text-align: center;
            line-height: 1.5;
            margin-bottom: 20px;
            background: #ffe4e6;
            padding: 12px 16px;
            border: 4px solid #4a3e3d;
            border-radius: 12px;
            width: 100%;
        }

        /* Screen Sections */
        .screen {
            width: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            transition: all 0.3s ease;
        }

        .hidden {
            display: none !important;
        }

        /* Form elements */
        .input-group {
            width: 100%;
            background: #ffffff;
            border: 4px solid #4a3e3d;
            border-radius: 16px;
            padding: 18px 15px;
            margin-bottom: 20px;
            box-shadow: inset 0 -4px 0 #f1f5f9;
        }

        label {
            font-weight: 700;
            color: #831843;
            font-size: 16px;
            display: block;
            margin-bottom: 12px;
            text-align: center;
        }

        .date-selects {
            display: flex;
            gap: 10px;
            justify-content: center;
        }

        select {
            padding: 10px;
            font-size: 16px;
            font-weight: 600;
            border: 3px solid #4a3e3d;
            border-radius: 10px;
            background: #fef2f2;
            color: #4a3e3d;
            outline: none;
            cursor: pointer;
        }

        select:focus {
            background: #ffe4e6;
        }

        /* Pixel Buttons */
        .pixel-btn {
            font-family: 'Mali', cursive;
            font-weight: 700;
            font-size: 18px;
            color: #ffffff;
            background-color: #ec4899;
            border: 4px solid #4a3e3d;
            border-radius: 14px;
            padding: 12px 24px;
            cursor: pointer;
            box-shadow: 0 6px 0 #4a3e3d;
            transition: transform 0.1s, box-shadow 0.1s;
            width: 100%;
            max-width: 280px;
            text-align: center;
            margin-top: 8px;
        }

        .pixel-btn:active {
            transform: translateY(4px);
            box-shadow: 0 2px 0 #4a3e3d;
        }

        .pixel-btn.secondary {
            background-color: #a855f7;
        }

        /* Envelope Art & Animation */
        .envelope-wrapper {
            perspective: 1000px;
            margin: 25px 0;
            cursor: pointer;
        }

        .envelope {
            width: 200px;
            height: 140px;
            background: #f43f5e;
            border: 4px solid #4a3e3d;
            border-radius: 8px;
            position: relative;
            box-shadow: 0 8px 0 #4a3e3d;
            transition: transform 0.5s ease;
        }

        .envelope-flap {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            border-left: 96px solid transparent;
            border-right: 96px solid transparent;
            border-top: 75px solid #fb7185;
            transform-origin: top;
            transition: transform 0.4s ease;
            z-index: 3;
        }

        .envelope.open .envelope-flap {
            transform: rotateX(180deg);
            z-index: 1;
        }

        .envelope-heart {
            position: absolute;
            top: 45px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 32px;
            z-index: 4;
            transition: opacity 0.3s;
        }

        .envelope.open .envelope-heart {
            opacity: 0;
        }

        .letter-paper {
            width: 100%;
            background: #fff;
            border: 4px solid #4a3e3d;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 6px 0 #4a3e3d;
            margin: 15px 0;
            position: relative;
            animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        }

        @keyframes popIn {
            0% { transform: scale(0.8); opacity: 0; }
            100% { transform: scale(1); opacity: 1; }
        }

        .letter-header {
            font-size: 14px;
            font-weight: 700;
            color: #9d174d;
            border-bottom: 2px dashed #fbcfe8;
            padding-bottom: 8px;
            margin-bottom: 12px;
            display: flex;
            justify-content: space-between;
        }

        .letter-body {
            font-size: 16px;
            line-height: 1.7;
            color: #374151;
            min-height: 120px;
            white-space: pre-line;
            font-weight: 600;
        }

        .letter-footer {
            margin-top: 15px;
            text-align: right;
            font-weight: 700;
            color: #be185d;
        }

        /* Sparkles / Pixel Deco */
        .decor-icon {
            font-size: 24px;
            animation: bounce 1.5s infinite alternate;
        }

        @keyframes bounce {
            0% { transform: translateY(0); }
            100% { transform: translateY(-8px); }
        }

        .footer-note {
            font-size: 12px;
            color: #9ca3af;
            margin-top: 15px;
            text-align: center;
        }
    </style>
</head>
<body>

<div id="game-container">
    <div class="title-banner">
        💌 MESSAGE FROM<br>MY BIAS
    </div>

    <!-- Screen 1: Input Birthday -->
    <div id="screen-input" class="screen">
        <div style="text-align: center; margin-bottom: 15px;">
            <span class="decor-icon">✨</span>
            <p style="font-weight: 700; color: #4a3e3d; margin: 5px 0;">โปรดระบุวันเกิดของคุณ</p>
            <p style="font-size: 13px; color: #6b7280; margin: 0;">เมนของคุณมีข้อความพิเศษเตรียมไว้ให้แล้วนะ!</p>
        </div>

        <div class="input-group">
            <label for="birth-month">🎂 วันเกิดของคุณคือวันที่เท่าไหร่?</label>
            <div class="date-selects">
                <select id="birth-day">
                    <!-- JS will populate days 1-31 -->
                </select>
                <select id="birth-month">
                    <option value="1">มกราคม</option>
                    <option value="2">กุมภาพันธ์</option>
                    <option value="3">มีนาคม</option>
                    <option value="4">เมษายน</option>
                    <option value="5">พฤษภาคม</option>
                    <option value="6">มิถุนายน</option>
                    <option value="7">กรกฎาคม</option>
                    <option value="8">สิงหาคม</option>
                    <option value="9">กันยายน</option>
                    <option value="10">ตุลาคม</option>
                    <option value="11">พฤศจิกายน</option>
                    <option value="12">ธันวาคม</option>
                </select>
            </div>
        </div>

        <button class="pixel-btn" id="btn-submit" onclick="submitBirthday()">📩 รับข้อความจากเมน</button>
    </div>

    <!-- Screen 2: Envelope Tap -->
    <div id="screen-envelope" class="screen hidden">
        <p style="font-weight: 700; color: #9d174d; font-size: 18px; text-align: center;">
            มีจดหมายส่งถึงคุณ 1 ฉบับ!
        </p>
        <p style="font-size: 14px; color: #4b5563;">แตะที่ซองจดหมายเพื่อเปิดอ่าน</p>

        <div class="envelope-wrapper" onclick="openEnvelope()">
            <div class="envelope" id="envelope-element">
                <div class="envelope-flap"></div>
                <div class="envelope-heart">💖</div>
            </div>
        </div>
    </div>

    <!-- Screen 3: Read Letter -->
    <div id="screen-letter" class="screen hidden">
        <div class="letter-paper">
            <div class="letter-header">
                <span>SPECIAL LETTER 💌</span>
                <span id="letter-date">FOR YOU</span>
            </div>
            <div class="letter-body" id="letter-content">
                <!-- Text filled dynamically -->
            </div>
            <div class="letter-footer">
                ด้วยรักเสมอ, ❤️<br>
                <span style="font-size: 18px; color: #db2777;">— เมนคนโปรดของคุณ</span>
            </div>
        </div>

        <button class="pixel-btn" onclick="getRandomMessage()">🎲 สุ่มคำอวยพรเพิ่ม</button>
        <button class="pixel-btn secondary" onclick="resetGame()" style="margin-top: 10px;">🔄 ใส่วันเกิดใหม่</button>
    </div>

    <div class="footer-note">
        Arcadelab Edition • Created with 💕
    </div>
</div>

<script>
    // --- Audio Sound Effects (Web Audio API) ---
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    let audioCtx = null;

    function playSound(type) {
        try {
            if (!audioCtx) {
                audioCtx = new AudioContext();
            }
            if (audioCtx.state === 'suspended') {
                audioCtx.resume();
            }

            const osc = audioCtx.createOscillator();
            const gain = audioCtx.createGain();
            osc.connect(gain);
            gain.connect(audioCtx.destination);

            const now = audioCtx.currentTime;

            if (type === 'click') {
                osc.type = 'sine';
                osc.frequency.setValueAtTime(400, now);
                osc.frequency.exponentialRampToValueAtTime(800, now + 0.08);
                gain.gain.setValueAtTime(0.2, now);
                gain.gain.linearRampToValueAtTime(0.01, now + 0.08);
                osc.start(now);
                osc.stop(now + 0.08);
            } else if (type === 'open') {
                osc.type = 'triangle';
                osc.frequency.setValueAtTime(300, now);
                osc.frequency.exponentialRampToValueAtTime(600, now + 0.15);
                osc.frequency.exponentialRampToValueAtTime(900, now + 0.3);
                gain.gain.setValueAtTime(0.25, now);
                gain.gain.linearRampToValueAtTime(0.01, now + 0.3);
                osc.start(now);
                osc.stop(now + 0.3);
            }
        } catch (e) {
            // Audio ignore if non-supported
        }
    }

    // --- Message Database for Birthday Matching ---
    const promoSuffix = "\n\nฝากติดตามรอดูซีรีส์ TheGrimLover รักลืมตาย ของพูห์พาเวลด้วยนะ เริ่ม 28 พฤศิจิกายนนี้ ทางช่อง ONE31 และย้อนหลังทาง NETFLIX ทุกวันเสาร์เวลา 22:30";

    const baseMessages = [
        "ยิ้มเยอะๆ นะคนเก่ง! รู้มั้ยว่ารอยยิ้มของคุณคือพลังที่ยิ่งใหญ่ที่สุดสำหรับเราเสมอ ขอให้ทำตามความฝันได้อย่างเต็มที่เลยนะ!",
        "ขอบคุณที่เกิดมาให้เราได้รักนะ วันไหนที่เหนื่อย ล้า หรือท้อแท้ หันมามองเราได้เสมอ เราจะคอยเป็นเซฟโซนและซัพพอร์ตเธอตรงนี้เสมอเลย",
        "เธอทำดีที่สุดแล้วในทุกๆ วัน ไม่ต้องกดดันตัวเองจนเกินไปนะ พักผ่อน กินของอร่อยๆ แล้วเก่งขึ้นในแบบของตัวเองต่อไปนะ!",
        "ถ้าโลกข้างนอกมันใจร้าย อยากให้รู้ว่าตรงนี้มีเราที่อยู่ข้างเธอเสมอนะ ขอบคุณที่เป็นความสุขให้เราเหมือนกันนะ!",
        "ขอให้ทุกวันของคุณสดใสเหมือนวันแรกที่เราได้เจอกันนะ อย่าลืมดูแลตัวเองด้วยล่ะ เป็นห่วงมากๆ เลย!",
        "วันนี้หรือวันไหนๆ เธอก็เป็นคนที่เก่งและมีเสน่ห์ที่สุดเสมอ เชื่อมั่นในตัวเองเยอะๆ นะ พวกเราภูมิใจในตัวเธอมากๆ!",
        "ข้อความนี้ส่งตรงมาจากใจเลยนะ ขอให้พรทุกประการในโลกนี้บันดาลให้เธอมีความสุข มีแต่รอยยิ้ม และไร้ความทุกข์นะ!",
        "การได้มีเธอเป็นแฟนคลับ/แฟนเพลง คือสิ่งที่โชคดีที่สุดของเราเลยนะ ขอบคุณที่อยู่เคียงข้างกันมาตลอดนะคนดี"
    ];

    const biasMessages = baseMessages.map(msg => msg + promoSuffix);

    let userDay = 1;
    let userMonth = 1;

    // --- DOM Elements Init ---
    window.onload = function() {
        const daySelect = document.getElementById('birth-day');
        for (let i = 1; i <= 31; i++) {
            let opt = document.createElement('option');
            opt.value = i;
            opt.innerHTML = i + ' ' + (i === 1 ? 'st' : i === 2 ? 'nd' : i === 3 ? 'rd' : 'th');
            daySelect.appendChild(opt);
        }
    };

    function submitBirthday() {
        playSound('click');
        userDay = parseInt(document.getElementById('birth-day').value);
        userMonth = parseInt(document.getElementById('birth-month').value);

        document.getElementById('screen-input').classList.add('hidden');
        document.getElementById('screen-envelope').classList.remove('hidden');
    }

    function openEnvelope() {
        playSound('open');
        const envelope = document.getElementById('envelope-element');
        envelope.classList.add('open');

        setTimeout(() => {
            document.getElementById('screen-envelope').classList.add('hidden');
            document.getElementById('screen-letter').classList.remove('hidden');
            
            // Calculate index based on birthday
            const msgIndex = (userDay + userMonth) % biasMessages.length;
            displayMessage(biasMessages[msgIndex]);
        }, 700);
    }

    function displayMessage(text) {
        document.getElementById('letter-date').innerText = `DAY ${userDay}/${userMonth}`;
        document.getElementById('letter-content').innerText = text;
    }

    function getRandomMessage() {
        playSound('click');
        const randomIdx = Math.floor(Math.random() * biasMessages.length);
        displayMessage(biasMessages[randomIdx]);
    }

    function resetGame() {
        playSound('click');
        document.getElementById('envelope-element').classList.remove('open');
        document.getElementById('screen-letter').classList.add('hidden');
        document.getElementById('screen-input').classList.remove('hidden');
    }
</script>
</body>
</html>
```

Game Source: Message from My Bias

Creator: FlashStar31

Libraries: none

Complexity: complex (464 lines, 17.5 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: message-from-my-bias-flashstar31-mv4vsp79" to link back to the original. Then publish at arcadelab.ai/publish.