【ぼっち】餃子×酒×肴 大衆酒場036(ゼロサンロク)

久しぶりの新店舗開拓。

いや、GoToイート利用したかったけど、1人で予約取れる店少ないのよ。

もっとぼっちに優しい世界になってほしい。

看板メニューは餃子。

タレは各種揃っておりますが、餃子自体に味が付いているので、まずは何もつけずにそのまま頂いて、残りは自分のお好きなように調合して頂くと良いと思います。

この餃子が本当に美味しくて、ビールが進む!

旬の鰹のたたきも頂きました。

いやー旨かった!

比較的早い時間からオープンしているのも嬉しいですね。

15:00開始はギリギリディナータイムなので。

今回は非常に満足でした。

【北海道大戦】じゃんけんアイコンをクラス化

じゃんけんアイコンを使いやすい様にクラス化させます。

    class BattleIcon
    {
        public enum Icon
        {
            Gu,
            Choki,
            Par
        }

        public enum Position
        {
            Attack,
            Deffence
        }

        private asd.TextureObject2D _image = null;
        private Icon _icon;
        private Position _position;
        private int _x;
        private int _y;
        private int width = 80;
        private int height = 80;

        public BattleIcon(Icon icon, Position pos)
        {
            _icon = icon;
            _position = pos;
            _image = new asd.TextureObject2D();
            if (pos == Position.Attack)
            {
                _y = 500;
                switch (icon)
                {
                    case Icon.Gu:
                        _x = 300;
                        _image.Texture = Singleton.ImageGu;
                        break;
                    case Icon.Choki:
                        _x = 450;
                        _image.Texture = Singleton.ImageChoki;
                        break;
                    case Icon.Par:
                        _x = 600;
                        _image.Texture = Singleton.ImagePar;
                        break;
                }
                _image.Position = new asd.Vector2DF(_x, _y);
            }
            else
            {
                _y = 250;
                switch (icon)
                {
                    case Icon.Gu:
                        _x = 300;
                        _image.Texture = Singleton.ImageGu;
                        break;
                    case Icon.Choki:
                        _x = 450;
                        _image.Texture = Singleton.ImageChoki;
                        break;
                    case Icon.Par:
                        _x = 600;
                        _image.Texture = Singleton.ImagePar;
                        break;
                }
                _image.Position = new asd.Vector2DF(_x, _y);
            }
        }

        public void AddLayer(asd.Layer2D layer)
        {
            layer.AddObject(_image);
        }

        public void Show()
        {
            switch (_icon)
            {
                case Icon.Gu:
                    _image.Texture = Singleton.ImageGu;
                    break;
                case Icon.Choki:
                    _image.Texture = Singleton.ImageChoki;
                    break;
                case Icon.Par:
                    _image.Texture = Singleton.ImagePar;
                    break;
            }
        }

        public void Hide()
        {
            _image.Texture = null;
        }

        public void OnMouse(asd.Vector2DF pos)
        {
            if (IsOnMouse(pos))
            {
                switch (_icon)
                {
                    case Icon.Gu:
                        _image.Texture = Singleton.ImageGu2;
                        break;
                    case Icon.Choki:
                        _image.Texture = Singleton.ImageChoki2;
                        break;
                    case Icon.Par:
                        _image.Texture = Singleton.ImagePar2;
                        break;
                }
            }
            else
            {
                switch (_icon)
                {
                    case Icon.Gu:
                        _image.Texture = Singleton.ImageGu;
                        break;
                    case Icon.Choki:
                        _image.Texture = Singleton.ImageChoki;
                        break;
                    case Icon.Par:
                        _image.Texture = Singleton.ImagePar;
                        break;
                }
            }
        }

        public bool IsOnMouse(asd.Vector2DF pos)
        {
            if (pos.X > _x && pos.X < width + _x
                && pos.Y > _y && pos.Y < height + _y)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

とりあえず、使いそうなメソッドをいくつか実装しました。

    class BattleScene : asd.Scene
    {
        protected override void OnUpdated()
        {
            asd.Vector2DF pos = asd.Engine.Mouse.Position;

            switch (_status)
            {
                case GameStatus.SelectDeffenceAction:
                    cycleProcessSelectDeffenceAction(pos);
                    break;
                case GameStatus.SelectAttackAction:
                    break;
                case GameStatus.ShowActionResult:
                    break;
            }
            if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
            {
                switch (_status)
                {
                    case GameStatus.SelectDeffenceAction:
                        break;
                    case GameStatus.SelectAttackAction:
                        break;
                    case GameStatus.ShowActionResult:
                        break;
                }
            }
        }

        private void cycleProcessSelectDeffenceAction(asd.Vector2DF pos)
        {
            _image_gu_deffence.OnMouse(pos);
            _image_choki_deffence.OnMouse(pos);
            _image_par_deffence.OnMouse(pos);
        }

とりあえず、こんなところか。

マウスカーソルを合わせることで色を変えるようにしました。

うん、今日もがんばった。

Pixel5とPixel4a(5G)が発表されましたね。

思ったより早かったね。

販売開始は10月15日、価格はPixel4(5G)が60,500円、Pixel5が74,800円です。

Pixel4a(5G)で何が変わったか

まず、当然のことながら、プロセッサーが5G対応のSnapdragon 765Gになりました。

あとは、背面に広角カメラがついて2眼になっています。

Pixel5で何が変わったか

プロセッサーはPixel4a(5G)と同じSnapdragon 765Gですね。

Pixel4にあったMotion Senseが無くなった模様です。

そのおかげで、Pixel4よりも安くなりました。

このシリーズ、毎回なにかしら尖った機能が搭載されているのですが、

おそらく、今回はバッテリーシェアがそれに当たると思います。

Pixel5から他の端末に無線で充電できる機能です。

そのためか、Pixel4の弱点だったバッテリー容量も大幅に強化されています。

iPhoneより先に5Gに対応したことで大きくアドバンテージを取ったことになりますが、

そうなると、次の新型iPhoneの発表も期待されますね。

まぁ、オイラはPixel4a買ったばかりだから。

【ラズパイ】リモートでカメラのプレビュー表示

いや、今回は結構ハマった。

これが半日頑張った成果だ。

まずはラズパイ側。

import base64
import cv2
import json
import os
import sys
import urllib.parse
import time
import threading

from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
from http import HTTPStatus

PORT = 8000

cap = cv2.VideoCapture(0)

def __main__():
    thread = threading.Thread(target=httpServe)
    thread.start()
    
    try:
        while cap.isOpened():
            time.sleep(1)
    except KeyboardInterrupt:
        return

def httpServe():
    handler = StubHttpRequestHandler
    httpd = HTTPServer(('',PORT),handler)
    httpd.serve_forever()

class StubHttpRequestHandler(BaseHTTPRequestHandler):
    server_version = "HTTP Stub/0.1"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def do_GET(self):
        enc = sys.getfilesystemencoding()

        _, img = cap.read()
        resized_img = cv2.resize(img, (480, 320))
        _, encoded_img = cv2.imencode('.jpg', resized_img, [int(cv2.IMWRITE_JPEG_QUALITY), 30])
        dst_base64 = base64.b64encode(encoded_img).decode('utf-8')

        data = {
            'image': 'data:image/jpg;base64,' + dst_base64
        }

        encoded = json.dumps(data).encode()

        self.send_response(HTTPStatus.OK)
        self.send_header("Content-type", "text/html; charset=%s" % enc)
        self.send_header("Access-Control-Allow-Origin", "null")
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()

        self.wfile.write(encoded)     

__main__()

そしてクライアント側。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="vue.min.js"></script>
  <script src="jquery-3.5.1.slim.min.js"></script>
</head>
<body>
  <div id="app">
      <image id="camera" src="" />
  </div>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        timer: null,
      },
      created: function() {
        self = this;
        this.timer = setInterval(function() {self.onLoad()}, 50)
      },
      methods: {
        onLoad: function() {
            axios.get('http://pi4.local:8000').then(function(response){
                $("#camera").attr('src', response.data.image);
            }).catch(function(error){
            });
        }
      }
    })
  </script>
