10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

webpack+VSCodeで、Vanilla JS+Canvas APIの簡単なゲーム開発準備

Last updated at Posted at 2018-09-17

13KB以下でHTMLゲームを開発するコンテスト js13kGames のために、とても簡単なゲーム開発の環境を構築しました。

やることは単なる伝統的なCanvas API操作なのですが、ファイルサイズを抑えるため一切ライブラリを同梱しないVanilla JSで記述していきます。ECMAScript 2015+(ES6+)で開発し、webpackでビルドします。Visual Studio CodeのJavaScript開発支援機能も少し使っていきます。

js13kGamesについて

下記の記事が詳しいです。

js13kGamesは参加してみて結構面白いと思ったのですが、日本語の情報があまり見つかりませんでした。もし来年以降も開催されるならば初学者の方が参加しやすくなるよう、このような単純な開発環境の構築手順をメモしておきます。

環境

  • Windows Subsystem for Linux / Ubuntu 16.04.4 LTS
    • たぶんMacでもほぼ同じです
  • node 9.4.0
  • npm 6.4.1
  • webpack 4.19.0
  • Visual Studio Code 1.27.2

jQuery, Lodash, Phaserのようなパッケージは一切使いません。

作成

適当な名前でリポジトリを作ります。ここではmy-gameとします。

$ mkdir my-game
$ cd my-game
$ git init
$ curl 'https://raw.githubusercontent.com/github/gitignore/master/Node.gitignore' > .gitignore

package-lock.jsongit diffの出力結果に混ざって欲しくない場合は、バイナリ扱いにしておきます。

$ echo 'package-lock.json binary' >> .gitattributes

webpackによるビルドの設定

まずpackage.jsonを作成します。
npm initで作成できますが、回答は適当で構いません。

$ npm init

webpackをインストールします。

$ npm install --save-dev webpack webpack-cli webpack-merge

本番出力用のwebpack.config.jsを作成します。

webpack.config.js
module.exports = {
  mode: 'production',
  entry: './src/index.js',
};

開発時に使うためのwebpack.dev.jsを作成します。

webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.config.js');
module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
});

webpack --config webpack.config.jsで本番用のビルドを、webpack --config webpack.dev.jsで開発用のビルドをします。これらのコマンドを実行しやすいよう npm scripts に記述しておきます。

最終的にpackage.jsonはこんな感じになります。

package.json
{
  "private": true,
  "scripts": {
    "prepare": "webpack --config webpack.config.js",
    "watch": "webpack --config webpack.dev.js --watch"
  },
  "devDependencies": {
    "webpack": "^4.19.0",
    "webpack-cli": "^3.1.0",
    "webpack-merge": "^4.1.4"
  }
}

Hello World

dist/index.htmlにHTMLを記述していきます。
VSCodeで空のファイルを作成してhtml:5と入力してTabを押すことで、Emmetのテンプレートを呼び出すと便利です。

dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="./main.js"></script>
  <title>My Game</title>
</head>
<body>
  <canvas id="main-canvas" width="640" height="480"></canvas>
</body>
</html>

JavaScriptの処理を記述していきます。
#main-canvasに「Hello, World」と描画してみます。

src/index.js
document.addEventListener('DOMContentLoaded', () => {
  // Canvas initialize
  const canvasElem = document.getElementById('main-canvas');
  const canvasContext = canvasElem.getContext('2d');
  canvasContext.font = '18px serif';

  // Canvas Clear
  canvasContext.fillStyle = 'black';
  canvasContext.clearRect(0, 0, canvasElem.width, canvasElem.height);
  canvasContext.fillRect(0, 0, canvasElem.width, canvasElem.height);

  // Render
  canvasContext.fillStyle = 'white';
  canvasContext.fillText('Hello, World!', 4, 20);
});

Visual Studio Codeでnpm watch

$ npm run watchコマンドでJavaScriptをビルドします。

Visual Studio Codeのnpm統合機能を使う場合は、コマンドパレットを開き、>Preferences: Open User Settingsで「ワークスペースの設定」からnpm.enableScriptExplorertrueにします。

.vscode/settings.json
{
  "npm.enableScriptExplorer": true
}

