Powrót do strony głównej

AI dla gier webowych: nauka kodowania

Artykuł opisuje metodę nauczania uczniów tworzenia gier webowych za pomocą AI. Szczegółowy prompt dla Gemini generuje pełny kod gry typu Whac-A-Mole na HTML/CSS/JS. Podkreśla się znaczenie przygotowania: czytanie kodu i projektowanie na papierze.

Tworzymy grę z AI: od promptu do kodu
Advertisement 728x90

Sztuczna inteligencja jako narzędzie do tworzenia gier internetowych: doświadczenie w nauczaniu uczniów

Uczniowie opanowali już podstawy HTML i CSS. Przed użyciem SI konieczne było wykształcenie umiejętności czytania cudzego kodu. Zadanie: otworzyć plik z komentarzami, zmienić wartość background-color w wskazanej linii, zapisać i odświeżyć stronę w przeglądarce. Takie podejście pozwala szybko powiązać zmiany w kodzie z wizualnym efektem, zmniejszając lęk przed obcymi źródłami.

Następnie przeszliśmy do projektowania na papierze. Wybraliśmy mechanikę gry typu Whac-A-Mole z personalizacją: zamiast standardowych obiektów — zdjęcia uczniów w normalnym stanie i z nadętymi policzkami po aktywacji.

Logika gry i wybór stosu technologicznego

Główne elementy mechaniki:

Google AdInline article slot
  • Siatka 3×3 z komórek (norki).
  • Losowe pojawianie się aktywnego obrazu co 5 sekund.
  • Zwiększanie prędkości z każdym cyklem.
  • Kliknięcie w aktywną komórkę przywraca ją do stanu normalnego.
  • Przegrana: wszystkie 9 komórek aktywnych jednocześnie — blokada wprowadzania na 5 sekund, miganie, okno modalne z restartem.

Stos: czysty HTML, CSS, JavaScript w jednym pliku. Zalety dla nauki:

  • Brak konfiguracji środowiska — wystarczy przeglądarka.
  • Natychmiastowa informacja zwrotna przy F5.
  • Pełna przenośność: jeden plik HTML działa wszędzie.

Do prototypu użyliśmy zdjęć kociąt: podstawowych i z reakcją (wygenerowanych przez SI na podstawie promptu).

Tworzenie skutecznego promptu

SI postrzegane jest jako narzędzie wykonawcze, wymagające szczegółowego opisu. Wspólnie z dziećmi stworzyliśmy prompt dla Gemini:

Google AdInline article slot

Szczegółowość:

  • Rola: doświadczony frontend developer.
  • Gra: odpowiednik Whac-A-Mole ze zdjęciami (normalne i z policzkami).
  • Styl: jasne tło, wyśrodkowanie.
  • Pole: biały panel 3×3 z zaokrągleniami i cieniem.
  • Komórki: 9 obrazów z efektem naciśnięcia, responsywność pod urządzenia mobilne.
  • 18 plików: photo1_normal.jpg ... photo9_highlighted.jpg.
  • Logika: timery, przyspieszenie, koniec gry, modal z rozmyciem.
  • Wymagania: jeden plik, nowoczesny JS, komentarze, bez podświetleń na urządzeniach mobilnych.

Rezultat: gotowy kod gry

