入門チュートリアル: UWP ゲーム (JavaScript)Get Started Tutorial: A UWP game in JavaScript

JavaScript と CreateJS で記述された Windows ストア向けのシンプルな 2D UWP ゲームA simple 2D UWP game for the Windows Store, written in JavaScript and CreateJS

Walking Dino スプライト シート

はじめにIntroduction

Windows ストアにアプリを公開すると、さまざまな種類のデバイスを使う膨大な数の人々に、そのアプリを提供 (または販売!) することができます。Publishing an app to the Windows Store means you can share it (or sell it!) with millions of people, on many different devices.

Windows ストアにアプリを公開するには、そのアプリを UWP (ユニバーサル Windows プラットフォーム) アプリとして作成する必要があります。In order to publish your app to the Windows Store it must be written as a UWP (Universal Windows Platform) app. ただし、UWP はきわめて柔軟であり、多様な言語およびフレームワークをサポートしています。However the UWP is extremely flexible, and supports a wide variety of languages and frameworks. これを証明するために、いくつかの CreateJS ライブラリを活用して JavaScript で記述されたシンプルなゲームをサンプルとして紹介します。このサンプルでは、スプライトの記述、ゲーム ループの作成、キーボードとマウスのサポート、さまざまな画面サイズへの調整の方法を示します。To prove the point, this sample is a simple game written in JavaScript, making use of several CreateJS libraries, and demonstrates how to draw sprites, create a game loop, support the keyboard and mouse, and adapt to different screen sizes.

このプロジェクトは、Visual Studio を使って JavaScript で構築します。This project is built with JavaScript using Visual Studio. 少し変更を加えると、Web サイトでホスティングすることも、他のプラットフォームに合わせることもできます。With some minor changes, it can also hosted on a website or adapted to other platforms.

注: これはアプリを Windows ストアに公開できる状態にするために、JavaScript やサード パーティのライブラリの使用方法を示すことを目的としたものであり、完全なゲームではありません (おもしろいゲームでもありません)。Note: This is a not a complete (or good!) game; it is designed to demonstrate using JavaScript and a third party library to make an app ready to publish to the Windows Store.

要件Requirements

このプロジェクトを操作するには、以下が必要になります。To play with this project, you'll need the following:

  • 現在のバージョンの Windows 10 を実行する Windows コンピューター (または仮想マシン)。A Windows computer (or a virtual machine) running the current version of Windows 10.
  • Visual Studio。A copy of Visual Studio. 無料の Visual Studio Community Edition は、Visual Studio ホームページからダウンロードできます。The free Visual Studio Community Edition can be downloaded from the Visual Studio homepage.

このプロジェクトでは、CreateJS という JavaScript フレームワークを使用します。This project makes use of the CreateJS JavaScript framework. CreateJS は、MIT ライセンスの下にリリースされる無料のツールであり、スプライト ベースのゲームを簡単に作成できるように設計されています。CreateJS is a free set of tools, released under a MIT license, designed to make it easy to create sprite-based games. CreateJS ライブラリは、既にプロジェクトに含まれています (ソリューション エクスプローラー ビューで js/easeljs-0.8.2.min.js および js/preloadjs-0.6.2.min.js を探してください)。The CreateJS libraries are already present in the project (look for js/easeljs-0.8.2.min.js, and js/preloadjs-0.6.2.min.js in the Solution Explorer view). CreateJS について詳しくは、CreateJS ホーム ページをご覧ください。More information about CreateJS can be found at the CreateJS home page.

はじめにGetting started

アプリの完全なソース コードは、GitHub にあります。The complete source code for the app is stored on GitHub.

最も簡単に始める方法は、GitHub のページで、緑色の [Clone or download] (複製またはダウンロード) ボタンをクリックし、[Open in Visual Studio] (Visual Studio で開く) を選択することです。The simplest way to get started it to visit GitHub, click on the green Clone or download button, and select Open in Visual Studio.

リポジトリを複製する

