📦 microsoft / Web-Dev-For-Beginners

📄 README.md · 624 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624<!--
CO_OP_TRANSLATOR_METADATA:
{
  "original_hash": "7994743c5b21fdcceb36307916ef249a",
  "translation_date": "2026-01-07T00:27:28+00:00",
  "source_file": "6-space-game/2-drawing-to-canvas/README.md",
  "language_code": "no"
}
-->
# Bygg et romspill del 2: Tegn helt og monstre på lerretet

```mermaid
journey
    title Din Canvas-grafikkreise
    section Grunnlag
      Forstå Canvas API: 3: Student
      Lær koordinatsystemet: 4: Student
      Tegn grunnleggende former: 4: Student
    section Bildehåndtering
      Last inn spillressurser: 4: Student
      Håndter asynkron lasting: 5: Student
      Posisjoner sprites: 5: Student
    section Spillrendering
      Lag spillskjerm: 5: Student
      Bygg formasjoner: 5: Student
      Optimaliser ytelse: 4: Student
```
Canvas API er en av nettutviklingens mest kraftfulle funksjoner for å lage dynamisk, interaktiv grafikk rett i nettleseren din. I denne leksjonen vil vi forvandle det tomme HTML `<canvas>`-elementet til en spillverden fylt med helter og monstre. Tenk på lerretet som ditt digitale tegnebrett der kode blir til visuelle bilder.

Vi bygger videre på det du lærte i forrige leksjon, og nå skal vi dykke ned i de visuelle aspektene. Du vil lære hvordan du laster og viser spill-sprites, plasserer elementer nøyaktig, og skaper det visuelle grunnlaget for romspillet ditt. Dette bygger bro mellom statiske nettsider og dynamiske, interaktive opplevelser.

Når du er ferdig med denne leksjonen, vil du ha en komplett spillscene med helteskipet plassert korrekt og fiendeformasjoner klare for kamp. Du vil forstå hvordan moderne spill gjengir grafikk i nettlesere og få ferdigheter til å lage dine egne interaktive visuelle opplevelser. La oss utforske lerret-grafikk og bringe romspillet ditt til liv!

```mermaid
mindmap
  root((Canvas Graphics))
    Canvas Element
      HTML5-funksjon
      2D-kontekst
      Koordinatsystem
      Pikselkontroll
    Drawing Operations
      Grunnleggende former
      Tekstgjengivelse
      Bildevisning
      Banetegning
    Asset Management
      Bildelasting
      Asynkrone operasjoner
      Feilhåndtering
      Ytelse
    Game Rendering
      Spriteplassering
      Formasjonsoppsett
      Scene-komposisjon
      Rammeoppdateringer
    Visual Effects
      Farger og stiler
      Transformasjoner
      Animasjoner
      Lagdeling
```
## Forkunnskapsquiz

