🎮ArcadeLab

Blok Blaze - Buatan Sendiri

by PixelHero77
235 lines8.4 KB
▶ Play
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blok Blaze - Buatan Sendiri</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style type="text/tailwindcss">
        @layer utilities {
            .grid-cell {
                @apply border border-gray-700/40;
            }
            .block-color {
                @apply rounded-sm shadow-md;
            }
        }
    </style>
</head>
<body class="bg-slate-900 text-white min-h-screen flex flex-col items-center py-6 px-4">
    <h1 class="text-[clamp(2rem,4vw,3rem)] font-bold text-orange-400 mb-2">🔥 Blok Blaze</h1>
    <p class="text-gray-300 mb-6">Susun & hancurkan garis penuh | ⬅️➡️ ⬇️ putar ⬆️</p>

    <div class="flex gap-6 flex-wrap justify-center">
        <!-- Papan Main -->
        <canvas id="papan" width="300" height="600" class="border-4 border-orange-500/60 rounded-lg bg-slate-800"></canvas>

        <!-- Panel Samping -->
        <div class="flex flex-col gap-5">
            <div class="bg-slate-800 p-4 rounded-lg border border-orange-400/40">
                <p class="text-lg">Skor: <span id="skor" class="font-bold text-orange-300 text-xl">0</span></p>
            </div>
            <div class="bg-slate-800 p-4 rounded-lg border border-orange-400/40">
                <p class="text-sm mb-2 text-gray-300">Berikutnya:</p>
                <canvas id="berikutnya" width="80" height="80"></canvas>
            </div>
            <button id="tombolMulai" class="bg-orange-500 hover:bg-orange-600 transition-all font-bold py-3 px-6 rounded-lg text-lg">
                MULAI / ULANG
            </button>
            <div class="text-sm text-gray-400 mt-2">
                ← → : Geser<br>
                ↑ : Putar<br>
                ↓ : Turun cepat
            </div>
        </div>
    </div>

    <script>
        // === PENGATURAN UKURAN ===
        const BARIS = 20;
        const KOLOM = 10;
        const UKURAN_KOTAK = 30;

        // Warna balok sama seperti gaya Blok Blaze
        const WARNA = [
            null,
            '#FF5722', '#2196F3', '#4CAF50', '#FFC107',
            '#9C27B0', '#00BCD4', '#F44336'
        ];

        // Bentuk balok standar
        const BENTUK = [
            [[1,1,1,1]], // I
            [[2,2],[2,2]], // O
            [[0,3,0],[3,3,3]], // T
            [[0,4,4],[4,4,0]], // S
            [[5,5,0],[0,5,5]], // Z
            [[6,0,0],[6,6,6]], // J
            [[0,0,7],[7,7,7]]  // L
        ];

        // Ambil elemen kanvas
        const kanvas = document.getElementById('papan');
        const konteks = kanvas.getContext('2d');
        const kanvasBerikutnya = document.getElementById('berikutnya');
        const konteksBerikutnya = kanvasBerikutnya.getContext('2d');
        const teksSkor = document.getElementById('skor');
        const tombolMulai = document.getElementById('tombolMulai');

        let papan = [];
        let skor = 0;
        let selesai = false;
        let balokSekarang, balokNanti;
        let jeda;

        // === Siapkan papan kosong ===
        function kosongkanPapan() {
            papan = Array(BARIS).fill().map(() => Array(KOLOM).fill(0));
        }

        // === Gambar kotak satu per satu ===
        function gambarKotak(x, y, warna, konteksGambar = konteks, ukuran = UKURAN_KOTAK) {
            konteksGambar.fillStyle = WARNA[warna];
            konteksGambar.fillRect(x * ukuran, y * ukuran, ukuran - 1, ukuran - 1);
        }

        // === Gambar seluruh papan ===
        function gambarPapan() {
            konteks.clearRect(0, 0, kanvas.width, kanvas.height);
            for (let b = 0; b < BARIS; b++) {
                for (let k = 0; k < KOLOM; k++) {
                    if (papan[b][k]) gambarKotak(k, b, papan[b][k]);
                }
            }
            // Gambar balok yang sedang jatuh
            balokSekarang.bentuk.forEach((baris, bi) => {
                baris.forEach((nilai, ki) => {
                    if (nilai) gambarKotak(balokSekarang.x + ki, balokSekarang.y + bi, nilai);
                });
            });
        }

        // === Buat balok baru ===
        function buatBalok() {
            balokSekarang = balokNanti || ambilAcak();
            balokNanti = ambilAcak();
            balokSekarang.x = Math.floor(KOLOM / 2) - Math.floor(balokSekarang.bentuk[0].length / 2);
            balokSekarang.y = 0;

            if (tabrakan(balokSekarang)) {
                selesai = true;
            }

            gambarBerikutnya();
        }

        function ambilAcak() {
            return { bentuk: BENTUK[Math.floor(Math.random() * BENTUK.length)] };
        }

        // === Gambar balok yang akan datang ===
        function gambarBerikutnya() {
            konteksBerikutnya.clearRect(0, 0, kanvasBerikutnya.width, kanvasBerikutnya.height);
            const ukKecil = 18;
            balokNanti.bentuk.forEach((baris, bi) => {
                baris.forEach((nilai, ki) => {
                    if (nilai) {
                        konteksBerikutnya.fillStyle = WARNA[nilai];
                        konteksBerikutnya.fillRect(ki * ukKecil + 10, bi * ukKecil + 10, ukKecil - 1, ukKecil - 1);
                    }
                });
            });
        }

        // === Cek tabrakan ===
        function tabrakan(balok) {
            return balok.bentuk.some((baris, bi) => {
                return baris.some((nilai, ki) => {
                    if (!nilai) return false;
                    let nx = balok.x + ki;
                    let ny = balok.y + bi;
                    return nx < 0 || nx >= KOLOM || ny >= BARIS || (ny >= 0 && papan[ny][nx]);
                });
            });
        }

        // === Tempel balok ke papan ===
        let tempel = () => {
            balokSekarang.bentuk.forEach((baris, bi) => {
                baris.forEach((nilai, ki) => {
                    if (nilai) papan[balokSekarang.y + bi][balokSekarang.x + ki] = nilai;
                });
            });
            hapusGarisPenuh();
            buatBalok();
        };

        // === Hapus garis penuh & tambah skor ===
        function hapusGarisPenuh() {
            let barisHapus = 0;
            papan = papan.filter(baris => {
                if (baris.every(sel => sel !== 0)) {
                    barisHapus++;
                    return false;
                }
                return true;
            });
            while (papan.length < BARIS) papan.unshift(Array(KOLOM).fill(0));
            skor += barisHapus * 100;
            teksSkor.innerText = skor;
        }

        // === Putar balok ===
        function putar(balok) {
            let ubah = balok.bentuk[0].map((_, i) => balok.bentuk.map(b => b[i]).reverse());
            let asli = balok.bentuk;
            balok.bentuk = ubah;
            if (tabrakan(balok)) balok.bentuk = asli;
        }

        // === Gerakan otomatis ===
        function gerakTurunOtomatis() {
            balokSekarang.y++;
            if (tabrakan(balokSekarang)) {
                balokSekarang.y--;
                tempel();
            }
        }

        // === Kontrol Keyboard ===
        document.addEventListener('keydown', e => {
            if (selesai) return;
            if (e.key === 'ArrowLeft') { balokSekarang.x--; if(tabrakan(balokSekarang)) balokSekarang.x++; }
            if (e.key === 'ArrowRight') { balokSekarang.x++; if(tabrakan(balokSekarang)) balokSekarang.x--; }
            if (e.key === 'ArrowDown') gerakTurunOtomatis();
            if (e.key === 'ArrowUp') putar(balokSekarang);
            gambarPapan();
        });

        // === Mulai / Ulang ===
        tombolMulai.addEventListener('click', () => {
            kosongkanPapan();
            skor = 0;
            selesai = false;
            teksSkor.innerText = '0';
            buatBalok();
            if (jeda) clearInterval(jeda);
            jeda = setInterval(() => {
                if (!selesai) {
                    gerakTurunOtomatis();
                    gambarPapan();
                } else {
                    clearInterval(jeda);
                    konteks.fillStyle = 'rgba(0,0,0,0.7)';
                    konteks.fillRect(0,0,kanvas.width,kanvas.height);
                    konteks.fillStyle = '#fff';
                    konteks.font = 'bold 22px sans-serif';
                    konteks.fillText('GAME SELESAI!', 40, 280);
                }
            }, 700);
        });
    </script>
</body>
</html>

Game Source: Blok Blaze - Buatan Sendiri

Creator: PixelHero77

Libraries: none

Complexity: complex (235 lines, 8.4 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: blok-blaze-buatan-sendiri-pixelhero77" to link back to the original. Then publish at arcadelab.ai/publish.