← Back to list

Created an eSports using blockchain, 1st. preparation and making a game.

e-sportsプロジェクトであるOraga eSportsの制作過程をここに記します。

Takashi Tahara (田原 崇) | TEM's Blog · 2025-06-22 01:57 · 0 claps · 13.3 min read
#flow-blockchain #esports-business #graphql #pixijs #vitejs
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval CRY · Crypto & Web3 🎮 · Gaming 🏆 · Sports · General

Created an eSports using blockchain, 1st. preparation and making a game.

e-sportsプロジェクトのOraga eSportsの制作過程をここに記します。

開発過程

まず、GraphQLをバックエンドサービスとしてNode.jsで動かしますので、ローカル環境とバックエンドのNode.jsのバージョンを念の為に合わせます。

なぜGraphQLかと言いますと、eSportsは世界全体で競う賞金制ゲームであるため、例えば自分が賞金1万円を獲得するためゲーム攻略を頑張っていたとしたら、その間に他のプレイヤーがその賞金を取っていたとしたら、すぐに通知してあげる必要があるからです。そうしないとそのプレイヤーはひどく落胆し、ゲーム自体に対して怒りの感情を持ってしまうからです。

GraphQLはTwitterがリアルタイム通知の環境のために積極採用しているWebSocketライブラリであり、AWS Amplifyを使うとAWS Lambdaをリゾルバとして利用できるなど、有利な点があります。現在AWS Lambdaは最新Node.jsバージョンがv22であるため、ローカル環境のNode.jsもv22に念の為合わせます。

nvm ls-remote
nvm install 22
nvm use 22
nvm alias default 22

ゲーム作成

eSportsは Vite + Svelteの環境で作成しました。

Vite + Svelte環境はnpm run buildしてできたファイルをCroudFrontに上げるだけですのでインフラ作業がとても簡単です。

eSportsの第一弾としてシューティングゲームを作成していくのですが、HTML5ライブラリのPixi.JSとSvelteの組み合わせは、検索すると良い情報がたくさん出てきます。Svelteはパフォーマンスが良いのでHTML5ゲームと相性がよく、この組み合わせは比較的簡単にゲームを作成することができます。

シューティングゲームの作成方法はこちらを参考にしました。

[embed]

キャラクターのデザインは商用利用が可能なこちらのサイトを活用しました。

[embed]フリー素材 「フリー素材」の記事一覧です。uzi-material.com

GraphQL環境の構築

ゲームの作成が約10時間で終わりましたので、次にGraphQL環境を用意します。この環境設立にAWS Amplifyを活用しますので、amplifyのcliを使用して環境をセットアップしていきます。

Amplifyの環境構築にはCLIを使用するGen1と、CDKを使用するGen2の2種類があります。Gen2を使用すると、強制的に毎月$15が取られてしまうので今回はGen1を利用します。

Gen1であればLambda + CloudFrontの環境を自分で自由に作れるので費用はほぼElasticIPなどのDNS費用だけとなり、比較的お得です。(AWSのAPIは良心的な従量課金制であるため結構安い)

Gen1による構築方法については以下のサイトが詳しいです。ほぼ同じ手順でGraphQL APIをセットアップしています。

[embed]AWS Amplify(Gen1)についてわかりやすくまとめてみた 今回は、Amplify CLI による開発(Amplify Gen1)について記事にしています。 また、下記のAmplify CDK による開発(Amplify Gen2)は、こちらを確認してください。 AWS…zenn.dev

GraphQLスキーマの編集

amplify add api

上記の段階まで終わるとGraphQLスキーマの編集を行います。

amplify/backend/api/<project name>/schema.graphql にはサンプルとしてTodoのtypeがあります。それを利用して、私はこのファイルを以下のように変更しました。

type GameServerProcess
  @model
  @auth(rules: [
    { allow: public, provider: apiKey }
  ]
) {
  id: ID!
  type: String!
  message: String!
  playerId: String!
}

世界中のゲームプレイヤーにゲームをプレイしてもらわなければなりませんので、認証はproviderをAPIキーとして、allowをpublicにします。