[Forkunnskapsquiz](https://ff-quizzes.netlify.app/web/quiz/31)

## Lerretet

Så hva er egentlig `<canvas>`-elementet? Det er HTML5s løsning for å lage dynamisk grafikk og animasjoner i nettlesere. I motsetning til vanlige bilder eller videoer som er statiske, gir lerretet deg pikselkontroll over alt som vises på skjermen. Dette gjør det perfekt for spill, datavisualisering og interaktiv kunst. Tenk på det som en programmerbar tegneflate der JavaScript blir penselen din.

Som standard ser et canvas-element ut som et tomt, gjennomsiktig rektangel på siden din. Men det er her potensialet ligger! Den virkelige kraften dukker opp når du bruker JavaScript til å tegne former, laste bilder, lage animasjoner, og gjøre ting responsive til brukerinteraksjoner. Det ligner på hvordan tidlige datagrafikkpionerer ved Bell Labs på 1960-tallet måtte programmere hver piksel for å lage de første digitale animasjonene.

✅ Les [mer om Canvas API](https://developer.mozilla.org/docs/Web/API/Canvas_API) på MDN.

Slik deklareres det vanligvis, som en del av sidens innhold:

```html
<canvas id="myCanvas" width="200" height="100"></canvas>
```

**Dette gjør koden:**
- **Setter** `id`-attributtet slik at du kan referere til dette spesifikke canvas-elementet i JavaScript
- **Definerer** `width` i piksler for å kontrollere det horisontale lerretsmålet
- **Fastsetter** `height` i piksler for å bestemme lerrets vertikale dimensjoner

## Tegne enkel geometri

Nå som du vet hva canvas-elementet er, la oss utforske hvordan man faktisk tegner på det! Lerretet bruker et koordinatsystem som kan føles kjent fra mattetimen, men det er én viktig forskjell som er spesifikk for datagrafikk.

Lerretet bruker kartesiske koordinater med en x-akse (horisontal) og y-akse (vertikal) for å posisjonere alt du tegner. Men her er forskjellen: i motsetning til koordinatsystemet fra mattetimen, starter origo `(0,0)` øverst til venstre, med x-verdier som øker mot høyre og y-verdier som øker nedover. Denne tilnærmingen stammer fra tidlige dataskjermer der elektronstråler skannet fra topp til bunn, noe som gjorde øverst til venstre til det naturlige startpunktet.

```mermaid
quadrantChart
    title Lerretets koordinatsystem
    x-axis Venstre --> Høyre
    y-axis Topp --> Bunn
    quadrant-1 Kvadrant 1
    quadrant-2 Kvadrant 2  
    quadrant-3 Kvadrant 3
    quadrant-4 Kvadrant 4
    
    Origin Point: [0.1, 0.1]
    Hero Center: [0.5, 0.8]
    Enemy Formation: [0.3, 0.2]
    Power-up: [0.7, 0.6]
    UI Elements: [0.9, 0.1]
```
![lerretets rutenett](../../../../translated_images/no/canvas_grid.5f209da785ded492.webp)
> Bilde fra [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)

For å tegne på canvas-elementet følger du den samme tre-trinns prosessen som danner grunnlaget for all lerretgrafikk. Når du gjør dette noen ganger, blir det helt naturlig:

```mermaid
flowchart LR
    A[HTML Canvas-element] --> B[Få Canvas-referanse]
    B --> C[Få 2D-kontekst]
    C --> D[Tegneoperasjoner]
    
    D --> E[Tegn former]
    D --> F[Tegn tekst]
    D --> G[Tegn bilder]
    D --> H[Bruk stiler]
    
    E --> I[Gjør klar for skjerm]
    F --> I
    G --> I
    H --> I
    
    style A fill:#e1f5fe
    style C fill:#e8f5e8
    style I fill:#fff3e0
```
1. **Hent en referanse** til Canvas-elementet ditt fra DOM (akkurat som med andre HTML-elementer)
2. **Hent 2D-renderingskonteksten** – dette gir deg alle tegnemetodene
3. **Begynn å tegne!** Bruk kontekstens innebygde metoder for å lage grafikken din

Slik ser det ut i kode:

```javascript
// Trinn 1: Hent canvas-elementet
const canvas = document.getElementById("myCanvas");

// Trinn 2: Hent 2D-renderingskonteksten
const ctx = canvas.getContext("2d");

// Trinn 3: Sett fyllfarge og tegn et rektangel
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 200, 200); // x, y, bredde, høyde
```

**La oss gå gjennom dette steg for steg:**
- Vi **tar tak** i canvas-elementet vårt ved hjelp av ID og lagrer det i en variabel
- Vi **henter** 2D-renderingskonteksten – dette er verktøykassen vår full av tegnemetoder
- Vi **forteller** canvas at vi vil fylle ting med rødt ved å sette `fillStyle`-egenskapen
- Vi **tegner** et rektangel som starter øverst til venstre (0,0) og som er 200 piksler bredt og høyt

✅ Canvas API fokuserer hovedsakelig på 2D-former, men du kan også tegne 3D-elementer på en nettside; for dette kan du bruke [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API).

Du kan tegne alle slags ting med Canvas API som:

- **Geometriske former**, vi har allerede vist hvordan man tegner et rektangel, men det er mye mer du kan tegne.
- **Tekst**, du kan tegne tekst med hvilken som helst skrift og farge du vil.
- **Bilder**, du kan tegne et bilde basert på bildeassets som for eksempel .jpg eller .png.

✅ Prøv det! Du vet hvordan du tegner et rektangel, kan du tegne en sirkel på en side? Ta en titt på noen interessante Canvas-tegninger på CodePen. Her er et [spesielt imponerende eksempel](https://codepen.io/dissimulate/pen/KrAwx).

### 🔄 **Pedagogisk sjekk**
**Forståelse av lerretets grunnprinsipper**: Før du går over til bildelasting, sørg for at du kan:
- ✅ Forklare hvordan lerretets koordinatsystem skiller seg fra matematiske koordinater
- ✅ Forstå tre-trinnsprosessen for tegneoperasjoner på lerretet
- ✅ Identifisere hva 2D-renderingskonteksten gir deg
- ✅ Beskrive hvordan fillStyle og fillRect fungerer sammen

**Rask selvtest**: Hvordan ville du tegne en blå sirkel på posisjon (100, 50) med radius 25?
```javascript
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(100, 50, 25, 0, 2 * Math.PI);
ctx.fill();
```

**Canvas-tegnemetoder du nå kan:**
- **fillRect()**: Tegner fylte rektangler
- **fillStyle**: Setter farger og mønstre
- **beginPath()**: Starter nye tegnestier
- **arc()**: Lager sirkler og kurver

## Last inn og tegn et bilde

Å tegne grunnleggende former er nyttig for å komme i gang, men de fleste spill trenger faktiske bilder! Sprites, bakgrunner og teksturer gir spillene deres visuelle appell. Å laste og vise bilder på canvas fungerer annerledes enn å tegne geometriske former, men det er enkelt når du først forstår prosessen.

Vi må lage et `Image`-objekt, laste bilde-filen vår (dette skjer asynkront, altså "i bakgrunnen"), og så tegne det på lerretet når det er klart. Denne tilnærmingen sikrer at bildene dine vises riktig uten å blokkere applikasjonen mens de lastes.

```mermaid
sequenceDiagram
    participant JS as JavaScript
    participant Img as Bildeobjekt
    participant Server as Filsystem
    participant Canvas as Canvas-kontekst
    
    JS->>Img: new Image()
    JS->>Img: Sett src-egenskap
    Img->>Server: Forespør bildefil
    Server->>Img: Returner bildedata
    Img->>JS: Utløser onload-hendelse
    JS->>Canvas: drawImage(img, x, y)
    Canvas->>Canvas: Tegn på skjerm
    
    Note over JS,Canvas: Asynkron lasting forhindrer UI-blokkering
```
### Enkel bildelasting

```javascript
const img = new Image();
img.src = 'path/to/my/image.png';
img.onload = () => {
  // Bilde lastet og klart til bruk
  console.log('Image loaded successfully!');
};
```

**Dette skjer i koden:**
- Vi **lager** et helt nytt Image-objekt for å holde vår sprite eller tekstur
- Vi **forteller** det hvilken bildefil som skal lastes ved å sette kilde-stien
- Vi **lytter** etter load-eventet slik at vi vet akkurat når bildet er klart til bruk

### En bedre måte å laste bilder på

Her er en mer robust måte å håndtere bildelasting på som profesjonelle utviklere ofte bruker. Vi pakker bildelastingen inn i en Promise-basert funksjon – denne tilnærmingen, som ble populær da JavaScript Promises ble standard i ES6, gjør koden din mer ryddig og håndterer feil på en god måte:

```javascript
function loadAsset(path) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = path;
    img.onload = () => {
      resolve(img);
    };
    img.onerror = () => {
      reject(new Error(`Failed to load image: ${path}`));
    };
  });
}

// Moderne bruk med async/await
async function initializeGame() {
  try {
    const heroImg = await loadAsset('hero.png');
    const monsterImg = await loadAsset('monster.png');
    // Bilder er nå klare til bruk
  } catch (error) {
    console.error('Failed to load game assets:', error);
  }
}
```

**Dette har vi gjort:**
- **Pakket** all den bildekodelasten inn i en Promise for bedre kontroll
- **Lagt til** feilhåndtering som faktisk sier ifra når noe går galt
- **Brukt** moderne async/await-syntaks fordi det er så mye mer lesbart
- **Inkludert** try/catch-blokker for å håndtere eventuelle feil på en pen måte

Når bildene dine er lastet, er det faktisk ganske enkelt å tegne dem på lerretet:

```javascript
async function renderGameScreen() {
  try {
    // Last inn spillressurser
    const heroImg = await loadAsset('hero.png');
    const monsterImg = await loadAsset('monster.png');

    // Hent lerret og kontekst
    const canvas = document.getElementById("myCanvas");
    const ctx = canvas.getContext("2d");

    // Tegn bilder til bestemte posisjoner
    ctx.drawImage(heroImg, canvas.width / 2, canvas.height / 2);
    ctx.drawImage(monsterImg, 0, 0);
  } catch (error) {
    console.error('Failed to render game screen:', error);
  }
}
```

**La oss gå gjennom dette steg for steg:**
- Vi **laster** både helte- og monsterbildene i bakgrunnen med await
- Vi **tar tak** i canvas-elementet og henter den 2D-renderingskonteksten vi trenger
- Vi **posisjonerer** heltebildet midt i senteret ved hjelp av litt rask koordinatmatematikk
- Vi **plasserer** monsterbildet øverst til venstre for å starte fiendeformasjonen vår
- Vi **fanger** opp eventuelle feil som kan skje under lasting eller visning

```mermaid
flowchart TD
    A[Last inn ressurser] --> B{Alle bilder lastet?}
    B -->|Nei| C[Vis lasting]
    B -->|Ja| D[Hent lerretskontekst]
    C --> B
    D --> E[Rydd skjerm]
    E --> F[Tegn bakgrunn]
    F --> G[Tegn fiendetropp]
    G --> H[Tegn helteskip]
    H --> I[Bruk visuelle effekter]
    I --> J[Render bilde]
    
    subgraph "Rendering Pipeline"
        K[Ressursstyring]
        L[Scene-komposisjon]
        M[Tegneoperasjoner]
        N[Bildeutgang]
    end
    
    style A fill:#e1f5fe
    style J fill:#e8f5e8
    style I fill:#fff3e0
```
## Nå er det på tide å begynne å bygge ditt spill

Nå skal vi sette alt sammen for å skape det visuelle grunnlaget for romspillet ditt. Du har nå en solid forståelse av lerretets grunnleggende konsepter og bildelastingsteknikker, så denne praktiske delen vil lede deg gjennom å bygge en komplett spillskjerm med riktig plasserte sprites.

### Hva du skal bygge

Du skal lage en nettside med et Canvas-element. Den skal vise en svart skjerm `1024*768`. Vi har gitt deg to bilder:

- Helteskip

   ![Helteskip](../../../../translated_images/no/player.dd24c1afa8c71e9b.webp)

- 5*5 monstre

   ![Monsterskip](../../../../translated_images/no/enemyShip.5df2a822c16650c2.webp)

### Anbefalte steg for å starte utvikling

Finn startfilene som er laget for deg i undermappen `your-work`. Prosjektstrukturen din skal inneholde:

```bash
your-work/
├── assets/
│   ├── enemyShip.png
│   └── player.png
├── index.html
├── app.js
└── package.json
```

**Dette jobber du med:**
- **Spill-sprites** ligger i `assets/`-mappen slik at alt holder seg organisert
- **Hoved-HTML-filen** setter opp canvas-elementet og gjør alt klart
- **En JavaScript-fil** hvor du skriver all spill-grafikkmagien din
- **En package.json** som setter opp en utviklingsserver slik at du kan teste lokalt

Åpne denne mappen i Visual Studio Code for å begynne utviklingen. Du trenger et lokalt utviklingsmiljø med Visual Studio Code, NPM og Node.js installert. Hvis du ikke har `npm` satt opp på datamaskinen din, [her er hvordan du installerer det](https://www.npmjs.com/get-npm).

Start utviklingsserveren din ved å navigere til `your-work`-mappen:

```bash
cd your-work
npm start
```

**Denne kommandoen gjør noen ganske kule ting:**
- **Starter** en lokal server på `http://localhost:5000` slik at du kan teste spillet ditt
- **Serverer** alle filene dine skikkelig slik at nettleseren kan laste dem riktig
- **Overvåker** filene dine for endringer så du kan utvikle smidig
- **Gir deg** et profesjonelt utviklingsmiljø for testing

> 💡 **Merk**: Nettleseren din vil vise en blank side i starten – det er som forventet! Når du legger til kode, oppdater nettsiden for å se endringene dine. Denne iterative utviklingsmetoden ligner på hvordan NASA bygde Apollo-veiledningscomputeren – ved å teste hver komponent før man integrerte den i det større systemet.

### Legg til kode

Legg til den nødvendige koden i `your-work/app.js` for å fullføre følgende oppgaver:

1. **Tegn et lerret med svart bakgrunn**
   > 💡 **Slik gjør du det**: Finn TODO-kommentaren i `/app.js` og legg til bare to linjer. Sett `ctx.fillStyle` til svart, deretter bruk `ctx.fillRect()` som starter på (0,0) med lerretsdimensjonene dine. Enkelt!

2. **Last spillteksturer**
   > 💡 **Slik gjør du det**: Bruk `await loadAsset()` for å laste inn spiller- og fiendebildene dine. Lagre dem i variabler slik at du kan bruke dem senere. Husk – de vises ikke før du faktisk tegner dem!

3. **Tegn helteskipet midt nederst på skjermen**
   > 💡 **Slik gjør du det**: Bruk `ctx.drawImage()` til å plassere helten. For x-koordinaten prøv `canvas.width / 2 - 45` for å sentrere, og for y-koordinaten bruk `canvas.height - canvas.height / 4` for å plassere det i bunnområdet.

4. **Tegn en 5×5-formation av fiendeskip**
   > 💡 **Slik gjør du det**: Finn funksjonen `createEnemies` og sett opp en nestet løkke. Du må gjøre litt matematikk for avstand og posisjon, men ikke bekymre deg – jeg skal vise deg nøyaktig hvordan!

Først definer konstanter for korrekt oppsett av fiendeformasjonen:

```javascript
const ENEMY_TOTAL = 5;
const ENEMY_SPACING = 98;
const FORMATION_WIDTH = ENEMY_TOTAL * ENEMY_SPACING;
const START_X = (canvas.width - FORMATION_WIDTH) / 2;
const STOP_X = START_X + FORMATION_WIDTH;
```

**La oss se på hva disse konstantene gjør:**
- Vi **setter** 5 fiender per rad og kolonne (et fint 5×5 rutenett)
- Vi **definerer** hvor mye plass som skal være mellom fiendene slik at de ikke blir for tett
- Vi **regner ut** hvor bred hele formasjonen vil bli
- Vi **finner** ut hvor vi skal starte og stoppe slik at formasjonen ser sentrert ut

```mermaid
flowchart LR
    A["Lerret Bredde: 1024px"] --> B["Formasjonsbredde: 490px"]
    B --> C["Start X: 267px"]
    C --> D["Fiendeavstand: 98px"]
    
    subgraph "5x5 Fiendeformasjon"
        E["Rad 1: Y=0"]
        F["Rad 2: Y=50"]
        G["Rad 3: Y=100"]
        H["Rad 4: Y=150"]
        I["Rad 5: Y=200"]
    end
    
    subgraph "Kolonneavstand"
        J["Kol 1: X=267"]
        K["Kol 2: X=365"]
        L["Kol 3: X=463"]
        M["Kol 4: X=561"]
        N["Kol 5: X=659"]
    end
    
    style A fill:#e1f5fe
    style B fill:#e8f5e8
    style C fill:#fff3e0
```
Deretter oppretter du nestede løkker for å tegne fiendeformasjonen:

```javascript
for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
  for (let y = 0; y < 50 * 5; y += 50) {
    ctx.drawImage(enemyImg, x, y);
  }
}
```

**Dette gjør den nestede løkken:**
- Ytre løkke **beveger** seg fra venstre mot høyre over formasjonen
- Indre løkke **går** fra topp til bunn for å lage pene rader
- Vi **tegner** hver fiendesprite på nøyaktig de x,y-koordinatene vi har regnet ut
- Alt er **jevnt fordelt** slik at det ser profesjonelt og ryddig ut

### 🔄 **Pedagogisk sjekk**
**Mestre spillrendering**: Bekreft at du forstår det komplette gjengivelsessystemet:
- ✅ Hvordan hindrer asynkron bildelasting UI-blokkering under oppstart av spillet?
- ✅ Hvorfor beregner vi fiendeformasjonens posisjoner ved hjelp av konstanter i stedet for hardkodet?
- ✅ Hvilken rolle spiller 2D-renderingskonteksten i tegneoperasjoner?
- ✅ Hvordan lager nestede løkker organiserte spriteformasjoner?

**Ytelseshensyn**: Spillet ditt demonstrerer nå:
- **Effektiv lasting av assets**: Promise-basert bildegjenkjenning
- **Organisert rendering**: Strukturerte tegneoperasjoner
- **Matematisk posisjonering**: Kalkulert plassering av sprites
- **Feilhåndtering**: Pen håndtering av feil

**Konsepter innen visuell programmering**: Du har lært:
- **Koordinatsystemer**: Oversette matematikk til skjermposisjoner
- **Sprite-håndtering**: Laste og vise spillgrafikk
- **Formasjonsalgoritmer**: Matematiske mønstre for organiserte oppsett
- **Asynkrone operasjoner**: Moderne JavaScript for jevn brukeropplevelse

## Resultat

Det ferdige resultatet skal se slik ut:

![Black screen with a hero and 5*5 monsters](../../../../translated_images/no/partI-solution.36c53b48c9ffae2a.webp)

## Løsning

Vennligst prøv å løse det selv først, men hvis du setter fast, ta en titt på en [løsning](../../../../6-space-game/2-drawing-to-canvas/solution/app.js)

---

## GitHub Copilot Agent Challenge 🚀

Bruk Agent-modusen for å fullføre følgende utfordring:

**Beskrivelse:** Forbedre romspillet ditt ved å legge til visuelle effekter og interaktive elementer ved hjelp av Canvas API-teknikker du har lært.

**Prompt:** Lag en ny fil kalt `enhanced-canvas.html` med et canvas som viser animerte stjerner i bakgrunnen, en pulserende helseindikator for helteskipet, og fiendtlige skip som langsomt beveger seg nedover. Inkluder JavaScript-kode som tegner blinkende stjerner med tilfeldige posisjoner og opasitet, implementerer en helseindikator som endrer farge basert på helsenivå (grønn > gul > rød), og animerer fiendeshipene til å bevege seg nedover skjermen i forskjellige hastigheter.

Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.

## 🚀 Utfordring

Du har lært om tegning med den 2D-fokuserte Canvas API; ta en titt på [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API), og forsøk å tegne et 3D-objekt.

## Post-forelesning Quiz

[Post-forelesning quiz](https://ff-quizzes.netlify.app/web/quiz/32)

## Gjennomgang & Selvstudium

Lær mer om Canvas API ved å [lese om det](https://developer.mozilla.org/docs/Web/API/Canvas_API).

### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne nettleserkonsollen og lag et canvas-element med `document.createElement('canvas')`
- [ ] Prøv å tegne et rektangel ved hjelp av `fillRect()` på et canvas-kontekst
- [ ] Eksperimenter med forskjellige farger ved bruk av `fillStyle`-egenskapen
- [ ] Tegn en enkel sirkel ved hjelp av `arc()`-metoden

### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør post-leksjonsquiz og forstå canvas-grunnleggende
- [ ] Lag et tegneprogram med canvas med flere former og farger
- [ ] Implementer bildeinnlasting og sprite-rendering for ditt spill
- [ ] Bygg en enkel animasjon som flytter objekter over canvas
- [ ] Øv på canvas-transformasjoner som skalering, rotasjon og translasjon

### 📅 **Din ukelange Canvas-reise**
- [ ] Fullfør romspillet med polerte grafikker og sprite-animasjoner
- [ ] Mestre avanserte canvas-teknikker som gradienter, mønstre og komposisjon
- [ ] Lag interaktive visualiseringer ved bruk av canvas til datavisualisering
- [ ] Lær om canvas-optimaliseringsteknikker for jevn ytelse
- [ ] Bygg et tegne- eller maleprogram med flere verktøy
- [ ] Utforsk kreative kodingsmønstre og generativ kunst med canvas

### 🌟 **Din månedslange grafikkmestring**
- [ ] Bygg komplekse visuelle applikasjoner med Canvas 2D og WebGL
- [ ] Lær grafikkprogrammeringskonsepter og shader-grunnlag
- [ ] Bidra til open source grafikkbiblioteker og visualiseringsverktøy
- [ ] Mestre ytelsesoptimalisering for grafikk-intensive applikasjoner
- [ ] Lag pedagogisk innhold om canvas-programmering og datagrafikk
- [ ] Bli en ekspert i grafikkprogrammering som hjelper andre å lage visuelle opplevelser

## 🎯 Din tidslinje for Canvas-grafikkmestring

```mermaid
timeline
    title Canvas API Læringsprogresjon
    
    section Canvas Grunnleggende (15 minutter)
        Grunnleggende operasjoner: Elementreferanse
                                : 2D konteksttilgang
                                : Koordinatsystem
                                : Enkel formtegning
        
    section Tegneteknikker (20 minutter)
        Grafikkprimitiver: Firkant og sirkler
                         : Farger og stiler
                         : Tekstgjengivelse
                         : Stioperasjoner
        
    section Bilderhåndtering (25 minutter)
        Ressursstyring: Opprettelse av bildeobjekt
                      : Asynkrone lastemønstre
                      : Feilhåndtering
                      : Ytelsesoptimalisering
        
    section Spillgrafikk (30 minutter)
        Sprite-rendering: Plasseringsalgoritmer
                         : Formasjonsberegninger
                         : Samanstelling av scene
                         : Rammegjengivelse
        
    section Avanserte teknikker (40 minutter)
        Visuelle effekter: Transformasjoner
                          : Animasjoner
                          : Lagdeling
                          : Tilstandshåndtering
        
    section Ytelse (35 minutter)
        Optimalisering: Effektiv tegning
                      : Hukommelsesstyring
                      : Bildefrekvenskontroll
                      : Ressursbufring
        
    section Profesjonelle ferdigheter (1 uke)
        Produksjonsgrafikk: WebGL-integrasjon
                          : Canvas-biblioteker
                          : Spillmotorer
                          : Plattformuavhengige hensyn
        
    section Avansert grafikk (1 måned)
        Spesialiserte applikasjoner: Datavisualisering
                                   : Interaktiv kunst
                                   : Sanntidseffekter
                                   : 3D-grafikk
```
### 🛠️ Oppsummering av ditt Canvas-grafikkverktøy

Etter å ha fullført denne leksjonen har du nå:
- **Canvas API-mestring**: Fullstendig forståelse av 2D-grafikkprogrammering
- **Koordinatmatematikk**: Presis posisjonering og layoutalgoritmer
- **Ressurshåndtering**: Profesjonell bildeinnlasting og feilhåndtering
- **Rendering-pipeline**: Strukturert tilnærming til scene-sammensetning
- **Spillgrafikk**: Sprite-posisjonering og formasjonberegninger
- **Asynkron programmering**: Moderne JavaScript-mønstre for jevn ytelse
- **Visuell programmering**: Oversetting av matematiske konsepter til skjermgrafikk

**Reelle bruksområder**: Dine Canvas-ferdigheter gjelder direkte for:
- **Datavisualisering**: Diagrammer, grafer og interaktive dashbord
- **Spillutvikling**: 2D-spill, simuleringer og interaktive opplevelser
- **Digital kunst**: Kreativ koding og generative kunstprosjekter
- **UI/UX Design**: Tilpasset grafikk og interaktive elementer
- **Pedagogisk programvare**: Visuelle læringsverktøy og simuleringer
- **Nettapplikasjoner**: Dynamisk grafikk og sanntidsvisualiseringer

**Profesjonelle ferdigheter oppnådd**: Du kan nå:
- **Bygge** skreddersydde grafikk-løsninger uten eksterne biblioteker
- **Optimalisere** rendering-ytelsen for jevn brukeropplevelse
- **Feilsøke** komplekse visuelle problemer med nettleserens utviklerverktøy
- **Designe** skalerbare grafikk-systemer ved hjelp av matematiske prinsipper
- **Integrere** Canvas-grafikk med moderne webapplikasjonsrammeverk

**Canvas API-metoder du har mestret**:
- **Elementhåndtering**: getElementById, getContext
- **Tegneoperasjoner**: fillRect, drawImage, fillStyle
- **Ressursinnlasting**: Image-objekter, Promise-mønstre
- **Matematisk posisjonering**: Koordinatberegninger, formasjonalgoritmer

**Neste nivå**: Du er klar for å legge til animasjon, brukerinteraksjon, kollisjonsdeteksjon, eller utforske WebGL for 3D-grafikk!

🌟 **Oppnåelse låst opp**: Du har bygget et komplett spillrenderingssystem ved bruk av grunnleggende Canvas API-teknikker!

## Oppgave

[Lek med Canvas API](assignment.md)

---

<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket bør betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->