GitHub プロジェクトは、zip ファイルとしてダウンロードすることも、その他の標準的な方法で操作することもできます。You can also download the project as a zip file, or use any other standard ways to work with GitHub projects.

ソリューションを Visual Studio に読み込むと、次のようなファイルが表示されます。Once the solution has been loaded into Visual Studio, you'll see several files, including:

  • Images/ - UWP アプリに必要なさまざまなアイコン、ゲームの SpriteSheet、その他のビットマップが含まれるフォルダー。Images/ - a folder containing the various icons required by UWP apps, as well as the game's SpriteSheet and some other bitmaps.
  • js/ - JavaScript ファイルが含まれるフォルダー。js/ - a folder containing the JavaScript files. main.js ファイルはゲームで、その他のファイルは EaselJS と PreloadJS です。The main.js file is our game, the other files are EaselJS and PreloadJS.
  • index.html - ゲームのグラフィックをホストする canvas オブジェクトが含まれる Web ページ。index.html - the webpage which contains the canvas object which hosts the game's graphics.

これでゲームを実行できます。Now you can run the game!

F5 キーを押して、アプリの実行を開始します。Press F5 to start the app running. ウィンドウが開き、牧歌的風景の中に、ありふれた恐竜が表示されます。You should see a window open, and our familar dinosaur standing in an idyllic (if sparse) landscape. それでは、アプリを調べていきましょう。重要な部分について説明し、他の機能についても、その都度明らかにします。We will now examine the app, explain some important parts, and unlock the rest of the features as we go.

ありふれた恐竜の背中に、ニンジャ キャットが乗っている

注: うまくいかない場合は、Note: Something go wrong? Web サポートを含めて Visual Studio がインストールされていることを確認してください。Be sure you have installed Visual Studio with web support. これは、新しいプロジェクトを作成することで確認できます。JavaScript のサポートが含まれていない場合は、[Microsoft Web Developer Tools] ボックスをオンにして Visual Studio を再インストールする必要があります。You can check by creating a new project - if there is no support for JavaScript, you will need to re-install Visual Studio and check the Microsoft Web Developer Tools box.

チュートリアルWalkthough

F5 キーでゲームを開始した場合は、内部的に何が起こっているのか疑問に思うかもしれません。If you started the game with F5, you're probably wondering what is going on. その答えは、"ほとんど何も起こっていない" です。現時点では、コードの大部分がコメントアウトされています。And the answer is "not a lot", as a lot of the code is currently commented-out. 今のところ、表示されるのは恐竜だけであり、Space キーを押しても何も起こりません。So far, all you'll see is the dinosaur, and a ineffectual plea to press Space.

1. ステージを設定する1. Setting the Stage

index.html を開いて内容を見ると、ほとんど空であることがわかります。If you open and examine index.html, you'll see it's almost empty. このファイルはアプリを含む既定の Web ページであり、重要な役割は次の 2 つだけです。This file is the default web page that contains our app, and it does only two important things. 1 つ目は、CreateJS の EaselJS ライブラリおよび PreloadJS ライブラリと main.js (このチュートリアルのソース コード ファイル) の JavaScript ソース コードが含まれていることです。First, it includes the JavaScript source code for the EaselJS and PreloadJS CreateJS libraries, and also main.js (our own source code file). 2 つ目は、すべてのグラフィックスを表示する場所として、<canvas> タグが定義されていることです。Second, it defines a <canvas> tag, which is where all our graphics are going to appear. <canvas> は、HTML5 ドキュメントの標準コンポーネントです。A <canvas> is a standard HTML5 document component. これには、main.js のコードから参照できるように gameCanvas という名前を付けます。We give it a name (gameCanvas) so our code in main.js can reference it. JavaScript で独自のゲームを 1 から記述する場合は、EaselJS ファイルと PreloadJS ファイルをソリューションにコピーして、canvas オブジェクトを作成する必要があります。By the way, if you are going to write your own JavaScript game from scratch, you too will need to copy the EaselJS and PreloadJS files into your solution, and then create a canvas object.

