Glitchではじめるお手軽オンラインハッカソン

[Glich](https://glitch.com)はWebブラウザーさえあれば無料でWebアプリを開発できちゃうサービスです。

（Visual Studio CodeのLive Share拡張を使ったときのように）複数人でリアルタイムのコード編集ができるので、オンラインハッカソンにピッタリです！

一応、[無料で使うときの制約](https://glitch.com/help/restrictions/)（最後に抜粋を載せました）はありますが、ハッカソンでデモをするのには十分でしょう。プロジェクトを非公開にできるのも嬉しいです。[^1]

とにかくお手軽にコーディングをはじめられるようになっています。ここでは、JavaScriptでゲームが作れる[phina.js](https://phinajs.com/)のチュートリアルを例にして、使い方を紹介します。

なお、次の前提を満たしている人が対象です。

- PCを持っていて、Webブラウザーが使える。
- 共同でコーディングする人への連絡手段、例えばSlackやChatworkなど、がある。
- Facebook, GitHub, Googleのいずれかのアカウントか、メールアドレスを持っている。

# 使い方

phina.jsのチュートリアルでは、```index.html```[^2]と```main.js```を作ります。この2つのファイルをGlitchのプロジェクトに反映して、Webアプリとして使えるようにします。

```html:index.html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, user-scalable=no" />
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <title>Getting started | phina.js</title>
    <!-- phina.js を読み込む -->
    <script src="https://cdn.rawgit.com/phi-jp/phina.js/v0.2.0/build/phina.js"></script>

    <!-- メイン処理 -->
    <script src="main.js"></script>
  </head>
  <body>

  </body>
</html>
```

```javascript:main.js
// phina.js をグローバル領域に展開
phina.globalize();

// MainScene クラスを定義
phina.define('MainScene', {
  superClass: 'CanvasScene',
  init: function() {
    this.superInit();
    // 背景色を指定
    this.backgroundColor = '#444';
    // ラベルを生成
    this.label = Label('Hello, phina.js!').addChildTo(this);
    this.label.x = this.gridX.center(); // x 座標
    this.label.y = this.gridY.center(); // y 座標
    this.label.fill = 'white'; // 塗りつぶし色
  },
});

// メイン処理
phina.main(function() {
  // アプリケーション生成
  var app = GameApp({
    startLabel: 'main', // メインシーンから開始する
  });
  // アプリケーション実行
  app.run();
});
```

## Glitchで新しいプロジェクトを作る

https://glitch.com にアクセスして、右上の「New Project」ボタンを押します。3つのテンプレートの中から、一番上のhello-webpageを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/8fe8c328-5a08-c4b9-19d7-8302234e5884.png)

Loading Projectと表示されるので少々待ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/264e4f02-3251-defb-94cb-9227032adcd1.png)

## index.htmlを反映する

作ったプロジェクトにはすでに```index.html```があります。

左ペインで```index.html```を選んだ後、上記したphina.jsの```index.html```をコピペして上書します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/60c4e9ef-4650-f118-11e5-e68cf579bd44.png)

保存ボタンはありません。自動的に保存されます。

## main.jsを追加する

次に左ペインの「New File」ボタンを押し、main.jsと入力した後に「Add This File」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/e3b9ed4b-584d-db36-b42a-f437a3958f55.png)

左ペインで```main.js```ファイルを選んだ後、上記したphina.jsの```main.js```をコピペして上書きします。

「phina is not defined」というエラーが表示されますが、今回はそのままにします。

## Webアプリの動作を確認する

サングラスマーク「Show」をクリックすると、「In a New Window」と「Next to The Code」が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/c9b4aab6-c238-9c83-ec24-a4cea4439f0b.png)

ここでは「Next to The Code」を選んでみましょう。すると、画面左にphina.jsが実行された結果が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/2aaa7b34-b524-65a0-9ca9-8a2e752985ee.png)

このWebアプリは、すでに一般に公開されています。WebアプリのURLは、実行結果画面の上にある「Change URL」ボタンを押すと分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/2484c9dc-a2ee-5097-29e5-5b2d1a4a5242.png)

URLは```https://xxxxx-xxxxx-xxxxx.glitch.me```という形式です。```xxxxx-xxxxx-xxxxx```はプロジェクト名です。

# 他の人と共同でコーディングしてみる

一緒にコーディングする人にURLを知らせます。

プロジェクトをデフォルトのまま公開にしている場合と、privateに変更して非公開にしている場合で、伝えるURLが変わります。

## プロジェクトをデフォルトのまま公開にしている場合

コードを表示している画面のURLをそのまま伝えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/8a50fe60-e38e-6164-4789-d0e97bf78078.png)

URLは```https://glitch.com/edit/#!/xxxxx-xxxxx-xxxxx```という形式です。```xxxxx-xxxxx-xxxxx```はプロジェクト名です。

一人でも実験できますので、上記URLを別のウィンドウで開いてみてください。片方の変更が、もう片方にすぐに反映されます。

## プロジェクトをprivateにして非公開にしている場合

画面左上のプロジェクト名```xxxxx-xxxxx-xxxxx```をクリックして、中程の「Make This Project Private」をチェックすることで非公開にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/19be3383-726f-009a-2e5a-ec5027fb2bb0.png)

非公開にした状態でコードを表示している画面のURLを他人が開いても「No project found at xxxxx-xxxxx-xxxxx」と表示されます。そのまま放置すると、別名の新しいプロジェクトが自動的に作成されるので注意してください。