</body>
</html>

まず、サーバ側の説明。

今回は、すでに使った実績のある、HTTPで通信を行います。

もっと下位層のプロトコルを使うと、もっと効率よくデータの送信ができるのですが、その分、扱いも難しくなります。

HTTPはTCP/UDPよりも、データのやりとりが多くなるので、少しモッサリ感がありますが、扱いが簡単になります。

実際、今回はブラウザで表示させているので!

カメラで撮影し、それを画像に落とすところまでは今まで通りですが、

今回はHTTPで送信するために、Base64に変換し、Jsonに載せて送信します。

Base64の頭にある「data:image/jpg;base64」というのは、このデータはJpegですよ、ということを示す文字列で、これがないと、受け手側は何のデータか判断できません。

「Access-Control-Allow-Origin」はCORS対策です。

例えばクロームなのでは、同じドメインでなければ画像が開けない、という制約がありまして、それを判断しているのが、リクエストヘッダーのOriginと、レスポンスヘッダーのAccess-Control-Allow-Origin。

この二つの値が一致しないと画像はエラーで表示されなくなります。(ただしブラウザによる)

今回はChrome側のOriginがnullだったので、それに合わせました。

FireFoxとかだったらまた話が変わってくるかもしれない。

続いて、クライアント側。

サクッと作成するために、Vue.jsを使用しました。

使用しているライブラリはaxios、jQueryです。

Laravelと同じような構成にしました。

画面には<div id=”app”>と<image id=”camera”>のみです。

