あれから二日経ちましたか。
体調は大分良くなりました。
まだかすかに耳鳴りがありますが、ほとんど気にならないレベルです。
やっぱりノングレア非対応ディスプレイが原因だったのですね。
あとは一日の内、定期的に目を休ませることにする。
アイマッサージャーとか使っていましたが、
なんだかんだ言って、一番良いのは蒸しタオルじゃないかと思いまして。
一番手軽。
蒸しタオルのやり方。
手ぬぐいを水で濡らして固く絞る。
それをレンジで1分間チンする。
以上。(火傷に注意)
引き続き体調回復に努めます。
前回までの状況はこちら

最新ソースはこちら(gitHub)。
https://github.com/takishita2nd/diet-mng
前回計算した内容をデータベースに保存・読み出しを行う機能を実装します。
まずはデータベースのマイグレーションを作成。
class CreateEatingTarget extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('eating_targets', function (Blueprint $table) {
$table->bigIncrements('id');
$table->double('protein');
$table->double('liqid');
$table->double('carbo');
$table->double('calorie');
$table->timestamps();
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
});
Schema::create('eating_target_user', function (Blueprint $table) {
$table->integer('user_id')
->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->integer('eating_target_id')
->foreign('eating_target_id')
->references('id')->on('eating_targets')
->onDelete('cascade');
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('eating_target_user');
Schema::dropIfExists('eating_targets');
}
}
$ php artisan migrate
このテーブルのモデルを作成。
class EatingTarget extends Model
{
protected $table = 'eating_targets';
public function users()
{
return $this->belongsToMany('App\User');
}
}
Userテーブルからのリレーションも作成します。
class User extends Authenticatable
{
public function EatingTargets()
{
return $this->belongsToMany('App\Model\EatingTarget');
}
このデータベースにアクセスするためのAPIを作成します。
セット処理。
Route::post('api/eating/settarget', 'Eating\ApiController@setTarget');
class ApiController extends Controller
{
/**
* 目標栄養素を設定する
*/
public function setTarget(Request $request)
{
$paramNames = $this->eatingManagement->getTargetParam();
$param = [];
foreach($paramNames as $name) {
$param[$name] = $request->contents[$name];
}
$this->eatingManagement->setTarget($param, Auth::user());
return response()->json();
}
use App\Model\EatingTarget;
class EatingManagementRepository
{
private $targetParamNames = ['protein', 'liqid', 'carbo', 'calorie'];
public function setTarget($param, $user)
{
$model = $user->EatingTargets()->first();
if(is_null($model)) {
$model = new EatingTarget();
}
foreach($this->targetParamNames as $name)
{
$model->$name = $param[$name];
}
$model->save();
$this->attachToUser($model, $user);
}
public function getTargetParam()
{
return $this->targetParamNames;
}
これをVue.jsの処理に組み込みます。
methods: {
clickAdd: function() {
var self = this;
this.param.contents = this.contents;
axios.post('/api/eating/settarget', this.param).then(function(response){
self.closeModal();
self.$emit('update');
}).catch(function(error){
self.error_flg = true;
self.errors = error.response.data.errors;
});
},

次は、このデータを読み出す処理を実装します。
グラフデータを読み出すAPIがすでにありますので、これにデータを追加します。
class ApiController extends Controller
{
/**
* グラフ用データを取得する
*/
public function graph(Request $request)
{
return response()->json([
'data' => $this->eatingManagement->getDaily(Auth::user(), $request->contents['date']),
'target' => $this->eatingManagement->getTarget(Auth::user())
]);
}
class EatingManagementRepository
{
public function getTarget($user)
{
return $user->EatingTargets()->first();
}
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(Math.ceil(response.data.data.protein / response.data.target.protein * 100));
self.datasets.push(Math.ceil(response.data.data.liqid / response.data.target.liqid * 100));
self.datasets.push(Math.ceil(response.data.data.carbo / response.data.target.carbo * 100));
self.datasets.push(Math.ceil(response.data.data.calorie / response.data.target.calorie * 100));
var myChart = new Chart(ctx, {

なかなかいい感じなので、これで行きましょう。
今日はもう一個やったので、まとめておく。
シーンを追加する場合。
Cocos2d-xでは1シーンにつき1クラスと考えまして、
今回はSampleSceneを追加してみます。

C++の場合はクラスを記入したヘッダーファイルと、処理本体を記述したソースファイル本体を作成します。

中身は、とりあえずHelloWorldとほぼ同じにして、最初にSampleSceneを表示するようにします。
class SampleScene : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(SampleScene);
};
#include "SampleScene.h"
#include "SimpleAudioEngine.h"
USING_NS_CC;
Scene* SampleScene::createScene()
{
return SampleScene::create();
}
// Print useful error message instead of segfaulting when files are not there.
static void problemLoading(const char* filename)
{
printf("Error while loading: %s\n", filename);
printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}
// on "init" you need to initialize your instance
bool SampleScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Scene::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
if (sprite == nullptr)
{
problemLoading("'HelloWorld.png'");
}
else
{
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(sprite, 0);
}
return true;
}
void SampleScene::menuCloseCallback(Ref* pSender)
{
//Close the cocos2d-x game scene and quit the application
Director::getInstance()->end();
/*To navigate back to native iOS screen(if present) without quitting the application ,do not use Director::getInstance()->end() as given above,instead trigger a custom event created in RootViewController.mm as below*/
//EventCustom customEndEvent("game_scene_close_event");
//_eventDispatcher->dispatchEvent(&customEndEvent);
}
// create a scene. it's an autorelease object
auto scene = SampleScene::createScene();
// run
director->runWithScene(scene);
return true;
}
ただ、C言語やっている人なら分かると思いますが、これだけじゃあビルドしてくれません。
通常はmakefileを弄るのですが、WindowsはVisualStudio、AndroidはAndroid Studioでビルドするので、
VisualStudioの場合
プロジェクト名\proj.win32\プロジェクト名.vcxproj
のここに追加するファイルを記載する。
<ItemGroup>
<ClCompile Include="..\Classes\AppDelegate.cpp" />
<ClCompile Include="..\Classes\HelloWorldScene.cpp" />
<ClCompile Include="..\Classes\SampleScene.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Classes\AppDelegate.h" />
<ClInclude Include="..\Classes\HelloWorldScene.h" />
<ClInclude Include="..\Classes\SampleScene.h" />
<ClInclude Include="main.h" />
</ItemGroup>
Androidの場合
プロジェクト名\CMakeLists.txt
のここに追加するファイルを記載する。
# add cross-platforms source files and header files
list(APPEND GAME_SOURCE
Classes/AppDelegate.cpp
Classes/HelloWorldScene.cpp
Classes/SampleScene.cpp
)
list(APPEND GAME_HEADER
Classes/AppDelegate.h
Classes/HelloWorldScene.h
Classes/SampleScene.h
)
Mac/iOSはXcodeのメニューから追加すれば良いと思う。(知らんけど)
こういうシーンの追加って、cocosコマンドでなんとかできないんですかね?
シーンに限らず、クラス追加するときも同じか。
めんどくさい。
前回の記事でシーンの内容は大体分かった。
ちょっと気になるのはvisibleSizeとoriginの値。
じゃあ、visibleSizeとoriginの値をラベルに表示させちゃおう。
auto str = String();
str.appendWithFormat("visible (%f %f)", visibleSize.width, visibleSize.height);
auto label = Label::createWithTTF(str.getCString(), "fonts/msgothic.ttc", 24);
if (label == nullptr)
{
problemLoading("'fonts/msgothic.ttc'");
}
else
{
// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// add the label as a child to this layer
this->addChild(label, 1);
}
auto str2 = String();
str2.appendWithFormat("origin (%f %f)", origin.x, origin.y);
auto label2 = Label::createWithTTF(str2.getCString(), "fonts/msgothic.ttc", 24);
if (label2 == nullptr)
{
problemLoading("'fonts/msgothic.ttc'");
}
else
{
// position the label on the center of the screen
label2->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height * 2));
// add the label as a child to this layer
this->addChild(label2, 2);
}
フォントについて
フォントはResource/fontsフォルダに拡張子ttfファイルが置いてあると思いますが、
Label::createWithTTF()をコールするときにフォントファイルを指定します。
Windowsだったらフォントはc:\windows\fontsがあるので、ここにあるttf/ttcファイルをここに置けば使用することができます。

文字列について
文字列はcocos2dx::Stringというクラスが存在するらしい。
これを使った方がいろいろと便利なので、これを使用する。
addChild()の第二パラメータ
これはzIndexとあったので、重ねて表示する場合、上に表示する順番を示すパラメータですね。
数字が大きい方が上に表示されるみたいです。
Windowsでの表示結果。

visibleは画面のサイズ、originは原点の座標のようです。
Windowsはこれでいいのですが、Android(pixel4a)の場合はこうなりました。

Pixel4aはちょっと横長なので、heightが少し小さいようです。
アスペクト比が異なり、アスペクト比は長辺が基準なので、その分heightが小さいのですね。
あと、左下にピンホールカメラがあるので、その分だけ、originのy座標が少し上になっていますね。
特殊ディスプレイ、嫌い。
まぁ、この点はどうするか後で考えよう。
以前話していたVDT症候群のような症状。
もしかしたらと思いまして、
古いディスプレイの電源を切って使用しないようにしていたところ、
だいぶ症状は改善してきました。
まだ耳鳴りするけど、そんなに気になるほどじゃないです。
というのも、この古いディスプレイ、
ノングレアディスプレイじゃないのです。
グレアというのは、室内の光りがディスプレイに反射して映る現象で、
これが目にあまり良くない。
最近のディスプレイはこういった現象を起きないようにするノングレア対応されています。
今使用している二枚のディスプレイは、いずれもノングレアディスプレイです。
まぁ、今回のは飛び抜けて一番古いディスプレイだったからねぇ。
仕方が無いけど、引退していただこう。
新しいディスプレイ買わなきゃ。

さらに強い敵を求めて、新たな大陸のダンジョンを攻略していきます。
1回攻略したダンジョンはアイテムは復活しないのですね。
ダンジョンはタルが沢山あるので、それを破壊すると調味料が手に入るし、
ダンジョン内の敵モブを倒すと作物の種が手に入ったりします。

ボスは光っているコアが弱点なので、ジャンプアタックを繰り返すと倒せます。
この種とは別のボスはいるのですか?

腰の所に立ててしまえます。
こうなればコア攻撃し放題。

最後のここを空けると、アヌビスに渡せるアイテムが手に入ります。
と言うことは、たくさんダンジョンを攻略すれば良いのですね。

拠点もかなり充実してきました。
まだ自動化は難しいですけどね。

なんか大量に届いた(6枚)
これを使用すると豚チャーシューが電子レンジで作れてしまうらしい。
ということで。

豚バラブロック500グラム。
スチーミー1枚当たり、250グラムらしいので。

4等分。
フォークで表面に穴を空けて、
1枚当たり2ブロックをスチーミーに入れます。

ああ、チャックを空けると、かなりニンニクの匂いが効いてるね。
これを、向きに注意して電子レンジでチンする。
うちの電子レンジは500Wなので、1枚ずつ9分30秒チンし、そのあと5分放置。

出来上がった物はこちら。
見た目はかなり良い感じです。
ちなみに、パックの中はかなり脂でギットギトです。
この残ったタレ、後で使おうと思ったけど遠慮しておきます。

切り分けるとこんな感じ。
はしっこの方を食べてみると、表面は少しカリッとしていて、良い感じに脂が抜けております。
これは丼にして食べよう。

さすがに全部一気に食べると確実に太るので、タッパーに取ってあります。
これらは後でラーメンを食べるときに焼いてトッピングにしましょう。
しかし、電子レンジで15分足らずでこんなに美味しいチャーシューが食べられるとは、
予想外でした。
スチーミーの構造的に蒸気で圧力がかかっている状態なので、圧力鍋で調理している感じらしい。
短時間で調理できるので、ガス代もかからないのでかなり便利です。
これ、チャーシュー以外に使えないかな?
前回までの状況はこちら。
最新ソースはこちら(gitHub)。
https://github.com/takishita2nd/HokkaidoWar
バトルシーンの画面を作成していきます。
とは言っても部品を配置しているだけですが。
class BattleScene : asd.Scene
{
private asd.TextObject2D _label = null;
private asd.TextObject2D _attackCity = null;
private asd.TextObject2D _deffenceCity = null;
private asd.TextureObject2D _image_gu_attack = null;
private asd.TextureObject2D _image_choki_attack = null;
private asd.TextureObject2D _image_par_attack = null;
private asd.TextureObject2D _image_gu_deffence = null;
private asd.TextureObject2D _image_choki_deffence = null;
private asd.TextureObject2D _image_par_deffence = null;
private asd.TextObject2D _attackParam = null;
private asd.TextObject2D _deffenceParam = null;
public BattleScene()
{
}
protected override void OnRegistered()
{
var layer = new asd.Layer2D();
AddLayer(layer);
// 下地
var background = new asd.GeometryObject2D();
layer.AddObject(background);
var bgRect = new asd.RectangleShape();
bgRect.DrawingArea = new asd.RectF(0, 0, 1800, 1000);
background.Shape = bgRect;
_label = new asd.TextObject2D();
_label.Font = Singleton.GetLargeFont();
_label.Text = "VS";
_label.Position = new asd.Vector2DF(470, 400);
layer.AddObject(_label);
_attackCity = new asd.TextObject2D();
_attackCity.Font = Singleton.GetLargeFont();
_attackCity.Text = "札幌";
_attackCity.Position = new asd.Vector2DF(450, 150);
layer.AddObject(_attackCity);
_deffenceCity = new asd.TextObject2D();
_deffenceCity.Font = Singleton.GetLargeFont();
_deffenceCity.Text = "小樽";
_deffenceCity.Position = new asd.Vector2DF(450, 650);
layer.AddObject(_deffenceCity);
_attackParam = new asd.TextObject2D();
_attackParam.Font = Singleton.GetLargeFont();
_attackParam.Text = "戦闘力:10000";
_attackParam.Position = new asd.Vector2DF(700, 650);
layer.AddObject(_attackParam);
_deffenceParam = new asd.TextObject2D();
_deffenceParam.Font = Singleton.GetLargeFont();
_deffenceParam.Text = "戦闘力:8000";
_deffenceParam.Position = new asd.Vector2DF(700, 150);
layer.AddObject(_deffenceParam);
_image_gu_attack = new asd.TextureObject2D();
_image_gu_attack.Texture = Singleton.GetImageGu();
_image_gu_attack.Position = new asd.Vector2DF(300, 500);
layer.AddObject(_image_gu_attack);
_image_choki_attack = new asd.TextureObject2D();
_image_choki_attack.Texture = Singleton.GetImageChoki();
_image_choki_attack.Position = new asd.Vector2DF(450, 500);
layer.AddObject(_image_choki_attack);
_image_par_attack = new asd.TextureObject2D();
_image_par_attack.Texture = Singleton.GetImagePar();
_image_par_attack.Position = new asd.Vector2DF(600, 500);
layer.AddObject(_image_par_attack);
_image_gu_deffence = new asd.TextureObject2D();
_image_gu_deffence.Texture = Singleton.GetImageGu();
_image_gu_deffence.Position = new asd.Vector2DF(300, 250);
layer.AddObject(_image_gu_deffence);
_image_choki_deffence = new asd.TextureObject2D();
_image_choki_deffence.Texture = Singleton.GetImageChoki();
_image_choki_deffence.Position = new asd.Vector2DF(450, 250);
layer.AddObject(_image_choki_deffence);
_image_par_deffence = new asd.TextureObject2D();
_image_par_deffence.Texture = Singleton.GetImagePar();
_image_par_deffence.Position = new asd.Vector2DF(600, 250);
layer.AddObject(_image_par_deffence);
}
protected override void OnUpdated()
{
}
}

シンプルだけどまぁいいでしょう。
グー・チョキ・パーは絵文字が使えないっぽいので、絵文字を拡大してスクリーンショットで画像を作成しています。
次回は実際にシーンの切り替えをやってみます。
例えば、長時間パソコン作業をしていると、耳鳴りがしたり、頭のあたりが押さえつけられるような感じがしたり、気分が悪くなったりすることはないだろうか?
まさしく自分がそうで。
特に最近症状がひどい。
また老眼が進んでしまったのかと。
いや、老眼とも関係してくるんですけど。
調べてみると、VDT症候群という病気がありまして、
直接の原因は眼精疲労。
治療法も予防策しかなくて、
今、スマホのタイマーを、1時間のタイマーと10分のタイマーをセットしてまして、
1時間のタイマーでパソコン使用後に、10分のタイマーで休憩する、というやり方を試しています。
休憩中はパソコンの画面を一切見ない。
さらに言うと、目を休ませる方法としては、
やっぱり、パソコン作業ができないと、オイラ、何もできないので、
きついっす。
でも、老化はどうやっても回復することはできないので、
今後はこの老化とどうやって付き合っていくかを考えなくちゃ行けません。
今、最善の方法を模索中です。
マジきついっす。