非公開プロジェクトに参加してもらうURLは、左ペイン「Share」ボタンを押して、Invite Others to EditにあるURLです。こちらを一緒にコーディングしたい人に伝えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/cee2438c-dccc-5450-e4e5-f520ed64e273.png)

URLは次のような形式です：```https://glitch.com/edit/#!/join/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx```

# アカウントを作りサインインしてプロジェクトを延命する

ここまで、サインインせずに作業してきました。このままだとこのプロジェクトは5日後に無くなってしまいます。アカウントを作ってサインインすれば、プロジェクトはずっと使えるようになります。[^3]

右上の「Sign In」ボタンを押した後に、画面中程の「Create an Account」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/ef15435b-b3cc-7ae7-e7ac-fa9680745d1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/266d29fb-ca05-4f06-aa5b-ce4d70603dfd.png)

次の4つの方法でアカウントを作れます。

- Facebook
- GitHub
- Google
- Email Magic Link

最後の Email Magic Link はメールアドレスを登録すると、そのアドレス宛にサインイン用のキーワードが送信されてくる機能です。

# phina.js で画像を作ったキャラクターを表示する

キャラクターを表示するには Sprite を使います。
Sprite を使うには、Sprite の一種として（名前は何でも良いのですが）Player クラスを作ることにします。

1. 利用する画像をアセット ASSETS として定義します。画像名を player とします。
2. Sprite の一種として、Player クラスを作ります（Sprite を親とします）。
3. Player クラスを初期化するときに、利用する画像名 player を指定します。
4. 画面（MainScene）に Player を作ります。
5. 上記 1 で作った ASSETS をメイン main で読み込みます。

```main.js
phina.globalize();

// (1) アセットに player という名前の画像を設定
var ASSETS = {
  image: {
    player: 'https://raw.githubusercontent.com/phinajs/phina.js/develop/assets/images/tomapiko.png'
  }
}

// (2) Sprite（キャラクター表示）の一種として、Player を定義
phina.define('Player', {
  superClass: 'Sprite',
  // コンストラクタ
  init: function() {
    // (3) アセットに設定した画像の名前 player を指定
    this.superInit('player');
  },
});

phina.define('MainScene', {
  superClass: 'CanvasScene',
  init: function() {
    this.superInit();
    this.backgroundColor = '#444';
    this.label = Label('Hello, phina.js!').addChildTo(this);
    this.label.x = this.gridX.center();
    this.label.y = this.gridY.center();
    this.label.fill = 'white';
    // (4) Player を作り、MainScene に追加
    this.player = Player()
    this.player.addChildTo(this);
    this.player.setPosition(this.gridX.center(), this.gridY.center() + this.player.height);
  },
});

// メイン処理
phina.main(function() {
  var app = GameApp({
    startLabel: 'main',
    // (5) アセットを読み込む
    assets: ASSETS
  });
  // アプリケーション実行
  app.run();
});
```

## Glitch にアップロードした画像を使う

**【注意！】アップロードした画像のURLは、assets/xxxx.png ではありません。詳しくは下記をご覧ください。**

Webブラウザーの画像ファイルをドラッグアンドドロップすると、Glitch に画像をアップロードできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/9ce4c290-5261-32c4-64ce-85e7bf47da1d.png)

少しの間待つと、assets ディレクトリーの下にアップロードした画像が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/22a2b10a-d1b3-1aee-7944-cd2234533e2a.png)

phina.js で画像を使うには、画像の URL が必要です（URL は assets/xxxx.png のような形式ではありまｓん）。画像の URL は、assets にある画像をクリックすることで表示されます。Copyボタンを押せば、URL をクリップボードにコピーできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/c40cb8cf-2228-1061-1d46-a89a39cbf0ba.png)

後は上記した ASSETS の image.player に URL をペーストして使ってください。

説明は以上です。Happy coding!
# おまけ
[What technical restrictions are in place?](https://glitch.com/help/restrictions/)から無料の場合の制約について抜粋します。[有料にすれば](https://glitch.com/help/boosted-apps-whats-that/)緩和されます。2020年5月14日時点の情報です。

- 実行時間
 - アクセスがないと5分後に停止する。また、12時間連続実行していると停止する。Webアプリへのアクセスがあると再び実行される。
 - サインインしたユーザーは20アプリまで、サインインしていないユーザーは3アプリまで同時に実行できる。
 - サインインしていないユーザーのアプリは5日後に削除される。
- コンテナ（アプリ）が利用できるディスクサイズ
 - コンテナが使えるディスクスペースは200MBと、アセット用の512MB。
 - /tmpディレクトリーは上記に含まれないが、アプリを再起動した時に消える。  
 - Node.jsのモジュールは上記に含まれないが、最大で1GBまで。
- コンテナ（アプリ）が利用できるRAM
 - RAMは512MBまで。
- Webアプリが処理できるリクエスト数
 - 1時間あたり4000リクエストまで。超えると、429 Too Many Requestsレスポンスが返却される。

[^1]: 非公開にできるのはソースコードを編集する機能です。Webアプリ自体は非公開にできません。

[^2]: HTMLでシングルクォーテーションを使っているところをダブルクオーテーションに変更しています。また、phina.jsのCDMのURLをhttpからhttpsに変更しています。

[^3]: サインインすると同時実行できるアプリ数が3から20に増えます。その他の無料の場合の制約はそのままです。