COCOS2D-Xの開発環境を作成してWindowsで動かすまでの話

こちらの話の続き。

ついでだからWindowsで動かすところまでやりました。

Android端末が入らない分、デバッグが楽になるかもしれないので。

必要なのはVisual Studio 2017。

2019ではダメです。

ツールの機能取得で、以下の機能をインストールします。

たぶん、必要なのはこれだけだと思う。

cocos run -p win32

で動きました。

Visual Studio 2017のRUNでも動くよ。

Cocos2d-xの開発環境を作成してAndroidで動かすまでの話

一応、プロジェクトを作成して、Hello Worldが出るまでやりました。

手順などは、Qiitaにまとめましたが、

https://qiita.com/takishita2nd/items/0b54af9860f54c65fd24

実際はもっと手こずったので、いろいろと愚痴を書きたい。

まず、Python2.7で無ければセットアップからプロジェクト作成まで動かないのだが、

Python3が動いているのは分かっているのにPython3の本体がどこにあるか分からない、という自体に。

そもそもWindowsにインストールした覚えがない。

ググってプログラムの本体を調べるコマンドを探しまして、

where python

って打てば良いんですけど、

これコマンドプロンプロのコマンドね。

最近はPowerShellをよく使うから。

C:\Users\[ユーザー名]\AppData\Local\Microsoft\WindowsApps\python.exe

にありました。

分かるか。

展開したPython2.7を展開し、環境変数のPATHの設定で、上のフォルダの記載がある場所の上にPython2.7のPATHを書かなければならない。

PATHの検索順をPython2.7→Python3に変えるんですね。

めんどくせぇ。

今時Python2.xなんて使うやついないよ。(たぶん)

もう設定元に戻したわ。

プロジェクト作るときだけ変えれば良い。

そして、もう一つ、Cocoa2d-xってWindowsでも動かすことができるんですが、

いわゆるマルチプラットフォームになっていて、C++の共通コードだけ記述すれば、他のOSでも動かすことができる。

しかし、Windowsで動かす場合は

Visual Studio 2017が必要。

2019ではダメらしい。

めんどくさい。

(一応動かしたけど、後でまとめるわ)

でも、動いたので、あとはガリガリC++のコードを書いていけば。

IDE何使えば良いんだ?

【openTK】STLファイルを表示させたい。

以前取り上げたopenTKのやつ。

これを使ってSTLファイルを表示する、というのをやってみたいと思います。

使用するSTLファイルは、こちらからダウンロードしました。

https://www.3dagogo.com/creativetools/designs/3DBenchy

ただしく処理できれば、こんな風に表示されるはずです。

STLファイルの読み込みはこちらのサイトを参考にしました。

https://codingsquare.net/cs/stlfile/#toc11

STLのデータは法線ベクトルと、三角形を構成する頂点の座標を示す3つのベクトルで構成されています。

法線ベクトルは三角形の面の表側を向いている方向を示すベクトルです。

		public bool ReadBinary(string filePath)
		{
			// filePath が null か、ファイルが存在しない場合はエラーとする
			if (filePath == null || File.Exists(filePath) == false)
				return false;

			try
			{
				// バイナリファイルの読み込み
				using (var reader = new BinaryReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)))
				{
					// ヘッダ読み込み
					Header = reader.ReadBytes(HeaderLength);

					// ファセットの枚数読み込み
					uint size = reader.ReadUInt32();

					// ファイルの残りのバイト数
					long rest = reader.BaseStream.Length - reader.BaseStream.Position;

					// ファセット1枚分のバイト数
					const int FacetLength = 50;

					// ファイルの残りのバイト数が、求められるファセットの枚数分のバイト数より少なければエラー
					if (rest < FacetLength * size)
						return false;

					// 全ファセット読み込み
					Facets = new Facet[size];
					for (int i = 0; i < size; ++i)
					{
						// ファセット1個分のバイト配列読み込み
						byte[] bytes = reader.ReadBytes(FacetLength);

						// ファセットデータ生成と配列への格納
						int index = 0;
						const int offset = sizeof(float);
						Facets[i] = new Facet(
							new Vertex(
								BitConverter.ToSingle(bytes, index),
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset)),
							new Vertex(
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset)),
							new Vertex(
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset)),
							new Vertex(
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset),
								BitConverter.ToSingle(bytes, index += offset))
						);
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

