Sådan bygger du et simpelt spil i browseren med Phaser 3 og TypeScript

Foto af Phil Botha på Unsplash

Jeg er en talsmand for udvikleren og en backend-udvikler, og min ekspertise inden for frontend-udvikling er relativt svag. For et stykke tid siden ønskede jeg at have det sjovt og lave et spil i en browser; Jeg valgte Phaser 3 som ramme (det ser meget populært ud i disse dage) og TypeScript som sprog (fordi jeg foretrækker statisk indtastning frem for dynamisk). Det viste sig, at du skal gøre nogle kedelige ting for at det hele skal fungere, så jeg skrev denne tutorial for at hjælpe de andre mennesker som mig med at komme hurtigere i gang.

Klargøring af miljøet

IDE

Vælg dit udviklingsmiljø. Du kan altid bruge almindeligt gammelt notesblok, hvis du ønsker det, men jeg vil foreslå at bruge noget mere nyttigt. Hvad mig angår, foretrækker jeg at udvikle kæledyrsprojekter i Emacs, derfor har jeg installeret tidevand og fulgt instruktionerne for at opsætte det.

Node

Hvis vi udviklede på JavaScript, ville det være helt fint at starte kodningen uden alle disse forberedelsestrin. Da vi imidlertid ønsker at bruge TypeScript, er vi nødt til at konfigurere infrastrukturen for at gøre den fremtidige udvikling så hurtig som muligt. Derfor er vi nødt til at installere node og npm.

Når jeg skriver denne tutorial, bruger jeg node 10.13.0 og npm 6.4.1. Bemærk, at versionerne i frontend-verdenen opdateres ekstremt hurtigt, så du tager blot de nyeste stabile versioner. Jeg anbefaler kraftigt at bruge nvm i stedet for at installere node og npm manuelt; det sparer dig meget tid og nerver.

Opsætning af projektet

Projektstruktur

Vi bruger npm til at opbygge projektet, så for at starte projektet skal du gå til en tom mappe og køre npm init. npm vil stille dig flere spørgsmål om dine projektegenskaber og derefter oprette en package.json-fil. Det ser sådan ud:

{
  "name": "Starfall",
  "version": "0.1.0",
  "description": "Starfall-spil (Phaser 3 + TypeScript)",
  "main": "index.js",
  "scripts": {
    "test": "echo \" Fejl: ingen test specificeret \ "&& exit 1"
  },
  "forfatter": "Mariya Davydova",
  "licens": "MIT"
}

pakker

Installer de pakker, vi har brug for, med følgende kommando:

npm installere -D typeskrift webpack webpack-cli ts-loader phaser live-server

-D-valgmulighed (a.k.a. - save-dev) gør, at npm automatisk tilføjer disse pakker til listen over afhængigheder i package.json:

"afhængighed": {
   "live-server": "^ 1.2.1",
   "phaser": "^ 3.15.1",
   "ts-loader": "^ 5.3.0",
   "typescript": "^ 3.1.6",
   "webpack": "^ 4.26.0",
   "webpack-cli": "^ 3.1.2"
 }

Webpack

Webpack kører TypeScript-kompilatoren og samler bunken af ​​de resulterende JS-filer såvel som biblioteker i en minificeret JS, så vi kan inkludere den på vores side.

Tilføj webpack.config.js i nærheden af ​​dit project.json:

const path = kræve ('sti');
module.exports = {
  post: './src/app.ts',
  modul: {
    regler: [
      {
        test: /\.tsx?$/,
        brug: 'ts-loader',
        ekskludere: / node_modules /
      }
    ]
  },
  beslutte: {
    udvidelser: ['.ts', '.tsx', '.js']
  },
  output: {
    filnavn: 'app.js',
    sti: path.resolve (__ dirname, 'dist')
  },
  tilstand: 'udvikling'
};

Her ser vi, at webpack skal hente kilderne fra src / app.ts (som vi snart vil tilføje) og samle alt i dist / app.js-filen.

maskinskrift

Vi har også brug for en lille konfigurationsfil til TypeScript-kompilatoren (tsconfig.json), hvor vi forklarer, hvilken JS-version vi ønsker, at kilderne skal kompileres til, og hvor vi kan finde disse kilder:

{
  "compilerOptions": {
    "mål": "es5"
  },
  "inkluderer": [
    "Src / *"
  ]
}

TypeScript-definitioner

