MOODUL 02 · TASE 1 — ALGAJA

🎨 HTML5 Canvas & JavaScript Põhialused

Õpi joonistama Canvas-ile, animeerima objekte ja reageerima kasutaja sisendile. See on alus kõigele mis järgneb!

⏱️ ~3 tundi 📝 5 harjutust 🟢 Algaja

📋 Eeldused

ℹ️

Enne seda moodulit peaksid olema läbinud Moodul 01 — VS Code, Git ja GitHub peavad olema seadistatud.

🎯 Mida Sa Õpid

  • ✅ HTML5 Canvas elemendi kasutamine
  • ✅ 2D konteksti joonistamisfunktsioonid
  • ✅ Animatsiooniloop requestAnimationFrame-iga
  • ✅ Klaviatuuri ja hiire sündmuste käsitlemine
  • ✅ Lihtne interaktiivne graafika loomine

📦 Samm 1 — Projekti Loomine

Loome uue projekti ja seadistame HTML faili koos Canvas elemendiga.

Terminal
# Loo uus projektikaust
mkdir canvas-pohialused
cd canvas-pohialused
git init

# Loo failid
touch index.html style.css main.js
index.html
<!DOCTYPE html>
<html lang="et">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Põhialused</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <canvas id="game" width="800" height="600"></canvas>
  <script src="main.js"></script>
</body>
</html>
style.css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: #1a1a2e;
}

canvas {
  border: 2px solid #333;
  border-radius: 8px;
  background: #0f0f23;
}

🎨 Samm 2 — Canvas-ile Joonistamine

Canvas 2D kontekst annab meile joonistamisfunktsioonid. Alustame lihtsatest kujunditest.

main.js
// 1. Hangi Canvas element ja 2D kontekst
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// 2. Joonista ristkülik
ctx.fillStyle = '#22c55e';       // Värv
ctx.fillRect(50, 50, 100, 80);  // x, y, laius, kõrgus

// 3. Joonista ring
ctx.beginPath();
ctx.arc(300, 200, 40, 0, Math.PI * 2); // x, y, raadius, algus, lõpp
ctx.fillStyle = '#3b82f6';
ctx.fill();
ctx.closePath();

// 4. Joonista joon
ctx.beginPath();
ctx.moveTo(400, 100);
ctx.lineTo(600, 300);
ctx.strokeStyle = '#ef4444';
ctx.lineWidth = 3;
ctx.stroke();
ctx.closePath();

// 5. Joonista tekst
ctx.font = '24px Inter, sans-serif';
ctx.fillStyle = '#e2e8f0';
ctx.fillText('Tere, Canvas! 🎮', 250, 400);
💡

Canvas koordinaadid: (0, 0) on ülemises vasakus nurgas. X kasvab paremale, Y kasvab alla (mitte üles nagu matemaatikas!).

🔄 Samm 3 — Animatsiooniloop

Mängudes ei joonista me ainult ühe korra — me joonistame 60 korda sekundis. Selleks kasutame requestAnimationFrame.

main.js — Animeeritud pall
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// Palli andmed
const ball = {
  x: 100,
  y: 100,
  radius: 20,
  dx: 3,  // kiirus x-teljel
  dy: 2,  // kiirus y-teljel
  color: '#06b6d4'
};

function update() {
  // Liiguta palli
  ball.x += ball.dx;
  ball.y += ball.dy;

  // Põrka servadest tagasi
  if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
    ball.dx = -ball.dx;
  }
  if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
    ball.dy = -ball.dy;
  }
}

function draw() {
  // Puhasta ekraan
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Joonista pall
  ctx.beginPath();
  ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
  ctx.fillStyle = ball.color;
  ctx.fill();
  ctx.closePath();
}

function gameLoop() {
  update();       // Uuenda loogikat
  draw();         // Joonista uus kaader
  requestAnimationFrame(gameLoop);  // Kutsu uuesti (~60fps)
}

// Käivita!
gameLoop();

⌨️ Samm 4 — Klaviatuuri Sisend

Nüüd lisame klaviatuuriga juhtimise — mängija saab WASD klahvidega liikuda.

main.js — Klaviatuuriga juhtimine
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// Mängija
const player = {
  x: canvas.width / 2,
  y: canvas.height / 2,
  size: 40,
  speed: 5,
  color: '#22c55e'
};