これでバイナリのSTLデータを読み込み、描画させます。

        STLFile stlFile = new STLFile();
        public Game() : base(800, 600, GraphicsMode.Default, "0-3:GameWindow")
        {
            stlFile.ReadBinary("3DBenchy.stl");
        }

        //画面描画で実行される。
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            GL.MatrixMode(MatrixMode.Modelview);
            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
            GL.LoadMatrix(ref modelview);

            int count = 0;
            foreach(var f in stlFile.Facets)
            {
                count++;
                GL.Begin(BeginMode.Triangles);

                GL.Color4(Color4.White);
                GL.Normal3(f.Normal.X, f.Normal.Y, f.Normal.Z);
                GL.Vertex3(f.Vertex1.X / 30, f.Vertex1.Y / 30, f.Vertex1.Z / 30);
                GL.Vertex3(f.Vertex2.X / 30, f.Vertex2.Y / 30, f.Vertex2.Z / 30);
                GL.Vertex3(f.Vertex3.X / 30, f.Vertex3.Y / 30, f.Vertex3.Z / 30);

                GL.End();
            }

            SwapBuffers();
        }

そしてライトの設定も加えます。

こちらのサイトを参考にしました。

https://ameblo.jp/nishi-u6fa4/entry-10864018960.html

        //ウィンドウのサイズが変更された場合に実行される。
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
            GL.MatrixMode(MatrixMode.Projection);
            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)Width / (float)Height, 1.0f, 64.0f);
            GL.LoadMatrix(ref projection);
            GL.MatrixMode(MatrixMode.Modelview);

            Matrix4 look = Matrix4.LookAt(3.0f * Vector3.One, Vector3.Zero, Vector3.UnitY);
            GL.LoadMatrix(ref look);
            GL.Enable(EnableCap.Lighting);
            float[] position = new float[] { 1.0f, 2.0f, 3.0f, 0.0f };
            GL.Light(LightName.Light0, LightParameter.Position, position);
            GL.Enable(EnableCap.Light0);
        }

実行結果はこちら。

なんだこりゃ。

たぶん、データは間違ってないと思うんですよ。

問題は視点なのかな、と思います。

視点を変えるとか、変更できるようにすればちゃんと表示させることができるかもしれません。

もうちょっと勉強します。

【北海道大戦】今後の実装について

まぁ、いまのままでもそこそこ楽しめるのですが、

ゲーム性を高めるために、いろいろ実装していこうかと思います。

まずは、今のバトルは完全乱数で発生させた値でのバトルなので、

ゲーム性を高めるために、じゃんけんバトルのようなものにしようかと思います。

そうなると必要なのがAltseedのシーン切り替え機能ですかね。

このシーン切り替え機能を使用するのに、どれだけ回収が必要なのかも考えないと行けません。

その検証を次回やりましょう。

あと、今は防御側勝利時、特に何もメリットがないので、防御側勝利時に1ターン戦力ボーナス・ペナルティを付与しようかなと思っています。

たぶん、そうすることでゲーム性が向上すると思うんですよね。

よし、がんばります。

あ、あと、Altseed2というのがリリースされたみたいですね。

https://altseed.github.io/index.html

【ラズパイ】【いろいろ計測モニター】あれから改造。

とりあえず、少し改造しました。

調べてみると、GPU温度も測定できるみたいなので、それも入れてみました。

ラズパイのGPU温度を確認するコマンドは、

sudo /opt/vc/bin/vcgencmd measure_temp

sudoなので、pythonプログラム実行時もsudoで管理者権限で実行しなければなりませんが、

サービスで実行させているので、基本的に管理者権限で動作しているので、問題無いでしょう。(実際、動いた。)

時刻というのは現在時刻じゃなくて、最後に測定した時刻です。

HTTPでラズパイからデータを取得していますが、間隔を短くすると、ラズパイZeroでもCPU温度が上がってしまうので、少し間隔を空けています。(1分ぐらい)

次どうしようか。

新しい部品があればネタに出来そうだけど、今はお金が無いので。

グラフ化させてみる?

防水タブレットが欲しいなぁって思ったんですが。

お風呂にタブレット持ち込めれば、最近見れていないアニメも消化できるのですが。

目にとまったのはこれ。