ここで、「NPMスクリプト」欄からnpm run watchを実行できるようになります。

image.png

ゲームの実行

dist/index.htmlを開きます。

# Windows Subsystem for Linuxの場合
$ explorer.exe $(wslpath -w dist/index.html)

# Macとかの場合
$ open dist/index.html

黒い背景に「Hello,World!」と表示されたら成功です。

image.png

これでゲームを実行するところまでは完成しました。あとは、JavaScriptでメイン処理を記述していくだけです。

たとえば以下のように記述すると、「Hello, World!」の文字をカーソルキーで操作できるようになります。

src/index.js
document.addEventListener('DOMContentLoaded', () => {
  // Keyboard Settings
  const keyCodes = {
    Right: 39,
    Left: 37,
    Up: 38,
    Down: 40,
    D: 68,
    A: 65,
    W: 87,
    S: 83,
  };
  let rightPressed;
  let leftPressed;
  let upPressed;
  let downPressed;
  function setKeyPressed(eventName, value) {
    document.addEventListener(eventName, (e) => {
      switch (e.keyCode) {
        case keyCodes.Right:
        case keyCodes.D:
          rightPressed = value;
          break;
        case keyCodes.Left:
        case keyCodes.A:
          leftPressed = value;
          break;
        case keyCodes.Up:
        case keyCodes.W:
          upPressed = value;
          break;
        case keyCodes.Down:
        case keyCodes.S:
          downPressed = value;
          break;
        default:
      }
    }, false);
  }
  setKeyPressed('keydown', true);
  setKeyPressed('keyup', false);

  // Canvas initialize
  const canvasElem = document.getElementById('main-canvas');
  const canvasContext = canvasElem.getContext('2d');
  canvasContext.font = '18px serif';

  // Cursor initialize
  let x = 4;
  let y = 20;
  const speed = 10;

  function main() {
    // Canvas Clear
    canvasContext.fillStyle = 'black';
    canvasContext.clearRect(0, 0, canvasElem.width, canvasElem.height);
    canvasContext.fillRect(0, 0, canvasElem.width, canvasElem.height);

    // User input
    if (rightPressed) {
      x += speed;
    } else if (leftPressed) {
      x -= speed;
    }
    if (downPressed) {
      y += speed;
    } else if (upPressed) {
      y -= speed;
    }

    // Render
    canvasContext.fillStyle = 'white';
    canvasContext.fillText('Hello, World!', x, y);
  }

  // loop
  setInterval(main, 1000 / 30);
});

たとえばMDNのブロック崩しチュートリアルなどを参考に、ゲームを開発していきましょう。

ESLintの導入

Canvas APIについてググって出てくる情報には、古い内容も多いです。
きちんとECMAScript 2015+に対応できるよう、予め ESLint を入れておくと効果を発揮すると思います。

$ npm install --save-dev eslint
$ ./node_modules/.bin/eslint --init

eslint --initの質問はお好みで。今回はこんな感じで設定しました。

Question Answer
How would you like to configure ESLint? Use a popular style guide
Which style guide do you want to follow? Airbnb (https://github.com/airbnb/javascript)
Do you use React? No
What format do you want your config file to be in? JavaScript
Would you like to install them now with npm? Yes

"env.browser": trueの設定は入れておきましょう。

.eslintrc.js
module.exports = {
  "env": {
    "browser": true
  },
  "extends": "airbnb-base"
};

Visual Studio Codeの ESLint 拡張を導入することで、ルールに違反している箇所が「問題」として警告が出るようになります。

image.png

完成

本番用のwebpackビルドをして、JavaScriptを圧縮します。

$ npm run prepare

もしjs13kGamesに応募するならば、dist/以下をzipで固めた物が提出物になります。このzipファイルが13KBを下回っていなければなりません。

$ zip --recurse-paths dist.zip dist/*
$ du --human-readable dist.zip
4.0K    dist.zip

参考

最終的に私が開発してjs13kGamesに提出した物はこちらです。
https://js13kgames.com/entries/inside-the-rect
締切当日夜20時に作り始めたため単純な内容であり、本稿以外の複雑な技術は使っていません。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?