ブロックチェーンゲーム制作チェーン -Minimal Arcade Medal-

ブロックチェーン技術、ゲーム作成のためのコード、ドット絵やアニメーションの作り方を解説するブログです。最終的に記事の内容を組み合わせることで誰でもブロックチェーンゲームが作れるようにしたいです。Micro Arcade MedalというdApps開発中です。

CocosCreatorとLoom SDKでブロックチェーンとゲームを連携させる方法

ゲームとブロックチェーンを連携させて、データを読み書きしてみようという内容です。


この記事ではCocosCreatorとLoom SDKを使います。


そもそもCocosって何?という方はこちらの記事が参考になると思います。
medium.com


またLoom SDKって何?という方にはこちらの記事が参考になると思います。
medium.com

環境準備

扱うサンプルコードはloomDemoForCreatorです。


サンプルコードならびにLoom SDK、CocosCreatorの導入手順は下記のドキュメントを参照してみてください。


ちなみに僕が詰まった箇所は

git submodule update --init

これがエラー吐きまくってて心折れかけたんですが、無事解決しました。
Loom SDKとかCocosCreator以前にgitですね笑
gitのkeyChainの設定を間違えていて、gitアカウントとローカルでの情報が違っていたのでそれを修正しました。

コードの挙動

無事導入できたら
/cocos-sdk/sample
にあるloomDemoForCreatorをCocos Creatorを開きたいんですが、まずブロックチェーンをRunしなければいけません。


詳細な手順は上記の記事に載っているんですが、具体的にはblueprintというスマートコントラクトがLoomブロックチェーン上で動いている状態にします。


これをしとかないとプロジェクト開いた時エラーが出るかもです。
先に接続先立ち上げて置くということですね。


2018/07/08 15:01:33 Sending logs to file://-
2018/07/08 15:01:34 Sending logs to file://-
I[07-08|06:01:34.284] Using simple log event dispatcher
I[07-08|06:01:46.677] Starting RPC HTTP server on tcp://127.0.0.1:9999 module=query-server



無事起動するとこんなメッセージが現れます。


そしたらプロジェクトを開きます。


f:id:kusakabob:20180708145317p:plain


こんな画面が出てきます。そしてRunすると


f:id:kusakabob:20180708145707p:plain


SaveとGetと書かれたボタンがあるだけという、非常にシンプルな作りですね。


コードもシンプルです。ちなみに少し実験のためにいじってあるのでOriginalとは少し違います。

main.js

import createContract from './SimpleContract'


cc.Class({
    extends: cc.Component,

    properties: {
  
    },

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {},

    start () {
        const self = this;
        this.count = 1;
        this.contract = null;
        createContract(function(err, c) {
            if (err) {
                cc.log('ERROR! create contract failed' + JSON.stringify(err));
                return;
            }
            self.contract = c;
        });
    },

    onBtnSave() {
        if (null == this.contract) {
            cc.log('ERROR! contract is null');
            return;
        }
        cc.log('button save clicked');
        const stringScore = JSON.stringify({yap:"yas",boo:2});//+ Math.round(cc.random0To1() * 255);
        this.contract.store('score'+this.count, stringScore, function(e) {
            if (e) {
                cc.log('ERROR! store failed');
                return;
            }
            cc.log('SUCCESS! store success:' + stringScore);
        });
        this.count += 1;
    },

    onBtnGet() {
        if (null == this.contract) {
            cc.log('ERROR! contract is null');
            return;
        }
        cc.log('button get clicked');

        var i;
        for(i=1;i<this.count;i++){

        this.contract.load('score'+i, function(e, result) {
            if(e) {
                cc.log('ERROR! load failed:' + JSON.stringify(e));
                cc.log(e.stack)
                cc.log(e.toString());
                return;
            }
        var obj = JSON.parse(result);
        cc.log(obj.yap);
            cc.log('SUCCESS! load value finish');
          
        });
    }

    },

    // update (dt) {},
});

ボタンを押すとどうなるのか

SaveとGetを押すとどうなるのか。
結論からいうと、Saveで0から255のランダムな数がブロックチェーンに保存されます。
Getでその数を持ってくることができます。

上記以外は初期化と例外処理ですね。

onBtnSave() {

        ...

        const stringScore = JSON.stringify({yap:"yas",boo:2});//'' + Math.round(cc.random0To1() * 255);
        this.contract.store('score'+this.count, stringScore, function(e) {
            if (e) {
                cc.log('ERROR! store failed');
                return;
            }
            cc.log('SUCCESS! store success:' + stringScore);
        });
        this.count += 1;
    },


stringScoreの部分、番号じゃなくてJSONを突っ込んでますがコメントアウトされてる部分がオリジナルです。
createContractという関数でSimpleContractへの参照を獲得しているんですが、これはブロックチェーン上のスマコンに接続するためのクラスです。
こいつのstoreメソッドで(key,value,callback)を入れてやると値が保存されます。

onBtnGet() {

        ...

        var i;
        for(i=1;i<this.count;i++){

        this.contract.load('score'+i, function(e, result) {
            if(e) {
                cc.log('ERROR! load failed:' + JSON.stringify(e));
                cc.log(e.stack)
                cc.log(e.toString());
                return;
            }
        var obj = JSON.parse(result);
        cc.log(obj.yap);
            cc.log('SUCCESS! load value finish');
          
        });
    }


こちらはGetボタンを押した時の処理です。
loadメソッドに(key,callback)を入れるとresultから値を参照できます。
上記のコードも少し改造しているのでオリジナルとは違います。


オリジナルはSaveボタンを何回押してもscoreを上書きするので、ブロックチェーンに1つ以上値が保存されませんでした。
実験では押すたびにキーを変更して、ブロックチェーン上に複数の値を持たせるということを試してみました。


また、JSONや配列など複雑な構造のデータを保存することができるのかということも試してみました。
JSONからStringに変換して送ることと、StringからJSONに変換して値を獲得することができました。


f:id:kusakabob:20180708153552p:plain

所感

JSONの読み書きできたら、このサンプルコードを応用するだけでいろんなものが作れそう!
とはいえ、大体のケースにおいてブロックチェーンである必要はなく、普通のデータベースでよくね?とはなります。
様々なアイデアを試してブロックチェーンならではと行ったユースケースを作ることが課題ですね。
あと小並感ですが例外処理は大事だなと思いました。


ちなみに今回はmain.jsにしか触れませんでしたが、StoreやLoadを定義しているSimpleContract.jsやデータを暗号化するためのsetscore_pbなどがあります。
main.jsはあくまでユーザーインターフェース周りなので、完全に理解するためにはまだまだコード読み込まないといけないです。