EaselJS では、stage と呼ばれる新しいオブジェクトが提供されます。EaselJS provides us with a new object called a stage. stage は canvas にリンクされ、画像とテキストを表示するために使用されます。The stage is linked to the canvas, and is used for displaying images and text. stage に表示するオブジェクトはすべて、まず stage の子として以下のように追加する必要があります。Any object we want to be displayed on the stage must first be added as a child of the stage, like this:

    stage.addChild(myObject);

このコード行は、main.js に数回出てきます。You will see that line of code appear several times in main.js

それでは、main.js を開いてみましょう。Speaking of which, now is a good time to open main.js.

2. ビットマップを読み込む2. Loading the bitmaps

EaselJS では、数種類のグラフィック オブジェクトが提供されます。EaselJS provides us with several different types of graphical objects. 単純な図形 (空に使用する青色の長方形など)、ビットマップ (後で追加する雲など)、テキスト オブジェクト、ストライプを作成できます。We can create simple shapes (such as the blue rectangle used for the sky), or bitmaps (such as the clouds we're about to add), text objects, and sprites. スプライトには、SpriteSheet (http://createjs.com/docs/easeljs/classes/SpriteSheet.html) を使用します。SpriteSheet は、複数の画像を含む単一ビットマップです。Sprites use a (SpriteSheet)[http://createjs.com/docs/easeljs/classes/SpriteSheet.html]: a single bitmap containing multiple images. たとえば、この SpriteSheet を使用して、共有アニメーションの複数フレームを格納することができます。For example, we use this SpriteSheet to store the different frame of dinosaur animation:

Walking Dino スプライト シート

恐竜を歩かせるには、複数のフレームを定義し、アニメーション化する際の速度をこのコードで指定します。We make the dinosaur walk, by defining the different frames and how fast they should be animated in this code:

    // Define the animated dino walk using a spritesheet of images,
    // and also a standing-still state, and a knocked-over state.
    var data = {
        images: [loader.getResult("dino")],
        frames: { width: 373, height: 256 },
        animations: {
            stand: 0,
            lying: { 
                frames: [0, 1],
                speed: 0.1
            },
            walk: {
                frames: [0, 1, 2, 3, 2, 1],
                speed: 0.4
            }
        }
    }

    var spriteSheet = new createjs.SpriteSheet(data);
    dino_walk = new createjs.Sprite(spriteSheet, "walk");
    dino_stand = new createjs.Sprite(spriteSheet, "stand");
    dino_lying = new createjs.Sprite(spriteSheet, "lying");

ここで、小さくてふわふわした雲をいくつか、stage に追加します。Right now, we're going to add some little fluffy clouds to the stage. ゲームが実行されると、画面上に雲が漂います。Once the game is running, they'll drift across the screen. 雲の画像は、既にソリューションの images フォルダーに含まれています。The image for the cloud is already in the solution, in the images folder.

main.js 内で、init() 関数を見つけます。Look through main.js until you find the init() function. この関数は、ゲームが開始されると呼び出されます。すべてのグラフィック オブジェクトのセットアップは、ここから開始します。This is called when the game starts, and it's where we begin to set up all our graphic objects.

以下のコードを見つけて、雲の画像を参照する行からコメント (\) を削除します。Find the following code, and remove the comments (\) from the line that references the cloud image.

 manifest = [
        { src: "walkingDino-SpriteSheet.png", id: "dino" },
        { src: "barrel.png", id: "barrel" },
        { src: "fluffy-cloud-small.png", id: "cloud" },
    ];

画像などのリソースを読み込むには JavaScript を少し補助する必要があるため、画像をプリロードするための LoadQueue という CreateJS ライブラリの機能を使用します。JavaScript needs a little help when it comes to loading resources such as images, and so we're using a feature of the CreateJS library that can preload images, called a LoadQueue. 画像の読み込みにどの程度の時間がかかるか予測できないため、LoadQueue を使用して処理します。We're can't be sure how long it will take the images to load, so we use the LoadQueue to take care of it. これにより、画像の準備ができると、キューによる通知を受けることができます。Once the images are available, the queue will tell us they are ready. そのためにはまず、すべての画像をリストした新しいオブジェクトを作成してから、LoadQueue オブジェクトを作成します。In order to do that, we first create a new object that lists all our images, and then we create a LoadQueue object. 下のコードに示すように、このオブジェクトは、すべての準備が整ったら loadingComplete() という関数が呼び出されるようにセットアップされています。You'll see in the code below how it is set-up to call a function called loadingComplete() when everything is ready.

    // Now we create a special queue, and finally a handler that is
    // called when they are loaded. The queue object is provided by preloadjs.

    loader = new createjs.LoadQueue(false);
    loader.addEventListener("complete", loadingComplete);
    loader.loadManifest(manifest, true, "../images/");

関数 loadingComplete() が呼び出されると、画像が読み込まれ、使用可能な状態になります。When the function loadingComplete() is called, the images are loaded and ready to use. コメントアウトされていたセクションでは雲を作成しますが、そのためのビットマップが使用できます。You'll see a commented-out section that creates the clouds, now their bitmap is available. コメントを削除すると、次のようになります。Remove the comments, so it looks like this:

    // Create some clouds to drift by..
    for (var i = 0; i < 3; i++) {
        cloud[i] = new createjs.Bitmap(loader.getResult("cloud"));
        cloud[i].x = Math.random()*1024; // Random start location
        cloud[i].y = 64 + i * 48;
        stage.addChild(cloud[i]);
    }

このコードでは、プリロードされた画像をそれぞれ使用する cloud オブジェクトを 3 つ作成し、これらの位置を定義して、stage に追加しています。This code creates three cloud objects each using our pre-loaded image, defines their location, and then adds them to the stage.

アプリをもう一度実行 (press F5 を押す) すると、雲が表示されます。Run the app again (press F5) and you'll see our clouds have appeared.

3. 雲を動かす3. Moving the clouds

次は、雲が動くようにします。Now we're going to make the clouds move. 雲を (または、あらゆる物を) を動かすための秘策は、1 秒に何度も呼び出される ticker 関数をセットアップすることです。The secret to moving clouds - and moving anything, in fact - is to set-up a ticker function that is repeatedly called multiple times a second. この関数が呼び出されるたびに、少し位置を変えてグラフィックスが再描画されます。Every time this function is called, it redraws the graphics in a slightly different place.

CodePen で、Microsoft Edge Docs (@MicrosoftEdgeDocumentation) による Pen (CreateJS - Animating clouds) をご覧ください。See the Pen CreateJS - Animating clouds by Microsoft Edge Docs (@MicrosoftEdgeDocumentation) on CodePen.

そのためのコードは既に main.js に含まれ、CreateJS ライブラリの EaselJS から提供されています。The code to do that is already in the main.js file, provided by the CreateJS library, EaselJS. 次のような内容です。It looks like this:

    // Set up the game loop and keyboard handler.
    // The keyword 'tick' is required to automatically animated the sprite.
    createjs.Ticker.timingMode = createjs.Ticker.RAF;
    createjs.Ticker.addEventListener("tick", gameLoop);

このコードでは、gameLoop() という関数が 1 秒あたり 30 ~ 60 回呼び出されます。This code will call a function called gameLoop() between 30 and 60 frames a second. 正確な速度は、使用するコンピューターの速度によって異なります。The exact speed depends on the speed of your computer.

gameLoop() 関数を探すと、終わりの方に animateClouds() という関数が記述されています。Look for the gameLoop() function, and down towards the end you'll see a function called animateClouds(). 編集してコメント アウトを解除してください。Edit it so that it is not commented out.

    // Move clouds
    animateClouds();

この関数の定義を見ると、それぞれの雲を順番に表示し、その際に X 座標を変化させていることがわかります。If you look at the defintion of this function, you'll see how it takes each cloud in turn, and changes its x co-ordinate. X 座標が画面の左端に到達すると、右端にリセットされます。If the x-ordinate is off the side of screen, it is reset to the far right. また、それぞれの雲は、やや異なる速度で動きます。Each cloud also moves at a slightly different speed.

function animate_clouds()
{
    // Move the cloud sprites across the sky. If they get to the left edge, 
    // move them over to the right.

    for (var i = 0; i < 3; i++) {    
        cloud[i].x = cloud[i].x - (i+1);
        if (cloud[i].x < -128)
            cloud[i].x = width + 128;
    }
}

ここでアプリを実行すると、雲が漂い始めます。If you run the app now, you'll see that the clouds have started drifting. ついに、動かすことができました!Finally we have motion!

4. キーボード/マウス入力を追加する4. Adding keyboard and mouse input

ユーザーが操作できないゲームは、ゲームとは言えません。A game that you can't interact with isn't a game. そこで、ユーザーがキーボードまたはマウスを使って何かできるようにしてみましょう。So let's allow the player to use the keyboard or the mouse to do something. loadingComplete() 関数に戻ると、次のようなコードがあります。Back in the loadingComplete() function, you'll see the following. コメントを削除してください。Remove the comments.

    // This code will call the method 'keyboardPressed' is the user presses a key.
    this.document.onkeydown = keyboardPressed;

    // Add support for mouse clicks
    stage.on("stagemousedown", mouseClicked);

これで、プレイヤーがキーを押すかマウスをクリックしたときに呼び出される 2 つの関数を使用できます。We now have two functions being called whenever the player hits a key or clicks the mouse. どちらのイベントでも userDidSomething() が呼び出されます。この関数では gamestate 変数を調べて、今ゲームで何が行われているかを判断し、その結果、次に何が必要かを決定します。Both event will call userDidSomething(), a function which looks at the gamestate variable to decide what the game is currently doing, and what needs to happen next as a result.

Gamestate は、ゲームで一般的に使用される設計パターンです。Gamestate is a common design pattern used in games. 発生する動作はすべて、ticker タイマーによって呼び出される gameLoop() 関数の中で実行されます。Everything that happens, happens in the gameLoop() function called by the ticker timer. gameLoop() では、変数を使用して、ゲームがプレイ中か、"ゲーム オーバー状態"、"プレイ準備完了状態、または作者が定義した他の状態であるかを追跡します。The gameLoop() keeps track of whether the game is playing, or in a "game over state", or a "ready-to-play state", or any other states defined by the author, using a variable. この状態の変数は、switch ステートメント内でテストされ、その結果によって他のどの関数を呼び出すかが決まります。This state variable is tested in a switch statement, and that defines what other functions are called. 状態が "playing" に設定されている場合は、恐竜にジャンプさせ、樽を動かす関数が呼び出されます。So if the state is set to "playing", the functions to make the dinosaur jump and make the barrels move will be called. 一方、何らかの手段で恐竜が倒されると、gamestate 変数が "ゲーム オーバー状態" に設定され、"Game over!" If the dinosaur is killed by something, the gamestate variable will be set to "game over state", and the "Game over!" というメッセージが表示されます。message will be displayed instead. ゲームの設計パターンに興味がある場合は、「Game Programming Patterns」(ゲーム プログラミングのパターン) という書籍が役立ちます。If you are interested in game design patterns, the book Game Programming Patterns is very helpful.

アプリをもう一度実行すると、ついにプレイを開始できます。Try running the app again, and finally you'll be able to start playing. Space キーを押す (または、マウスをクリックするか画面をタップする) と、ゲームが始まります。Press space (or click the mouse, or tap the screen) to start things happening.

樽が、こちらに向かって転がってきます。適切なタイミングで Space キーを押すかもう一度クリックすると、恐竜がジャンプします。You'll see a barrel come rolling towards you: press space or click again at just the right time, and the dinosaur will leap. タイミングを間違えると、ゲーム オーバーとなります。Time it wrong, and your game is over.

樽は、雲と同じ方法でアニメーション化されます (ただしこちらは毎回速度が速くなります)。恐竜と樽については、衝突しないように位置を確認します。The barrel is animated in the same way as the clouds (although it gets faster each time), and we check the position of the dinosaur and the barrel to make sure they haven't collided:

 // Very simple check for collision between dino and barrel
                if ((barrel.x > 220 && barrel.x < 380)
                    &&
                    (!jumping))
                {
                    barrel.x = 380;
                    GameState = GameStateEnum.GameOver;
                }

恐竜がジャンプ中ではなく、樽が近くにある場合は、状態変数が GameOver という状態に変更されます。If the dinosaur isn't jumping and the barrel is nearby, the code changes the state varaible to the state we've called GameOver. ご想像どおり、GameOver 状態になるとゲームが停止します。As you can imagine, GameOver stops the game.

また、ゲームのメイン メカニズムも終了します。And so the main mechanics of our game are complete.

5. サポートのサイズを変更する5. Resizing support

これで、ほとんどの作業が終わりました。We're almost done here! ただし、作業を終える前に対処すべき問題がもう 1 つあります。But before we stop, there is one annoying problem to take care of first. ゲームの実行中、ウィンドウのサイズを変更してみてください。When the game is running, try resizing the window. オブジェクトの位置が乱れ、ゲームは直ちに混乱状態になります。You'll see that the game quickly becomes very messed-up, as objects are no longer where they should be. この問題は、ウィンドウのサイズ変更イベント用ハンドラーを作成することで処理できます。このイベントは、プレイヤーがウィンドウのサイズを変更したときや、デバイスが回転されて横から縦になったときに発生します。We can take care of that by creating a handler for the window resizing event generated when the player resizes the window, or when the device is rotated from landscape to portrait.

ハンドラーのコードは既に存在します (UWP アプリの起動時にはウィンドウのサイズがどうなるかわからないため、既定のウィンドウ サイズを使用できるかどうかを確認するために、ゲームが初めて実行されると、このコードが呼び出されます)。The code to do this is already present (in fact, we call it when the game first starts, to make sure the default window size works, because when a UWP app is launched, you can't be certain what size the window will be).

画面サイズのイベントが発生したときに関数が呼び出されるように、以下の行のコメントを解除します。Just uncomment this line to call the function when the screen size event is fired:

    // This code makes the app call the method 'resizeGameWindow' if the user resizes the current window.
     window.addEventListener('resize', resizeGameWindow);

アプリをもう一度実行すると、ウィンドウのサイズを変更したときの結果が改善されます。If you run the app again, you should now be able to resize the window and get better results.

Windows ストアへの公開Publishing to the Windows Store

UWP アプリを作成できたため、(もう少し改善すれば) Windows ストアに公開することもできます。Now you have a UWP app, it is possible to publish it to the Windows Store (assuming you have improved it first!)

このプロセスにはいくつかの手順が必要になります。There are a few steps to the process.

  1. Windows 開発者として登録する必要があります。You must be registered as a Windows Developer.
  2. アプリの申請チェックリストを使用する必要があります。You must use the app submission checklist.
  3. 認定を受けるために、アプリを提出する必要があります。The app must be submitted for certification.

詳しくは、「Windows ストア アプリの公開」をご覧ください。For more details, see Publishing your Windows Store app.

その他のおすすめ機能Suggestions for other features.

次にすることWhat next? アプリの質を高めるために追加をお勧めする機能を以下に示します。Here are a few suggestions for features to add to your (soon to be) award-winning app.

  1. 音響効果。Sound effects. CreateJS ライブラリには、SoundJS というライブラリによるサウンドのサポートが含まれています。The CreateJS library includes support for sound, with a library called SoundJS.
  2. ゲームパッドのサポート。Gamepad support. 利用できる API があります。There is an API available.
  3. もっともっとすばらしいゲームにしてください。Make it a much, much better game! この部分はあなた次第ですが、オンラインで利用可能なリソースも多数あります。That part is up to you, but there are lots of resources available online.