Making Story
今年の七夕にブロックチェーンを使った一つのeSportsプラットフォームが立ち上がったのですが、そこにはこう記載があります。
Flow blockchain を採用した理由は、開発ツールが揃い、スマートコントラクトを書く言語が他のブロックチェーンに比べて書きやすい点と、ビルドまで手が止まらずに開発を行える点などが挙げられます。
中の人として、どういった制作過程があったかをまとめておきたくて、こちらに記しておこうと思います。
まず、6月13日の時点ではまだゲームのコードも書いていませんでした。それから1週間でコードを書いてゲームを作ってみたら、プログラマーの情熱が出てきて、残り2週間と1日でブロックチェーン接続周り全てを仕上げていました。
こんなことができるのはFlow blockchainのCadenceというスマートコントラクト言語が書きやすく、仕様がはっきりしていて、本当にRobustでありつつ、エンジニアにはとても開発がしやすいからです。
また、その理念が周りの開発ツールに受け継がれているのもFlowの特徴です。
・Blockchain
・JavaScriptライブラリ(fcl)
・Cadence言語 ← Bastian開発(Flowの開発チームのリーダー)
・Flow CLI
どれもすごい(特にfclは誰でも1日でBlockchainエンジニアになれるので凄い)ですが、これだけではありません。
一時はFlow Diverという流行りの名前にしていたお茶目なコミュニティプロダクトのFlowScanですが、このコミュニティのプロダクトもFlowの理念を受け継ぎ、ぱっと見でわかる、誰でも操作できる、誰でも親しみを持てるプロダクトになっています。
最初は同時参加型のRPGを作るつもりでした。武器屋が鍛冶屋に頼まれてモンスターのいる洞窟に鉄鉱石を取りに行く。出来た武器を戦士に売って暗号通貨を稼ぐ。盗賊がモンスターの城に行ってジェムを盗み、それをお城の役人に渡して魔法石を作る原料にしてもらう。この武器防具と魔法石を戦士に暗号通貨で買ってもらい、戦士はその魔法石などでモンスターと戦って攫われた姫を助けに行くみたいなのを作るつもりでした。
Flowにはリソースという概念があります。それにはHPや運などのステータスをそれこそTypeScriptよりも書きやすく、誰でもRPGを作れるような簡単さで作れる言語と仕様があります。
Flowを作った人(Dieter)が元Appleの開発者であり、スティーブ・ジョブズがiPhoneを開発していた時期にAppleで働いていたものですからApple熱がすごく、自然と言語はSwiftそっくりになりました。私はWebエンジニアなのでSwiftは触ったことはありませんが、こんなに書きやすい言語なんですね。
このリソースはFlowではすぐに作れて(慣れれば1日でできます)、暗号通貨などもこのリソースの役割(method)で受け渡しすることができます。
暗号通貨もNFTもリソースなので、リソースを動かせるのもリソース、というシンプルさがあり(一つのコーディングスタイルを学んだらブロックチェーンでできること全てができてしまいます)、私が作ったスマートコントラクトで言うと、こちらのAdminやGamerと書いてあるものがリソースです。
これをブロックチェーンでアカウントを作った人なら(※誰でも無料でブロックチェーンのアカウントを作れます)誰もが持っているストレージに保存することができ、ゲームの世界の一員となってゲームをやりつつ、価値のある暗号通貨やNFTなどを稼いでいくリアルワールドのe-sportsを遊ぶことができます。
その一連の情報はFlow Scanでいつでも(誰でも)、そのリソースがどう移動したのかを画像付きで確認できるわけですから(リソースは画像として表示されますのでどう動いたのかを視覚的に確認できます)、すでに世界規模での同時プレイe-sports開発体制は完成していると言えます。(FlowScanは5月にメジャーアップデートがありました)
メイキングについて
このようにリソースの概念がシンプルでとにかく頭に思いついたことは何でもすぐに(しかも安全に)実装して実現できるわけですから、何でもいいからゲームを作って世界レベルで稼ごう、と思いました。
FlowのJabaScriptライブラリであるfclが、SvelteというWebフレームワークであればNode.jsと同じように何の設定も要らずに動かせるものですから、これでゲームを作ってみようかとゲーム製作環境についてリサーチしました。そしたらSvelteはゲームを作るプラットフォームとしては、jsが早く動く特性から、世界中から高い評価を得ていたんですね。
こちらをご覧ください
これはe-sportsゲームの一部始終ですが、ゾンビに触れられると左下のゲージが減っていきます。Svelteはjsの動く速さが速いので、frame速度が速く、frame速度は表現がカクカクするかに繋がっていきますが、とにかく速いので1フレームごとにダメージではなく、5フレームごとにダメージを与えるようにしていました。
やはり優秀なフレームワークには優秀なライブラリがよく作られるということで、リサーチしているとSveltePixiというライブラリに出会います。(Pixi.jsはCanvasゲームを作る時のデファクト的なライブラリであり、今回初めて触りました。)
このサイトを見ていると非常に短いコード数でHTML5ゲームが作れるとわかり、そのGithubをクローンしました。まだ最新ステーブルバージョンがSvelte5に対応していなかったですが、Svelte4は好きなのでそれでexamples/viteの下にpackage.jsonがあったのでこれを開発プロジェクトのルートフォルダにしました。
このライブラリの作者が言っているようにexamplesの各フォルダの下でnpm run dev
コマンドを叩けばサンプル画面が立ち上がるわけで、そのためすぐにゲーム開発を行うことができました。ゲームはPixi.jsをリサーチしていて見つけたこちらのサイトのYoutubeを見ながら作りました。
ですからゲームができあがってから、そのフォルダを分離させて、個人のGithubに新たなプロジェクトとしてPushしました。そのため、init commitの中にはゲームが全て完成された状態でコードが含まれています。
この時Svelteを最新のバージョン5にしたかったけれど出来なかったので、Oraga eSportsはSvelte4で動いている、というわけです。ですが圧倒的にSvelte4は書くコード数が少ないのでSvelte5は退化している、とも言えますけどね。
Stats画面を作る
メイキングストーリーは終わりにしまして、Flow blockchainによる
e-sportsの恩恵はゲーム開発者とゲーマーだけではないことをここから書いていきます。
Stats(=統計)画面は本来は管理画面のようなものですが、ブロックチェーンの情報は世界中の人が何の許可もなしに取得できます。ですから秘匿ができない管理画面です。
このブロックチェーンの情報を集めて整形して画面を作るのは開発者にとっては嬉しいことです。何しろブロックチェーン情報自体にはお金が要らず、世界中でプレイされた情報を画面に統計情報として出せるのですから開発者だって嬉しくなります。ブロックチェーンの情報は世界規模ですから自分が作ったStats画面だって世界規模になります。
▪️Stats画面のURL:
というわけでStats画面を作りましたが、ゲーム以外は2週間で作ったものなのでこれぐらいの情報量です。
コードは
const getGamersInfo = async function () {
const result = await query({
cadence: `
import "OragaESports"
access(all) fun main(): OragaESports.GamersInfo {
return OragaESports.getGamersInfo()
}
`,
});
return result;
};
setInterval(async () => {
currentSituation = await getGamersInfo();
gamerIDs = Object.keys(currentSituation?.prizeWinners || {})
prizeWinners = []
for (let key of gamerIDs) {
const gamerInfo = currentSituation?.prizeWinners[key]
prizeWinners.push({
id: key,
name: gamerInfo?.gamerName,
prizeTotal: gamerInfo?.prize,
winCount: gamerInfo?.totalCount,
});
prizeWinners.sort((f, s) => (s.prizeTotal + s.winCount) - (f.prizeTotal + f.winCount))
}
}, 1500);
</script>
<p class="current_stats">
・ Current Prize: <img src="/assets/flow_fire.png" alt="$FLOW" />
<span class="prize">{!currentSituation?.currentPrize ? '-' : parseInt(currentSituation?.currentPrize) + 1}</span>
<span class="unit">($FLOW)</span>
</p>
<p class="current_stats">
・ Tip Jar amount: <span class="prize">₣{currentSituation?.tipJarBalance ? parseInt(currentSituation?.tipJarBalance) : '-'}</span>
<span class="unit">($FLOW)</span>
</p>
<p class="current_stats">
・ Prize Winners: <br>
{#each prizeWinners as gamer, i}
<div class="gamer_info">
ID{gamer.id} {gamer.name} -> <span class="prize">₣{parseInt(gamer.prizeTotal) + parseInt(gamer.winCount)}</span>
({gamer.winCount})
</div>
{/each}
</p>
といった感じですね。1時間もかからずにできてしまいました。ブロックチェーンのアプリを作るのってすっごい簡単なんですよね。
Oraga eSportsで使用した各情報をまとめてみましたのでよかったら見ていってください。
▪️Oraga eSportsの各情報==
使用した技術:
- AWS Lambda Function
- S3
- CloudFront
- AppSync (最初のDataSourceの設定だけ)
- Svelte+Vite (Svelteはv4をFork開発してほしい)
- PIXI.js
- SveltePixi
ソースコード一覧:
- Shooting.svelte コイン投入以外のブロックチェーンとのやり取りが実装
- Player.svelte コイン投入後の実装とGraphQLとのやり取り
- schema.graphql GraphQLスキーマの実装
- index.mjs GraphQL のバックエンド処理、トランザクション処理
- OragaESports.cdc Mainnetにデプロイされているスマートコントラクト
- flow.json デプロイ情報や各環境に接続する先などがまとめられている
- scripts.js ブロックチェーンに対する問い合わせ処理の実装
- transactions.js ブロックチェーンに対する変更処理の実装
- addKey.cdc アカウントのkeyIDに公開鍵を追加する実装
- sendFlow.js ゲームの売り上げをウォレットに送金する実装
その他
- App.svelte ルーティングおよびトップ画面の実装
- Zombie.svelte 敵キャラの動きを定義
- Contents.svelte プレイヤーや弾、敵キャラの配置。難易度もここで調整
- Field.svelte 背景処理
参考文献:
Create Accounts & Deploy Smart Contracts on TestNet using the Flow CLI
How to Create a Testnet/Mainnet Account using the Flow CLI
FLOW dApp 作成完全マニュアル (テストネット環境接続など)
SvelteとGraphQLでブロックチェーンゲームを作る! (GraphQLリゾルバ周りの設定情報)