ここまで来たら、あとはamplify pushするだけです。これによって、GraphQLが利用するDynamoDBなどは全てAWS Cloud上に用意されます。ローカルの環境もあとはクエリーを呼び出すだけの状態にまで準備されています。

私はschema.graphqlファイルにSubscriptionのtypeを宣言してませんが、自動でSubscriptionクエリーメソッドもAWSによって用意されています。

APIキーのローテーション方法

これは、以前はすごく分かりにくかったのですが、今は改善されて簡単にできるようになっています。

amplify/backend/api/<project name>/フォルダの下にparameters.jsonというファイルがあります。ここに

"CreateAPIKey": 0

をセットしてamplify pushを行うと現在のAPIキーが削除されます。

そして同じファイルを以下のように変更してもう一度amplify pushを行うとAPIキーを新しく作成し直してくれます。(初期状態ではAPIキーは7日間しか有効期間がありません)

"CreateAPIKey": 1,
"APIKeyExpirationEpoch": 1768000000 // 2026年1月9日(約半年後)

(ここにこのようにすると書いてあったのですが、再生成しても私の場合有効期間が1週間のままで変わりませんでした。そのため、私はAWSコンソールで直接、有効期間を変更しました。その方が意外と簡単で確実です)

AWS Lambdaファイルの作成

GraphQLサーバーとして働くLambdaファルを作成するためにAWSのコンソールを開き、AWSサービスの中でLambdaを開きます。

そしてindex.js(mjs)ファイルを以下のようにします。

export const handler = async (event) => {
  return {
    id: new Date().getTime(),
    type: 'This is from Lambda',
    message: 'This is from Lambda',
    playerId: 'This is from Lambda',
    createdAt: new Date(),
    updatedAt: new Date(),
  };
};

この値は全てGraphQLのスキーマで設定した値を返すようにしたものです。意外かもしれませんが、DateオブジェクトをAWSはインターネット上で受け渡しすることができます。

DataSourceの作成

AppSyncサービスをWebコンソールで開くとAPIが一つ作成されています。そこで以下のようにData Sourceを開くボタンを押します。今作ったAWS Lambda FunctionをData Sourceとして作成します。

Schemaのリゾルバに設定

そしてそれをGraphQL Schemaのリゾルバに設定します。具体的には以下のリンクをクリックして変更します。(PipelineというのはAWSがデフォルトで設定している少し複雑な設定です。ここの作業手順を詳しく知りたい方はこちらを買って読んでみてください。)

AppSyncに接続するコードを書く

以下のコマンドを実行して、接続するコードを書いていきます。

npm install aws-amplify

後はGraphQLを呼び出したい時に呼び出すだけですので、ゲームに勝利した時に他のプレイヤーに賞金は私がいただいた、とリアルタイムに通知できるようにゲーム勝利時のコードを変更します。

<script>
  import * as PIXI from 'pixi.js'
  import { Sprite, Graphics, Text, Ticker, getApp } from 'svelte-pixi'
  import { generateClient } from 'aws-amplify/api';
  import { createGameServerProcess } from '../../graphql/mutations';

  const client = generateClient();

  async function onGameWonOrLose() {
    clearInterval(timerCtrl2)
    started = false

    const query = {
      type: 'Test',
      message: 'Test',
      playerId: 'Test',
    };

    /* create a todo */
    await client.graphql({
      query: createGameServerProcess,
      variables: {
        input: query
      }
    });
  }

ゲームの勝敗が決着がついた時にこのメソッドを呼び出せば..

このようにGraphQLのクエリが呼び出されます。この辺りは本当に簡単ですね。

GraphQLのDataSourceに設定しているAWS Lambda Functionのサイトを見てみます。以下のようにLambda Functionが呼ばれていることを確認できます。

次にSubscriptionを実装してみます。これができれば、まだプレイ中の他のゲームユーザーに「おっと誰かが賞金をかっさらったようだ。あなたの賞金は₣1にリセットされてしまったよ。」と伝えることが出来ます。

  import * as subscriptions from '../../graphql/subscriptions';

  const createSub = client
  .graphql({ query: subscriptions.onCreateGameServerProcess })
  .subscribe({
    next: ({ data }) => console.log(data),
    error: (error) => console.warn(error)
  });