やっていることは単純で、画面が作成されたらcreatedメソッドが実行されて、onLoad()を周期的にコールするようにしています。

50という数字を小さくすればヌルヌルになりますし(ただしラズパイ側の負荷が大きくなる)、大きくすればカクカクになります。

今回はラズパイにクーラーつけているから大丈夫だけど、ラズパイZeroでこの負荷はやばいと思う。

そして、レスポンスの中のBase64をimageのsrcに入れれば画像が表示されます。

これを早いサイクルで実行・画像更新することで、動画のように見せることが出来ます。

今回はWebカメラみたいに仕上がりましたが、HTTPが使えるならばクライアントは何だってできます!

openGLって今更やる必要があるのかって思った。

openTKでハマってしまったのを前に記事で書いたのですが、

本気でやるなら書籍を買うしかないと思って探しては見た物の、あまりピンとこないというか、アレだったので、

そんなときに見つけたのがこのページ。

細かい所は上のページを読んで貰うとして、

結論から言うと、

openGLの理論を学ぶとするのはいいけれど、

単に3Dアプリを作りたいと言うだけならば、既存のプラットフォームを使った方が早い。

例えばUnityとか。

openGLで悩むより、Unityの勉強を始めた方がいい。

そういえば、Unityの書籍を使った勉強、途中で止まっていたけど、

再開してみるかな。

【ダイエット支援】もっと具体的な設計をしなくちゃいけなくて

たぶん、前回の記事の内容だけではコーディングはまだできなくって、

もっと具体的に動作の仕組みを考えなくちゃいけないと思いまして。

UIの動き

  • 文字を入力すると、データベースから入力候補を取得し、表示する
  • 入力した内容が入力候補と一致すると、その栄養素値が自動で入力される
  • 入力を空にすると、入力候補も空にする

テキスト窓に入力したかどうかはVue.jsではv-on:changeで処理を起動することができるみたいなので、これを使用します。

データベース

基本的には入力済みの食品・栄養素の情報(テンプレート)からデータを抽出して候補がある物から選択するという形にしたいと思います。

ただ、そう言った食品や栄養素の情報を全部用意するのは大変なので、ユーザーが入力した情報を記憶しておいて(ヒストリ)、管理者が正式データとして登録する、という仕組みにしたいと思います。

なので、管理者画面が必要になりますね。

データベースはテンプレートとヒストリの二つ用意しておきたいと思います。

ここらへん、本当はもっと詰めなくちゃいけない所ですが、今回はあとでどうにでもできるように、リスクが少ない方法を選択したいと思います。

あとでデータベース構成を変えるとなるとコードの修正も大変なので。

なので、今後の作業はこんな感じです。

  • データベースの構築
  • テンプレートからデータを入力する処理
  • ユーザーが入力したデータをヒストリに保存する処理
  • 管理者がヒストリからテンプレートに移す処理

よし、これでいきましょう。

【COCOS2D-X】タッチ処理を使用する。

さて、今回はタッチ処理を試してみたいと思います。

タッチ処理はスマホ専用の処理なので、Windowsでは動かないので、スマホで動作確認します。

で、タッチした座標を画面に表示させたいと思います。

    auto listener1 = EventListenerTouchOneByOne::create();
    listener1->onTouchBegan = [this](Touch* touch, Event* event)->bool
    {
        auto str = String();
        str.appendWithFormat("Touch (%f %f)", touch->getLocation().x, touch->getLocation().y);
        label->setString(str.getCString());
        return true;
    };
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

タッチ処理はイベントリスナーを使用するのですが、

EventListenerTouchOneByOneとEventListenerTouchAllAtOnceがあるのですが、前者はシングルタッチ、後者はマルチタッチのようです。

使用するハンドラ名が若干違うようです。

今回はシングルタッチを使用します。

で、今回初めてC++のラムダ式を使ったのですが、

[]はキャプチャといって、ラムダ式内に持っていく変数を指定するみたいなんですよね。

座標を表示するラベルなんですが、

ローカルにLabelオブジェクトを定義して[&label]って書いてもエラーで動かなかったので、

今回はサンプルコードに従って、labelはprivate変数に定義し、キャプチャには[this]とします。

こうすることでprivateのlabelオブジェクトを使用することができました。

あとは、引数touchからx,y座標をラベルに表示させる。

スマホだからか、画像のクリッピング処理がWindowsとは動きが違ってたんですよね。

ちょっとここは要調査ですわ。

もしかしたら、Windows用とスマホ用に画像を2種類用意しないといけないかもしれん。

イマイチ仕事する気が起きないのです。

まぁ、ちょっと前にも医者から仕事したらどうだとは言われたことがあるんですが。

仕事やめるまでは仕事一生懸命やっていたんですが、

次第に体調が悪化していって、

仕事を休むことが多くなって、