// Jälgi milliseid klahve hoitakse all
const keys = {};

window.addEventListener('keydown', (e) => {
  keys[e.key.toLowerCase()] = true;
});

window.addEventListener('keyup', (e) => {
  keys[e.key.toLowerCase()] = false;
});

function update() {
  // WASD liikumine
  if (keys['w'] || keys['arrowup'])    player.y -= player.speed;
  if (keys['s'] || keys['arrowdown'])  player.y += player.speed;
  if (keys['a'] || keys['arrowleft'])  player.x -= player.speed;
  if (keys['d'] || keys['arrowright']) player.x += player.speed;

  // Hoia mängija ekraanil
  player.x = Math.max(0, Math.min(canvas.width - player.size, player.x));
  player.y = Math.max(0, Math.min(canvas.height - player.size, player.y));
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Joonista mängija
  ctx.fillStyle = player.color;
  ctx.fillRect(player.x, player.y, player.size, player.size);

  // Juhised
  ctx.font = '16px Inter, sans-serif';
  ctx.fillStyle = '#94a3b8';
  ctx.fillText('Kasuta WASD või nooleklahve liikumiseks', 10, 30);
}

function gameLoop() {
  update();
  draw();
  requestAnimationFrame(gameLoop);
}

gameLoop();

🖱️ Samm 5 — Hiire Sisend

Lisa hiire jälgimine — ring jälgib kursori positsiooni sujuvalt kasutades lineaarset interpolatsiooni (lerp).

main.js — Hiire jälgimine (lerp)
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

const follower = { x: 400, y: 300, radius: 15 };
const mouse = { x: 400, y: 300 };

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  mouse.x = e.clientX - rect.left;
  mouse.y = e.clientY - rect.top;
});

// Lineaarne interpolatsioon — sujuv liikumine
function lerp(start, end, factor) {
  return start + (end - start) * factor;
}

function update() {
  // Liigu hiire suunas, aga sujuvalt (factor 0.05 = aeglane, 0.3 = kiire)
  follower.x = lerp(follower.x, mouse.x, 0.08);
  follower.y = lerp(follower.y, mouse.y, 0.08);
}

function draw() {
  // Poolläbipaistev puhastus = jäljeefekt!
  ctx.fillStyle = 'rgba(15, 15, 35, 0.15)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // Joonista jälgija
  ctx.beginPath();
  ctx.arc(follower.x, follower.y, follower.radius, 0, Math.PI * 2);
  ctx.fillStyle = '#a855f7';
  ctx.fill();
  ctx.closePath();

  // Joonista sihtpunkt
  ctx.beginPath();
  ctx.arc(mouse.x, mouse.y, 4, 0, Math.PI * 2);
  ctx.fillStyle = '#ef4444';
  ctx.fill();
  ctx.closePath();
}

function gameLoop() {
  update();
  draw();
  requestAnimationFrame(gameLoop);
}

gameLoop();

🔀 Ära Unusta Commitida!

Terminal
git add .
git commit -m "feat: lisa Canvas põhialused — joonistamine, animatsioon, input"
git push

📝 Harjutused

Kinnista õpitut nende 5 harjutusega!

  • Joonista Eesti lipp

    Joonista Canvas-ile Eesti lipp — kolm horisontaalset ristkülikut: sinine (#0072CE), must (#000000), valge (#FFFFFF). Lipp peab olema proportsionaalne (7:11).

  • Animeeritud põrkav pall

    Loo pall mis põrkab ekraani kõigist neljast servast tagasi. Lisa igal põrkel juhuslik värvivahetus.

  • WASD-ga juhitav ruut

    Loo WASD-ga liigutatav ruut, mis ei saa ekraanilt välja minna. Lisa kiiruse kuva (pikslid/kaader).

  • Hiire jälgija lerpiga

    Loo ring mis jälgib hiire kursori positsiooni sujuvalt. Katse erinevaid lerp väärtusi (0.02, 0.1, 0.5) — mis tundub loomulik?

  • Kombineeri kõik!

    Loo stseen kus: WASD-mängija liigub, hiire sihtpunkt on nähtav, taust on animeeritud (liikuvad tähed/osakesed). Commiti tulemus GitHubi!

← Moodul 01: Arenduskeskkond Järgmine: Esimene Mäng →