SI wygenerował działający prototyp w ciągu sekund. Po minimalnych poprawkach otrzymaliśmy wersję końcową. Kod wykorzystuje zmienne CSS, Flexbox/Grid, backdrop-filter, nowoczesne transition i media queries.

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kocięta!</title>
    <style>
        /* Zmienne dla łatwej regulacji rozmiarów i kolorów w jednym miejscu */
        :root {
            --bg-color: #f0f2f5;   /* Jasnoszare tło */
            --grid-gap: 15px;      /* Odstęp między kartami */
            --cell-size: 180px;    /* Bazowy rozmiar kwadratu ze zdjęciem */
            --text-color: #333;    /* Ciemnoszary kolor tekstu */
        }

        /* Główne ustawienia ekranu */
        body {
            margin: 0;
            padding: 0;
            display: flex;          /* Użycie Flexbox do wyrównania */
            justify-content: center; /* Wyśrodkowanie poziome */
            align-items: center;     /* Wyśrodkowanie pionowe */
            min-height: 100vh;      /* Wysokość równa oknu przeglądarki */
            background-color: var(--bg-color);
            font-family: 'Segoe UI', Tahoma, sans-serif;
            overflow: hidden;       /* Wyłączenie przewijania */
            user-select: none;      /* Wyłączenie zaznaczania przy szybkich kliknięciach */
            -webkit-tap-highlight-color: transparent; /* Usunięcie niebieskiego podświetlenia przy dotknięciu na urządzeniach mobilnych */
        }

        /* Główny kontener dla instrukcji i gry */
        .main-wrapper {
            display: flex;
            flex-direction: column; /* Układanie tekstu i siatki pionowo */
            align-items: center;    /* Wyśrodkowanie poziome */
        }

        /* Style dla instrukcji tekstowych */
        .instructions {
            text-align: center;     /* Wyśrodkowanie tekstu */
            color: var(--text-color);
            font-size: 1.8rem;
            line-height: 1.4;       /* Odstęp między wierszami dla dwóch linii */
            margin-bottom: 25px;    /* Odstęp od tekstu do pola gry */
            font-weight: 500;
        }

        /* Kontener siatki gry 3x3 */
        .game-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr); /* 3 równe kolumny */
            grid-template-rows: repeat(3, 1fr);    /* 3 równe wiersze */
            gap: var(--grid-gap);
            padding: 20px;
            background: white;       /* Białe tło pod siatką */
            border-radius: 24px;     /* Zaokrąglenie głównego panelu */
            box-shadow: 0 10px 40px rgba(0,0,0,0.08); /* Miękki cień dla objętości */
            position: relative;
        }

        /* Stan zablokowany: wyłączenie kliknięć po zakończeniu gry */
        .game-container.disabled {
            pointer-events: none;    /* Ignorowanie wejść myszki/dotknięć */
        }

        /* Kontener dla każdego zdjęcia */
        .cell {
            width: var(--cell-size);
            height: var(--cell-size);
            overflow: hidden;        /* Przycięcie krawędzi zdjęcia */
            border-radius: 16px;     /* Zaokrąglenie rogów zdjęcia */
            cursor: pointer;
            transition: transform 0.1s ease; /* Płynna animacja przy kliknięciu */
            background: #f9f9f9;     /* Kolor tła podczas ładowania zdjęcia */
        }

        /* Efekt kliknięcia: karta lekko się zmniejsza */
        .cell:active {
            transform: scale(0.96);
        }

        /* Rzeczywisty obraz wewnątrz komórki */
        .cell img {
            width: 100%;
            height: 100%;
            object-fit: cover;       /* Wypełnienie kwadratu bez zniekształceń */
            display: block;
        }

        /* Okno modalne pełnoekranowe */
        #modal {
            display: none;           /* Ukryte domyślnie */
            position: fixed;         /* Ustalone na wierzchu całej zawartości */
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.01); /* Przezroczyste tło */
            backdrop-filter: blur(15px);          /* Główny efekt: rozmycie tła */
            -webkit-backdrop-filter: blur(15px);  /* Obsługa rozmycia w Safari */
            justify-content: center; /* Wyśrodkowanie zawartości poziomo */
            align-items: center;     /* Wyśrodkowanie zawartości pionowo */
            z-index: 100;            /* Przeniesienie na przód */
        }

        /* Biała karta wewnątrz okna modalnego */
        .modal-content {
            background: white;
            padding: 50px;
            border-radius: 30px;
            text-align: center;
            box-shadow: 0 15px 60px rgba(0,0,0,0.15); /* Głęboki cień dla akcentu */
            border: 1px solid rgba(255,255,255,0.3);
        }

        .modal-content h2 {
            margin: 0 0 30px 0;
            font-size: 28px;
            color: #222;
        }

        /* Przycisk restartu */
        .modal-content button {
            background: #222;        /* Ciemny stylowy przycisk */
            color: white;
            border: none;
            padding: 16px 50px;
            font-size: 18px;
            border-radius: 14px;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .modal-content button:hover {
            background: #000;
            transform: translateY(-2px); /* Efekt unoszenia się przy najechaniu myszką */
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
        }

        /* Adaptacja dla urządzeń mobilnych */
        @media (max-width: 650px) {
            :root {
                --cell-size: 28vw;   /* Rozmiar zależny od szerokości ekranu */
            }
        }
    </style>
</head>
<body>
    <div class="main-wrapper">
        <div class="instructions">Klikaj w kocięta z nadętymi policzkami!</div>
        <div class="game-container" id="gameContainer">
            <!-- 9 komórek zostanie wygenerowanych przez JS -->
        </div>
    </div>

    <div id="modal">
        <div class="modal-content">
            <h2>😿 Wszystkie kocięta nadęły policzki!</h2>
            <p>Spróbujesz ponownie?</p>
            <button onclick="resetGame()">Tak!</button>
        </div>
    </div>

    <script>
        // Zmienne stanu gry
        let gameActive = true;
        let activeCell = null;
        let intervalId = null;
        let speed = 5000; // Początkowe 5 sekund
        let highlightedCount = 0;
        const cells = [];
        const totalCells = 9;

        // Obrazy: zastąp swoimi photo_normal.jpg i photo_highlighted.jpg
        const images = {
            1: { normal: 'photo1_normal.jpg', highlighted: 'photo1_highlighted.jpg' },
            2: { normal: 'photo2_normal.jpg', highlighted: 'photo2_highlighted.jpg' },
            // ... aż do 9
        };

        // Inicjalizacja gry
        function initGame() {
            const container = document.getElementById('gameContainer');
            container.innerHTML = '';
            cells.length = 0;
            highlightedCount = 0;

            for (let i = 1; i <= totalCells; i++) {
                const cell = document.createElement('div');
                cell.className = 'cell';
                cell.dataset.index = i;
                const img = document.createElement('img');
                img.src = images[i].normal;
                img.alt = `Kocię ${i}`;
                cell.appendChild(img);
                cell.addEventListener('click', handleClick);
                container.appendChild(cell);
                cells.push(cell);
            }

            startGameLoop();
        }

        // Pętla gry: aktywacja losowej komórki
        function startGameLoop() {
            if (intervalId) clearInterval(intervalId);
            intervalId = setInterval(() => {
                if (!gameActive || highlightedCount >= totalCells) return;
                
                const availableCells = cells.filter(cell => !cell.classList.contains('highlighted'));
                if (availableCells.length === 0) return;
                
                const randomCell = availableCells[Math.floor(Math.random() * availableCells.length)];
                activateCell(randomCell);
            }, speed);
        }

        // Aktywacja komórki (nadęcie policzków)
        function activateCell(cell) {
            cell.classList.add('highlighted');
            const img = cell.querySelector('img');
            img.src = images[parseInt(cell.dataset.index)].highlighted;
            highlightedCount++;
            
            if (highlightedCount >= totalCells) {
                gameOver();
            }
        }

        // Obsługa kliknięcia: reset komórki
        function handleClick(e) {
            const cell = e.currentTarget;
            if (!cell.classList.contains('highlighted') || !gameActive) return;
            
            cell.classList.remove('highlighted');
            const img = cell.querySelector('img');
            img.src = images[parseInt(cell.dataset.index)].normal;
            highlightedCount--;
        }

        // Sekwencja zakończenia gry
        function gameOver() {
            gameActive = false;
            clearInterval(intervalId);
            
            const container = document.getElementById('gameContainer');
            container.classList.add('disabled');
            
            // Miganie wszystkich komórek
            const blinkInterval = setInterval(() => {
                cells.forEach(cell => {
                    const img = cell.querySelector('img');
                    const index = parseInt(cell.dataset.index);
                    img.src = cell.classList.contains('blinking') ? 
                        images[index].normal : images[index].highlighted;
                    cell.classList.toggle('blinking');
                });
            }, 500);
            
            setTimeout(() => {
                clearInterval(blinkInterval);
                document.getElementById('modal').style.display = 'flex';
            }, 5000);
        }

        // Reset gry
        function resetGame() {
            document.getElementById('modal').style.display = 'none';
            document.getElementById('gameContainer').classList.remove('disabled');
            speed = Math.max(1000, speed - 500); // Zwiększenie trudności
            gameActive = true;
            initGame();
        }

        // Rozpoczęcie gry po załadowaniu
        window.addEventListener('load', initGame);
    </script>
</body>
</html>

Co jest ważne

  • Szczegółowy prompt przyspiesza generowanie: Określenie roli, stylu, mechaniki i wymagań kodu daje działający prototyp w ciągu sekund.
  • Czytanie kodu przed SI: Podstawowa umiejętność analizy zmniejsza barierę dla eksperymentów.
  • Projektowanie na papierze: Wizualizacja logiki przed kodowaniem upraszcza zadanie dla SI.
  • Jeden plik na wszystko: Idealne do nauki i rozpowszechniania.
  • Responsywność i efekty: CSS Grid, zmienne, backdrop-filter zapewniają nowoczesny UX.

— Editorial Team

Google AdInline article slot
Advertisement 728x90

Czytaj dalej