結果的に退職したのですが、

その後も加齢や老眼や肩こりとか首コリに悩まされて、

なんか、そのときに心がポッキリ折れてしまったような感じがして、

ちょうど同じ時期に借金も全額返済したし、

働かなくても障害年金もらえているし、

お金は欲しいけど、今は十分に暮らしていけるし、

養う家族もいないし、

まぁ、要するに、今頑張って仕事する理由が無い。

仕事をするためのモチベーションが無い。

そのままで良いのか、と言われると、良くはないのですが、

こればっかりは仕事したくなるのを待つしか無いのかな、

とか思ってみたり。

とりあえず今は趣味のプログラミングを続けてスキルを磨いておく。

ぐらいしかできないかなー

それとも時短のバイトでもやってみる?

クラウドソージングに登録してみたけど、案件見る限り、高スキルのものばっかりだし。

自分に見合った案件が無い。

そんな状況ですわ。

【北海道大戦】バトルシーンへパラメータを渡す。

前回までの状況はこちら。

バトルシーンを作成するために、バトルシーンで使用するパラメータを設定します。

シーンはその都度作成しなくちゃいけないので、コンストラクタで渡すのが一番良いでしょう。

        public enum Player
        {
            Attack,
            Deffence
        }

        public BattleScene(City attack, City deffence, Player player)
        {
            _attack = attack;
            _attackPower = attack.Population;
            _deffence = deffence;
            _deffencePower = deffence.Population;
            _player = player;
            _status = GameStatus.SelectDeffenceAction;
        }

playerというパラメータは、プレイヤーが攻撃側か防御側かを示すパラメータです。

あれこれ悩んだ結果、これが一番簡単だろうと。

これを画面に表示させます。

            var attackCityLabel = new asd.TextObject2D();
            attackCityLabel.Font = Singleton.LargeFont;
            attackCityLabel.Text = _attack.Name;
            attackCityLabel.Position = new asd.Vector2DF(450, 150);
            layer.AddObject(attackCityLabel);

            var deffenceCityLabel = new asd.TextObject2D();
            deffenceCityLabel.Font = Singleton.LargeFont;
            deffenceCityLabel.Text = _deffence.Name;
            deffenceCityLabel.Position = new asd.Vector2DF(450, 650);
            layer.AddObject(deffenceCityLabel);

            _attackParam = new asd.TextObject2D();
            _attackParam.Font = Singleton.LargeFont;
            _attackParam.Text = "戦闘力:" + _attack.Population;
            _attackParam.Position = new asd.Vector2DF(700, 650);
            layer.AddObject(_attackParam);

            _deffenceParam = new asd.TextObject2D();
            _deffenceParam.Font = Singleton.LargeFont;
            _deffenceParam.Text = "戦闘力:" + _deffence.Population;
            _deffenceParam.Position = new asd.Vector2DF(700, 150);
            layer.AddObject(_deffenceParam);

さらに、

このフローからバトルシーンの状態を抽出。

        enum GameStatus {
            SelectDeffenceAction,
            SelectAttackAction,
            ShowActionResult
        }

これを実装。

        protected override void OnUpdated()
        {
            switch (_status)
            {
                case GameStatus.SelectDeffenceAction:
                    break;
                case GameStatus.SelectAttackAction:
                    break;
                case GameStatus.ShowActionResult:
                    break;
            }
            if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
            {
                switch (_status)
                {
                    case GameStatus.SelectDeffenceAction:
                        break;
                    case GameStatus.SelectAttackAction:
                        break;
                    case GameStatus.ShowActionResult:
                        break;
                }
            }
        }

あとは、各状態について実装していけば良いのですな。

とりあえず今回はここまでにしておこう。

【クラフトピア】鉱石無限生産機構

やっぱりどの世界でも鉄は大量に必要。

なので、鉄無限生産機構です。

まずは平べったい鉱石がある場所を見つけます。

そこに掘削機を設置します。

そうすると、鉄鉱石を吐き出してくれるので、これをキャッチする感じでコンベアーを設置します。

吐き出す方向は常に同じみたい。

それを自動炉に流し込みます。

自動炉には操作できる箇所が二つあって、

一つは自動炉のチェスト、コンベアーで流し込まれたアイテムが入ります。

自分でアイテムを入れることもできます。

もう一つは生成するアイテムを設定するところ。

ここで設定したアイテムの材料がコンテナ内にあれば、アイテム(インゴット)を生成してくれます。

生成されたアイテムは後ろのコンベアーから流れてくるので、そこにコンテナを接続します。

これで鉄を自動的に掘削し、インゴットを精製してコンテナに入れてくれる装置が完成しました。

鉄無限生産機構の完成です。

この仕組みをもう一組作り、銀も無限生産機構化しました。

あとは、砂無限も欲しいな。

自分、ぼっちですが何か?