TypeScript er et statisk typisk sprog. Derfor kræver det typedefinitioner for samlingen. På det tidspunkt, hvor denne tutorial blev skrevet, var definitionerne for Phaser 3 endnu ikke tilgængelige som npm-pakken, så du skal muligvis downloade dem fra det officielle arkiv og sætte filen i src-undermappen for dit projekt.

Scripts

Vi er næsten færdige med det oprettede projekt. I dette øjeblik skulle du have oprettet package.json, webpack.config.js og tsconfig.json og tilføjet src / phaser.d.ts. Den sidste ting, vi skal gøre, før vi begynder at skrive kode, er at forklare, hvad npm nøjagtigt har at gøre med projektet. Vi opdaterer scriptsafsnittet i package.json som følger:

"scripts": {
  "build": "webpack",
  "start": "webpack - watch & live-server --port = 8085"
}

Når du udfører npm build, vil app.js-filen bygges i henhold til webpack-konfigurationen. Og når du kører npm-start, behøver du ikke bekymre dig om byggeprocessen: så snart du gemmer en kilde, genopbygger webpack appen, og live-serveren genindlæser den i din standardbrowser. Appen hostes på http://127.0.0.1:8085/.

Kom godt i gang

Nu hvor vi har konfigureret infrastrukturen (den del, jeg personligt hader, når jeg starter et projekt), kan vi endelig begynde at kode. I dette trin gør vi en enkel ting: tegne et mørkeblå rektangel i vores browservindue. Brug af en stor spiludviklingsramme til dette er en lille smule ... hmmm ... overdreven. Vi har stadig brug for det på de næste trin.

Lad mig kort forklare hovedbegreberne i Phaser 3. Spillet er et eksempel på Phaser.Game-klassen (eller dets efterkommer). Hvert spil indeholder et eller flere tilfælde af Phaser.Scene efterkommere. Hver scene indeholder flere objekter, enten statiske eller dynamiske, og repræsenterer en logisk del af spillet. For eksempel vil vores trivielle spil have tre scener: velkomstskærmen, selve spillet og scoringsskærmen.

Lad os begynde at kode.

Opret først en minimalistisk HTML-container til spillet. Opret en index.html-fil, der indeholder følgende kode:



  
     Starfall </ title>
    
  </ Head>
  <Body>
    <div id = "game"> </div>
  </ Body>