呼ばれました!一回で成功です。簡単ですね。messageとplayerIdとtypeを見てみてください。”This is from Lambda”と書かれてあります。このページ内の「AWS Lambdaファイルの作成」の項目を見てください。全く同じ情報です。

素晴らしい。Amplify Gen1は本当に簡単にLambdaをGraphQLサーバーとして設定できますね。

後はLambdaからjs(mjs)ファイルをダウンロードして必要なnpmパッケージをインポートしてzip化してLambdaに再アップロードすればブロックチェーンにトランザクションを送ることもできます。その場合は、GraphQLのSubscriptionは3秒ほど遅れることになります。トランザクションがちゃんと受理されるまではトランザクションIDが発行されないためです。トランザクションIDは重要な情報ですのでそれをawaitで待ってからLambdaはreturnするようにします。

CloudFrontで公開

ゲームはできており、実機のスマホでも動作を確認してみたい為、試しにCloudFrontで公開してみます。

npm run build

(以下のコマンドを叩くと、ビルドしたファイルをチェックすることが出来ます。)

npm run preview

もし、画像のパスを/public/assetsのように/publicからにしていると、この時点で画像取得エラーが起こります。画像のパスは/publicを含めない形で設定する必要があります。

次は、distフォルダ以下のindex.htmlとassetsフォルダをS3のバケットにアップロードします。

次にCloudFrontをAWSコンソールで開きます。S3をオリジンにするのがデファクトスタンダートなので何も考えなくても設定することが出来ます。

途中でoraga-esports.comのドメインを買いました。意外に.comが安かったです。(年1400円)

私はWAFをオフにしました。Vite + フレームワークは静的ファイルを生成するだけですので攻撃されても大丈夫と判断しています。APIキーが静的ファイル内にないこともWAFをオンにしない判断材料になりました。

Trouble Shooting

私が一つ詰まったのはDefault root objectを空でDistributionを作成してしまったことです。この場合、https://oraga-esports.com/index.htmlにはアクセスすることが出来ますが、https://oraga-esports.com/にアクセスしようとすると403 Access Deniedとなります。

Default root objectにindex.htmlを設定し忘れた場合は、CroudFrontのGeneral Tab > Settings section > Edit > scroll down to Default root objectからindex.htmlを設定して保存するとDomain Nameからアクセスができるようになります。

以上で開発の準備が完了しました。(ゲームのURLは以下)

https://oraga-esports.com/

最後に

GraphQLに通信する箇所のソースコードは以下のURLにあります。

[embed]oraga-esports/src/lib/shooting/Player.svelte at main · temt-ceo/oraga-esports Oraga eSports project. Contribute to temt-ceo/oraga-esports development by creating an account on GitHub.github.com

一つAWS AppSyncDirect Lambda Resolverの凄いところを書くとすれば、ゲームの内容にもよりけりですが、一度amplify pushをした後は、もうamplify push をする必要がない、ということが挙げられます。バックエンドのGraphQL処理の変更はAWS Lambdaからダウンロードしたjsファイルに編集してzip化してAWS Lambdaにアップロードすれば次回からはその変更が反映されるためです。

次の記事 >

[embed]Created an eSports using blockchain, 2nd. writing Smart contract and interact with it. eSportsを作る上でブロックチェーンに接続する部分について解説していきます。medium.com


메타데이터
post_id
6eab22fd6b8a
slug
created-an-esports-using-blockchain-1st-preparation-and-making-a-game-6eab22fd6b8a
url
https://medium.com/@tickets.on.flow/created-an-esports-using-blockchain-1st-preparation-and-making-a-game-6eab22fd6b8a
canonical_url
https://medium.com/@tickets.on.flow/created-an-esports-using-blockchain-1st-preparation-and-making-a-game-6eab22fd6b8a
author_url
https://medium.com/@tickets.on.flow
status
ok
fetched_at
2026-07-19 08:25:40