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:
- 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:
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
Brak komentarzy.