</ Html></pre><p>Der er kun to vigtige dele her: den første er en scriptindgang, der siger, at vi vil bruge vores indbyggede fil her, og den anden er en divindgang, der vil være spilcontaineren.</p><p>Opret nu en fil src / app.ts med følgende kode:</p><pre>import "phaser";</pre><pre>const config: GameConfig = {
  titel: "Starfall",
  bredde: 800,
  højde: 600,
  forælder: "spil"
  baggrund Farve: "# 18216D"
};</pre><pre>eksportklasse StarfallGame udvider Phaser.Game {
  konstruktør (config: GameConfig) {
    super (config);
  }
}</pre><pre>windows.onload = () => {
  var spil = nyt StarfallGame (config);
};</pre><p>Denne kode er selvforklarende. GameConfig har mange forskellige egenskaber, du kan tjekke dem her.</p><p>Og nu kan du endelig køre npm start. Hvis alt blev gjort korrekt på dette og tidligere trin, skal du se noget så simpelt som dette i din browser:</p><img alt="Ja, dette er en blå skærm." src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1569967675050.png" /><h3>At få stjernerne til at falde</h3><p>Vi har oprettet en elementær applikation. Nu er det tid til at tilføje en scene, hvor noget vil ske. Vores spil vil være enkelt: stjernerne falder til jorden, og målet er at fange så mange som muligt.</p><p>For at nå dette mål skal du oprette en ny fil, gameScene.ts, og tilføje følgende kode:</p><pre>import "phaser";</pre><pre>eksportklasse GameScene udvider Phaser.Scene {</pre><pre>konstruktør () {
    super({
      nøgle: "GameScene"
    });
  }</pre><pre>init (params): ugyldig {
    // AT GØRE
  }</pre><pre>preload (): ugyldig {
    // AT GØRE
  }
  
  oprette (): ugyldig {
    // AT GØRE
  }</pre><pre>opdatering (tid): annulleret {
    // AT GØRE
  }
};</pre><p>Konstruktør her indeholder en nøgle, under hvilken andre scener kan kalde denne scene.</p><p>Du ser her stubber for fire metoder. Lad mig kort forklare forskellen mellem derefter:</p><ul><li>init ([params]) kaldes, når scenen starter; denne funktion accepterer muligvis parametre, der sendes fra andre scener eller spil ved at kalde scene.start (tast, [params])</li><li>preload () kaldes, inden sceneobjekter oprettes, og det indeholder indlæsning af aktiver; disse aktiver er cachelagret, så når scenen genstartes, genindlæses de ikke</li><li>create () kaldes, når aktiverne indlæses og indeholder normalt oprettelse af de vigtigste spilobjekter (baggrund, spiller, forhindringer, fjender osv.)</li><li>opdatering ([tid]) kaldes hvert kryds og indeholder den dynamiske del af scenen - alt, hvad der bevæger sig, blinker osv.</li></ul><p>For at være sikker på, at vi ikke glemmer det senere, skal vi hurtigt tilføje følgende linjer i game.ts:</p><pre>import "phaser";
import {GameScene} fra "./gameScene";</pre><pre>const config: GameConfig = {
  titel: "Starfall",
  bredde: 800,
  højde: 600,
  forælder: "spil",
  scene: [GameScene],
  fysik: {
    standard: "arkade",
    arkade: {
      debug: falsk
    }
  },
  baggrund Farve: "# 000033"
};
...</pre><p>Vores spil ved nu om spillescenen. Hvis spilkonfigurationen indeholder en liste med scener, startes den første, når spillet startes, og alle andre oprettes, men først startes, før de udtrykkeligt kaldes.</p><p>Vi har også tilføjet arkadefysik her. Det kræves for at få vores stjerner til at falde.</p><p>Nu kan vi lægge kød på knoglerne i vores spil.</p><p>Først erklærer vi nogle egenskaber og genstande, vi får brug for:</p><pre>eksportklasse GameScene udvider Phaser.Scene {
  delta: antal;
  lastStarTime: antal;
  stjernerFanget: antal;
  stjernerFallen: antal;
  sand: Phaser.Physics.Arcade.StaticGroup;
  info: Phaser.GameObjects.Text;
...</pre><p>Derefter initialiserer vi tal:</p><pre>init (/ * params: any * /): ugyldig {
    dette = 1000;
    this.lastStarTime = 0;
    dette.stjerner = 0;
    dette.stjernerFallen = 0;
  }</pre><p>Nu indlæser vi et par billeder:</p><pre>preload (): ugyldig {
    this.load.setBaseURL (
      "https://raw.githubusercontent.com/mariyadavydova/" +
      "Starfall-phaser3-maskinskrift / master /");
    this.load.image ("stjerne", "aktiver / star.png");
    this.load.image ("sand", "aktiver / sand.jpg");
  }</pre><p>Derefter kan vi forberede vores statiske komponenter. Vi skaber jorden, hvor stjernerne falder, og teksten informerer os om den aktuelle score:</p><pre>oprette (): ugyldig {
    this.sand = this.physics.add.staticGroup ({
      nøgle: 'sand',
      frameQuantity: 20
    });
    Phaser.Actions.PlaceOnLine (this.sand.getChildren (),
      ny Phaser.Geom.Line (20, 580, 820, 580));
    this.sand.refresh ();</pre><pre>this.info = this.add.text (10, 10, '',
      {font: '24px Arial Bold', udfyld: '#FBFBAC'});
  }</pre><p>En gruppe i Phaser 3 er en måde at oprette en masse af de objekter, du vil kontrollere sammen. Der er to typer objekter: statisk og dynamisk. Som du måske gætter, bevæger ikke statiske genstande sig (jord, vægge, forskellige forhindringer), mens dynamiske gør jobbet (Mario, skibe, missiler).</p><p>Vi opretter en statisk gruppe af jordstykkerne. Disse stykker er placeret langs linjen. Bemærk, at linjen er opdelt i 20 lige store sektioner (ikke 19, som du måske havde forventet), og jordpladerne er placeret på hvert afsnit i venstre ende med flisecentret placeret på det tidspunkt (jeg håber, at dette forklarer dem numre). Vi er også nødt til at kalde opdatering () for at opdatere gruppeafgrænsningsfeltet (ellers kontrolleres kollisionerne mod standardplaceringen, der er øverste venstre hjørne af scenen).</p><p>Hvis du tjekker din ansøgning i browseren nu, skal du se noget lignende:</p><img alt="Blue screen evolution" src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1569967676394.png" /><p>Vi er endelig nået til den mest dynamiske del af denne sceneopdateringsfunktion, hvor stjernerne falder. Denne funktion kaldes et sted omkring en gang på 60 ms. Vi ønsker at udsende en ny faldende stjerne hvert sekund. Vi bruger ikke en dynamisk gruppe til dette, da hver stjernes livscyklus vil være kort: Den ødelægges enten ved brugerklik eller ved at kollidere med jorden. Derfor opretter vi funktionen emitStar () en ny stjerne og tilføjer behandlingen af ​​to begivenheder: onClick () og onCollision ().</p><pre>opdatering (tid: antal): ugyldig {
    var diff: antal = tid - dette.lastStarTime;
    if (diff> this.delta) {
      this.lastStarTime = tid;
      if (this.delta> 500) {
        denne.delta - = 20;
      }
      this.emitStar ();
    }
    this.info.text =
      dette.stjerner fanget + "fanget -" +
      this.starsFallen + "fallen (max 3)";
  }</pre><pre>privat onClick (stjerne: Phaser.Physics.Arcade.Image): () => annulleret {
    returfunktion () {
      star.setTint (0x00ff00);
      star.setVelocity (0, 0);
      dette.stjerner fanget + = 1;
      this.time.delayedCall (100, funktion (stjerne) {
        star.destroy ();
      }, [stjerne], dette);
    }
  }</pre><pre>privat onFall (stjerne: Phaser.Physics.Arcade.Image): () => annulleret {
    returfunktion () {
      star.setTint (0xff0000);
      dette.stjernerFallen + = 1;
      this.time.delayedCall (100, funktion (stjerne) {
        star.destroy ();
      }, [stjerne], dette);
    }
  }</pre><pre>private emitStar (): ugyldig {
    var stjerne: Phaser.Physics.Arcade.Image;
    var x = Phaser.Math. Mellem (25, 775);
    var y = 26;
    stjerne = this.physics.add.image (x, y, "stjerne");</pre><pre>star.setDisplaySize (50, 50);
    star.setVelocity (0, 200);
    star.setInteractive ();</pre><pre>star.on ('pointerdown', this.onClick (star), dette);
    this.physics.add.collider (stjerne, dette.sand,
      this.onFall (stjerne), null, dette);
  }</pre><p>Endelig har vi et spil! Det har endnu ikke en win-betingelse. Vi tilføjer det i den sidste del af vores tutorial.</p><img alt="Jeg er dårlig til at fange stjerner ..." src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1569967677698.png" /><h3>Indpakning af det hele</h3><p>Normalt består et spil af flere scener. Selvom gameplayet er enkelt, har du brug for en åbningsscene (indeholdende mindst "Play!" -Knappen) og en afsluttende (der viser resultatet af din spilsession, som scoringen eller det maksimale niveau, der er nået). Lad os tilføje disse scener til vores applikation.</p><p>I vores tilfælde vil de være temmelig ens, da jeg ikke ønsker at være for meget opmærksom på det grafiske design af spillet. Når alt kommer til alt er dette en programmeringsvejledning.</p><p>Velkomstscenen har følgende kode i WelcomeScene.ts. Bemærk, at når en bruger klikker et sted på denne scene, vises en spillescene.</p><pre>import "phaser";</pre><pre>eksportklasse WelcomeScene udvider Phaser.Scene {
  titel: Phaser.GameObjects.Text;
  tip: Phaser.GameObjects.Text;</pre><pre>konstruktør () {
    super({
      nøgle: "WelcomeScene"
    });
  }</pre><pre>oprette (): ugyldig {
    var titleText: string = "Starfall";
    this.title = this.add.text (150, 200, titleText,
      {font: '128px Arial Bold', udfyld: '#FBFBAC'});</pre><pre>var hintText: string = "Klik for at starte";
    this.hint = this.add.text (300, 350, hintText,
      {font: '24px Arial Bold', udfyld: '#FBFBAC'});</pre><pre>this.input.on ('pointerdown', funktion (/ * pointer * /) {
      this.scene.start ( "GameScene");
    }, dette);
  }
};</pre><p>Scorescenen ser næsten den samme ud, hvilket fører til velkomstscenen på klik (scoreScene.ts).</p><pre>import "phaser";</pre><pre>eksportklasse ScoreScene udvider Phaser.Scene {
  score: antal
  resultat: Phaser.GameObjects.Text;
  tip: Phaser.GameObjects.Text;</pre><pre>konstruktør () {
    super({
      nøgle: "ScoreScene"
    });
  }</pre><pre>init (params: any): ugyldig {
    this.score = params.starsFanget;
  }</pre><pre>oprette (): ugyldig {
    var resultText: string = 'Din score er' + this.score + '!';
    this.result = this.add.text (200, 250, resultText,
      {font: '48px Arial Bold', udfyld: '#FBFBAC'});</pre><pre>var hintText: string = "Klik for at genstarte";
    this.hint = this.add.text (300, 350, hintText,
      {font: '24px Arial Bold', udfyld: '#FBFBAC'});</pre><pre>this.input.on ('pointerdown', funktion (/ * pointer * /) {
      this.scene.start ( "WelcomeScene");
    }, dette);
  }
};</pre><p>Vi skal opdatere vores vigtigste applikationsfil nu: tilføje disse scener og gøre WelcomeScene til at være den første på listen:</p><pre>import "phaser";
import {WelcomeScene} fra "./welcomeScene";
import {GameScene} fra "./gameScene";
import {ScoreScene} fra "./scoreScene";</pre><pre>const config: GameConfig = {
  ...
  scene: [WelcomeScene, GameScene, ScoreScene],
  ...</pre><p>Har du bemærket, hvad der mangler? Okay, vi kalder ikke ScoreScene hvor som helst endnu! Lad os kalde det, når afspilleren har savnet den tredje stjerne:</p><pre>privat onFall (stjerne: Phaser.Physics.Arcade.Image): () => annulleret {
    returfunktion () {
      star.setTint (0xff0000);
      dette.stjernerFallen + = 1;
      this.time.delayedCall (100, funktion (stjerne) {
        star.destroy ();
        if (this.starsFallen> 2) {
          this.scene.start ( "ScoreScene",
            {starsFangst: dette.stjerner fanget});
        }
      }, [stjerne], dette);
    }
  }</pre><p>Endelig ser vores Starfall-spil ud som et rigtigt spil - det starter, slutter og har endda et mål at arkivere (hvor mange stjerner kan du fange?).</p><p>Jeg håber, at denne tutorial er lige så nyttig for dig, som den var for mig, da jeg skrev det :) Enhver feedback er meget værdsat!</p><p>Kildekoden til denne tutorial findes her.</p></div><div class="neighbor-articles"><h4 class="ui header">Se også</h4><a href="/question/how-to-connect-samsung-note-5-to-computer/" title="hvordan man forbinder samsung note 5 til computeren">hvordan man forbinder samsung note 5 til computeren</a><a href="/question/how-to-turn-on-epson-projector-without-remote/" title="hvordan man tænder for epson projektor uden fjernbetjening">hvordan man tænder for epson projektor uden fjernbetjening</a><a href="/question/how-to-determine-if-a-matrix-is-singular/" title="hvordan man bestemmer, om en matrix er ental">hvordan man bestemmer, om en matrix er ental</a><a href="/question/how-to-paralyze-yourself/" title="hvordan man lammer sig selv">hvordan man lammer sig selv</a><a href="/question/how-to-say-wet-paint-in-spanish/" title="hvordan man siger våd maling på spansk">hvordan man siger våd maling på spansk</a><a href="/question/how-to-install-avada/" title="hvordan man installerer avada">hvordan man installerer avada</a><a href="/question/how-to-test-for-endogeneity/" title="hvordan man tester for endogenitet">hvordan man tester for endogenitet</a><a href="/question/how-to-open-a-stapler-all-the-way/" title="hvordan man åbner en hæftemaskine hele vejen">hvordan man åbner en hæftemaskine hele vejen</a></div></div><div class="article-sidebar"><div class="neighbor-articles"><h4 class="ui header">Se også</h4><a href="/article/the-burden-of-making-decisions-and-how-to-break-the-toxic-cycle-of-procrastination-51b2e8/" title="Byrden ved at træffe beslutninger og hvordan man bryder den giftige cyklus med udskillelse.">Byrden ved at træffe beslutninger og hvordan man bryder den giftige cyklus med udskillelse.</a><a href="/article/how-to-make-work-better-bcc75a/" title="Sådan gør du arbejdet bedre">Sådan gør du arbejdet bedre</a><a href="/article/a-practical-guide-on-how-to-stop-people-pleasing-and-start-being-yourself-50e709/" title="En praktisk guide til, hvordan man stopper folk, der glæder sig og begynder at være dig selv">En praktisk guide til, hvordan man stopper folk, der glæder sig og begynder at være dig selv</a><a href="/article/how-to-update-the-apollo-client-s-cache-after-a-mutation-929230/" title="Sådan opdateres Apollo-klientens cache efter en mutation">Sådan opdateres Apollo-klientens cache efter en mutation</a><a href="/article/how-to-put-the-reader-in-the-story-with-description-aabaab/" title="Sådan placeres læseren i historien med beskrivelse">Sådan placeres læseren i historien med beskrivelse</a><a href="/article/how-to-start-a-successful-side-hustle-and-make-1000-mo-or-more-98634d/" title="Sådan starter du et vellykket sidevink og tjener $ 1000 / mo eller mere">Sådan starter du et vellykket sidevink og tjener $ 1000 / mo eller mere</a><a href="/article/how-to-optimize-your-writing-toolbox-and-determine-what-type-of-writer-you-want-to-be-d2d588/" title="Sådan optimeres din skriveværktøjskasse og afgør, hvilken type forfatter du vil være">Sådan optimeres din skriveværktøjskasse og afgør, hvilken type forfatter du vil være</a><a href="/article/how-to-handle-adult-temper-tantrums-982625/" title="Sådan håndteres voksne tantrums for voksne">Sådan håndteres voksne tantrums for voksne</a></div></div></div></main><div class="push"></div></div><footer><div class="flags-footer"><a href="https://uz.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="uz flag"></i></a><a href="https://bg.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="bg flag"></i></a><a href="https://et.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ee flag"></i></a><a href="https://lt.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="lt flag"></i></a><a href="https://lv.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="lv flag"></i></a><a href="https://sr.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="rs flag"></i></a><a href="https://sl.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="si flag"></i></a><a href="https://sk.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="sk flag"></i></a><a href="https://uk.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ua flag"></i></a><a href="https://sq.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="al flag"></i></a><a href="https://hy.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="am flag"></i></a><a href="https://is.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="is flag"></i></a><a href="https://az.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="az flag"></i></a><a href="https://kk.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="kz flag"></i></a><a href="https://fa.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ir flag"></i></a><a href="https://tg.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="tj flag"></i></a><a href="https://ga.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ie flag"></i></a><a href="https://be.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="by flag"></i></a><a href="https://ka.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ge flag"></i></a><a href="https://ky.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="kg flag"></i></a><a href="https://lb.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="lu flag"></i></a><a href="https://lo.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="la flag"></i></a><a href="https://ar.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="sa flag"></i></a><a href="https://bn.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="in flag"></i></a><a href="https://ca.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="es flag"></i></a><a href="https://zh.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="cn flag"></i></a><a href="https://hr.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="hr flag"></i></a><a href="https://cs.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="cz flag"></i></a><a href="https://nl.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="nl flag"></i></a><a href="https://tl.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ph flag"></i></a><a href="https://fi.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="fi flag"></i></a><a href="https://fr.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="fr flag"></i></a><a href="https://de.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="de flag"></i></a><a href="https://el.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="gr flag"></i></a><a href="https://iw.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="il flag"></i></a><a href="https://hi.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="in flag"></i></a><a href="https://hu.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="hu flag"></i></a><a href="https://id.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="id flag"></i></a><a href="https://it.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="it flag"></i></a><a href="https://ja.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="jp flag"></i></a><a href="https://ko.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="kr flag"></i></a><a href="https://ms.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="my flag"></i></a><a href="https://mr.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="io flag"></i></a><a href="https://no.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="no flag"></i></a><a href="https://pl.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="pl flag"></i></a><a href="https://pt.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="pt flag"></i></a><a href="https://ro.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ro flag"></i></a><a href="https://ru.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ru flag"></i></a><a href="https://internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="es flag"></i></a><a href="https://sv.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="ch flag"></i></a><a href="https://ta.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="sg flag"></i></a><a href="https://te.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="in flag"></i></a><a href="https://th.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="th flag"></i></a><a href="https://tr.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="tr flag"></i></a><a href="https://ur.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="pk flag"></i></a><a href="https://vi.internautasporlapaz.org/article/how-to-build-a-simple-game-in-the-browser-with-phaser-3-and-typescript-dede14/"><i class="vn flag"></i></a></div>internautasporlapaz.org<!-- --> © <!-- -->2021<!-- --> </footer></div></div></div></body></html>