https://www.nttdocomo.co.jp/product/d41a/

dtab d-41Aなんですが。

dtabは低スペックで低価格ですが、dが付いているだけまだ安心できる性能は発揮してくれるハズ。

いままでのdtabもそうだった。

しかし、一括購入で5万円か・・・

オイラ、ブラックリストに入っているから分割できないのよね。

で、いろいろ考えた結果、こういう結論になりました。

タブレット用の防水カバー。

今持っているiPad Pro(第2世代 11インチ)入りました。

入り口はジッパー二つでガード+折り曲げてマジックテープなので、水没しない限りは水が入ることは多分ありません。

指も反応するし、FaceIDも使える(場合による。最悪数字入力でロック解除すれば良い)し、音も十分聞こえます。

全然こっちの方が安かった。

これでお風呂タイムも楽しめるぜ!

GoToイートってどういう仕組みなんですか?

先日GoToイートの委託先事業者が決まったというニュースが流れてきたので、

農林水産省のサイトに情報が載っています。

https://www.maff.go.jp/j/shokusan/gaisyoku/hoseigoto.html

外食をして外食産業や消費を促進させようという事ですね。

GoToイートはお食事券とポイント還元の二本柱で構成されていて、

お食事券は25%のプレミア付きで利用できるのですが、

対象地域は33府県で、北海道は含まれておりません。

最終的に全国で利用できるようになりました。

ただし、まだ販売方法が決まっていないので、今後の情報をお待ちください。

ポイント還元は予約サイトで予約してお食事すると、ポイントが多くもらえる仕組みです。

ランチで500ポイント、ディナー(午後3時以降)で1000ポイントとなります。

そのポイントを使ってもっとお食事に行こうということですね。

対象事業者を見てみると、ぐるなびリクルート(ホットペッパー)などが含まれています。

出前は含まれていないようですね。

遠出は怖いけど、近場だったら予約してお食事するというのも良いかもしれない。

こういう制度はどんどん利用しようぜ。

【ダイエット支援】【食事管理】グラフデータ取得処理を作成する。

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/diet-mng

ダッシュボードに表示するグラフを作成していきます。

どんあグラフにしようかというと、

こんな感じのレーダーグラフです。

一日分の摂取したタンパク質、脂質、炭水化物などの情報を取得するAPIが必要になります。

まずは、それを作ります。

app/Repository/EatingManagementRepository.php

    /**
     * 一日あたりのデータを取得する
     */
    public function getDaily($user, $date)
    {
        $eatings = $user->EatingManagements()
            ->where(DB::raw('date_format(date, "%Y-%m-%d")'), $date)
            ->get();

        $retDatas = [];
        for($j = 2; $j < count($this->paramNames); $j++) {
            $retDatas[$this->paramNames[$j]] = 0;
        }
        foreach($eatings as $eating) {
            for($j = 2; $j < count($this->paramNames); $j++) {
                $retDatas[$this->paramNames[$j]] += $eating->{$this->paramNames[$j]};
            }
        }
        return $retDatas;
    }

$dateに取得する日付が入ります。

その日付に一致するデータをすべて取得し、それを栄養素毎に集計します。

これをAPIで取得するようにします。

app/Http/Controllers/Eating/ApiController.php

    /**
     * グラフ用データを取得する
     */
    public function graph(Request $request)
    {
        return response()->json(['data' => $this->eatingManagement->getDaily(Auth::user(), $request->contents['date'])]);
    }
routes/web.php

Route::post('api/eating/graph', 'Eating\ApiController@graph');

これをダッシュボードからデータを取得し、グラフにします。

