Het creƫren van een multiplayer webgame in het .io-genre

Het creƫren van een multiplayer webgame in het .io-genre
Uitgebracht in 2015 Agar.io werd de grondlegger van een nieuw genre van .io-spellen, waarvan de populariteit sindsdien sterk is toegenomen. De groei van de populariteit van .io-spellen heb ik zelf ervaren: in de afgelopen drie jaar heb ik twee spellen in dit genre gemaakt en verkocht..

Voor het geval je nog nooit van dergelijke spellen hebt gehoord: dit zijn gratis multiplayer webspellen waaraan je gemakkelijk kunt deelnemen (er is geen account vereist). Gewoonlijk draaien ze om het strijden tussen veel tegenstanders op ƩƩn arena. Andere beroemde spellen in het .io-genre zijn: Slither.io en Diep.io.

In dit bericht gaan we bekijken hoe je een .io-spel vanaf nul kunt maken. Hiervoor heb je alleen kennis van Javascript nodig: je moet dingen begrijpen zoals de syntaxis ES6, het sleutelwoord this en Belofte. Zelfs als je Javascript niet perfect kent, kun je nog steeds het grootste deel van het bericht begrijpen.

Voorbeeld van een .io-spel

Ter ondersteuning van het leren zullen we verwijzen naar het voorbeeld van een .io-spel. Probeer het te spelen!

Het creƫren van een multiplayer webgame in het .io-genre
Het spel is behoorlijk eenvoudig: je bestuurt een ruimteschip op een arena met andere spelers. Je schip schiet automatisch projectielen en je probeert andere spelers te raken, terwijl je tegelijkertijd hun projectielen probeert te ontwijken.

1. Korte overzicht/structuur van het project

Ik raad je aan de broncode te downloaden van het voorbeeldspel, zodat je mij kunt volgen.

In het voorbeeld worden de volgende dingen gebruikt:

  • Express is het populairste webframework voor Node.js, dat de webserver van het spel beheert.
  • socket.io is een websocketbibliotheek voor het uitwisselen van gegevens tussen de browser en de server.
  • Webpack is een modulebeheerder. Over waarom je Webpack moet gebruiken, kun je lezen hier.

Dit is hoe de projectdirectorystructuur eruit ziet:

public/
    assets/
        ...
src/
    client/
        css/
            ...
        html/
            index.html
        index.js
        ...
    server/
        server.js
        ...
    shared/
        constants.js

public/

Alles in de map public/ zal statisch door de server worden aangeboden. In public/assets/ staan de afbeeldingen die door ons project worden gebruikt.

src/

Alle broncode staat in de map src/. De namen . ā”œā”€ā”€ client.py └── Dockerfile 0 mappen, 2 bestanden en server/ moeten eruitzien: . ā”œā”€ā”€ Dockerfile ā”œā”€ā”€ index.html └── server.py 0 mappen, 3 bestanden spreken voor zich, en shared/ bevat een constante bestand dat wordt geĆÆmporteerd door zowel de client als de server.

2. Builds/projectparameters

Zoals eerder vermeld, gebruiken we een modulebeheerder voor het bouwen van het project. WebpackLaten we een kijkje nemen naar onze Webpack-configuratie:

webpack.common.js:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: {
    game: '.\/src\/client\/index.js',
  },
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: \/\.js$\/, 
        exclude: \/node_modules\/, 
        use: {
          loader: "babel-loader",
          options: {
            presets: ['@babel\/preset-env'],
          },
        },
      },
      {
        test: \/\.css$\/, 
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          'css-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'src\/client\/html\/index.html',
    }),
  ],
};

De belangrijkste regels hier zijn de volgende:

  • src/client/index.js — dit is het toegangspunt voor de Javascript (JS) client. Webpack zal hier beginnen en andere geĆÆmporteerde bestanden recursief zoeken.
  • De uitvoer-JS van onze Webpack-bundel zal zich bevinden in de map dist\/. Ik zal dit bestand onze JS-bundel.
  • Wij gebruiken Babelnoemen, en specifiek de configuratie van @babel\/preset-env voor het transpilen van onze JS-code voor oudere browsers.
  • We gebruiken een plugin om alle CSS die door de JS-bestanden worden aangesproken te extraheren en ze op ƩƩn plek samen te voegen. Ik zal dit onze CSS-bundel.

noemen. Je hebt misschien vreemde bestandsnamen voor de bundels opgemerkt '[name].[contenthash].ext'. Er zijn bestandsnaam placeholders Webpack: [name] zal worden vervangen door de naam van het toegangspunt (in ons geval is dat game), terwijl [contenthash] zal worden vervangen door de hash van de inhoud van het bestand. We doen dit om het project te optimaliseren voor hashing — we kunnen de browsers vertellen om onze JS-bundels oneindig te cachen, omdat als de bundel verandert, verandert ook de bestandsnaam (de contenthash). Het eindresultaat zal een bestandsnaam zijn zoals game.dbeee76e91a97d0c7207.js.

Bestand webpack.common.js — dit is het basisconfiguratiebestand dat we importeren in de ontwikkelings- en productieconfiguraties. Hier is bijvoorbeeld de ontwikkelingsconfiguratie:

webpack.dev.js

const merge = require('webpack-merge');
const common = require('.\/webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
});

Voor efficiƫntie gebruiken we tijdens de ontwikkeling webpack.dev.js, en schakelt naar webpack.prod.js, om de bundelgrootte te optimaliseren bij het uitrollen naar productie.

Lokale setup

Ik raad aan om het project op je lokale machine op te zetten, zodat je de stappen kunt volgen die in deze post staan. De setup is eenvoudig: ten eerste moet Node en NPMop je systeem zijn geĆÆnstalleerd.

$ git clone https:\/\/github.com\/vzhou842\/example-.io-game.git
$ cd example-.io-game
$ npm install

en u bent klaar om te beginnen! Om de ontwikkelingsserver te starten, hoeft u alleen maar

$ npm run develop

te bezoeken in uw webbrowser op localhost:3000. De ontwikkelingsserver zal automatisch opnieuw JS- en CSS-pakketten samenstellen tijdens het wijzigen van de code — ververs gewoon de pagina om alle wijzigingen te zien!

3. Klantpunten

Laten we beginnen met de eigenlijke gamecode. Eerst hebben we een pagina nodig index.html, die de browser zal laden wanneer de site wordt bezocht. Onze pagina zal vrij eenvoudig zijn:

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Een voorbeeld .io spel</title>
  <link type="text/css" rel="stylesheet" href="/game.bundle.css">
</head>
<body>
  <canvas id="game-canvas"></canvas>
  <script async src="/game.bundle.js"></script>
  <div id="play-menu" class="hidden">
    <input type="text" id="username-input" placeholder="gebruikersnaam" />
    <button id="play-button">SPELEN</button>
  </div>
</body>
</html>

Dit codevoorbeeld is een beetje vereenvoudigd voor de duidelijkheid, hetzelfde zal ik doen met vele andere voorbeelden in de post. De volledige code is altijd te bekijken op Github.

We hebben:

  • HTML5 Canvas-element (<canvas>), dat we zullen gebruiken voor het renderen van het spel.
  • <link> om ons CSS-pakket toe te voegen.
  • <script> om ons Javascript-pakket toe te voegen.
  • Hoofdmenu met gebruikersnaam