resources/assets/js/components/Eating/EatingDashboardComponent.vue

            param: {},
            contents: {
               date: "",
            },
            label: ['タンパク質', '脂質', '炭水化物', 'カロリー'],
            datasets: [],
            sub: 0,
        };
    },
    created: function() {
        this.todayDate = this.getDate(this.sub);
    },
    mounted: function() {
        this.graphUpdate();
    },
    methods: {
        getDate: function(sub) {
            var today = new Date();
            return today.getFullYear() + "-" + ('00'+(today.getMonth() + 1)).slice( -2 ) + "-" + ('00'+(today.getDate() + sub)).slice(-2);
        },
        onClickNext: function() {
            this.sub++;
            this.todayDate = this.getDate(this.sub);
            this.graphUpdate();
        },
        onClickPrev: function() {
            this.sub--;
            this.todayDate = this.getDate(this.sub);
            this.graphUpdate();
        },
        onClickInput: function() {
            this.showInputDialogContent = true;
        },
        invokeUpdateList: function() {
            this.graphUpdate();
        },
        graphUpdate: function() {
            var ctx = document.getElementById("eating");
            var self = this;
            this.contents.date = this.todayDate;
            this.param.contents = this.contents;
            this.datasets = [];
            axios.post('api/eating/graph', this.param).then(function(response){
                if(response.data.data != null) {
                    self.datasets.push(response.data.data.protein);
                    self.datasets.push(response.data.data.liqid);
                    self.datasets.push(response.data.data.carbo);
                    self.datasets.push(response.data.data.calorie);
                    var myChart = new Chart(ctx, {
                        type: 'radar',
                        data: {
                            labels: self.label,
                            datasets: [{
                                label: self.todayDate,
                                data: self.datasets,
                                backgroundColor: 'RGBA(225,95,150, 0.5)',
                                borderColor: 'RGBA(225,95,150, 1)',
                                borderWidth: 1,
                                pointBackgroundColor: 'RGB(46,106,177)'
                            }]
                        },
                        options: {
                            title: {
                                display: true,
                                text: '摂取栄養素'
                            },
                            scale:{
                                ticks:{
                                    suggestedMin: 0,
                                    suggestedMax: 100,
                                }
                            }
                        }
                    });
                } else {
                    var myChart = new Chart(ctx, {
                        type: 'radar',
                        data: {
                            labels: self.label,
                            datasets: [
                            ]
                        },
                    });
                }
            }).catch(function(error){
            });
        }

デフォルトはアクセスした当日を表示し、next、prevクリックでそれぞれ次の日、前の日に切り替えることができるようにします。

getDate()で取得する日付の文字列を取得し、これをAPIのパラメータとします。

取得したデータをグラフのdatasets[]に設定すれば、グラフが表示されます。

次回はこのグラフをもっと見やすいようにカスタマイズしていきます。

Pixel4aを使ってみた結果、ほとんどの人はハイエンドなんて不要だった。

Pixel4aを使い始めて2日が経過しました。

いまのところ、なんの問題もなく動作しております。

ゲームも問題ありません。

むしろ、Pixel3より軽快に動ています。

これは買い替え成功間違いなし。

「戻る」の操作が変わったので、いまだにそこは慣れないですが、慣れればこちらのほうがサクサク操作できそうです。

メモリの量が増えたというのもあるかもしれませんが、

このスマホはミドルレンジのプロセッサーを使用しています。

はい、ほとんどの人たちにとってはハイエンドのスマホなんて不要だったんですね。

逆に、Pixel4aがここまで快適に動くのなら、低価格スマホは全部クソになりました。

低価格スマホに手を出して失敗するよりは、オイラは+1万ぐらい出してでもPixel4aを勧めます。

なんか5G対応機種が予定されているようですが、5G普及までにはまだ1~2年かかりますので、その頃には新機種が出ているので全く問題ありません。

そもそも、4Gまでは、それまで出来なかったことが出来るようになった、という点がありましたが、

5Gでは、今まで出来た事がより便利になった、という程度なので、焦って5Gにする必要はないです。

さて、今まで使用していたPixel3ですが、ヤフオク!に出品しようと思います。

いまの相場なら2~3万程度で売れるはず。

【ガルパ】ガチのバンドリーマーがナナオンをプレイした結果

もうナナオンをプレイ初めて三ヵ月ぐらいになる?

ナナオンをプレイして、その相乗効果といいますか、ガルパの腕前が上がりました。

その証拠。

初のレベル28フルコンしました。

flame of hopeも実装当日にフルコンしました。

おそらくですけど、

リズムゲーム上達の近道は、たくさんの種類の譜面をプレイすることじゃないかな、と思います。

ガルパリリース当初から高難易度曲をプレイできていた人たちは、おそらく以前からアーケードの音ゲーをプレイしてきた人たちではないでしょうか。

ここまでくればEXトライマスター狙えるかな、と思いましたが、

世の中そんなに甘くなかった。

もっと修行します。