【プロジェクトセカイ】しばらくプレイし続けて思ったこと。

どこか行きたい。

なんとかmasterも普通にクリアできるレベルになりました。

EXもフルコンできた曲増えてきたし。

いきなりこんな譜面出てきたときは、確実に初心者を殺しに来てると思いました。

難しそうで、慣れちゃえば、意外と簡単に行けるもんすよ。

指をクロスしなくちゃいけないけど。

親指じゃ厳しいかもしれない。

そして、とにかく最初はデッキの強化に努めるしかない。

スコアランクがA以上になればレアアイテム獲得できる確率が高くなる。

それまでは、ありったけのリソースを使ってデッキを強化するしかない。

ベテランルームに入れることができれば、また変わってくるかもしれない(←まだ入れない)

ライブボーナスの使用量を調整できるのは良いですね。

ライブボーナス残っていても、消費しないでプレイすることも可能。

練習し放題。

メルト選曲すると切断されがち。

【ラズパイ】【カメラ】Webからカメラの画像を保存する。

前回はカメラのプレビュー画面をWebに表示させましたが、

今回はWebからシャッターボタンを設置して、カメラの画像を保存させます。

すでにPOSTリクエストを処理する方法も知っていますし、カメラの画像を保存する方法も知っているので、これらを組み合わせればできるはずです。

まずはサーバ(ラズパイ)の処理。


    def do_POST(self):
        content_len = int(self.headers.get('content-length'))
        requestBody = json.loads(self.rfile.read(content_len).decode('utf-8'))

        if requestBody['contents']['command'] == 1:
            _, img = cap.read()
            dt_now = datetime.datetime.now()
            filename = dt_now.strftime('%Y%m%d_%H%M%S')+".jpg"
            cv2.imwrite(filename, img)

            response = {
                'status' : 200,
                'path': "http://pi4.local:8000/" + filename
            }
        else:
            response = {
                'status' : 200
            }

        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        responseBody = json.dumps(response)

        self.wfile.write(responseBody.encode('utf-8'))

POST処理を追加しました。

カメラの画像をファイルに保存し、そのファイルパスをレスポンスで返すようなイメージです。

次はWeb側。

<!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="" /><br />
      <button @click="onShutter">Shutter</button><br />
      <a id="picture" href="" target="_blank">{{ path }}</a>
  </div>

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

ボタンとリンクを追加しました。

ボタンをクリックすると、onShutter処理が実行され、ラズパイ側にPOSTリクエストを送信します。

そのレスポンスから画像のファイルパスを取得し、リンクに反映させます。

同じ仕組みで動画の撮影もできそう。

次回やります。

【ダイエット支援】【入力履歴機能】入力履歴にデータを記入

ここもサクッと作成できると思う。

namespace App\Repository;

use App\Model\EatingHistoryItem;

class EatingManagementRepository
{
    private $templateParamNames = ['item', 'protein', 'liqid', 'carbo', 'calorie'];

    /**
     * ヒストリにデータを1件追加する
     */
    public function addHistory($param, $user)
    {
        $model = new EatingHistoryItem();
        foreach($this->templateParamNames as $name)
        {
            $model->$name = $param[$name];
        }
        $model->save();

        $this->attachToUser($model, $user);
    }
class ApiController extends Controller
{
    /**
     * データを1件登録する
     */
    public function add(Request $request)
    {
        $paramNames = $this->eatingManagement->getParam();

        $param = [];
        foreach($paramNames as $name) {
            $param[$name] = $request->contents[$name];
        }

        $this->eatingManagement->add($param, Auth::user(), $request->contents['timezone']);
        $this->eatingManagement->addHistory($param, Auth::user());
        
        return response()->json();
    }

入力したデータをそのまま履歴にも記入する、という処理ですな。

ここまではサクッとできたけど、次回からはかなりヘビーになると思う。

【ぼっち】いろはにほへと白石店

1人でもGoToイートが利用できることに重点を置いています。

居酒屋チェーン店ですが、LINEのクーポンを使えば、飲み放題が安くなります。

中トロの刺身が期間限定メニューで500円。

これでも刺身では一番安いです。

牛串。

間に挟まっているのはニンニクでした。

いや、美味しかった。

【COCOS2D-X】背景画像を設置。

画像はWeb検索して、見つけたフリー素材を使用しました。

で、これ多分、普通に表示するだけだと、画面からはみ出してしまうので。

これを上手く画面に収まるようにしたい。

見た感じ、画像の高さがはみ出ているので、高さの表示を画像に合うように拡大率を計算して、画像を縮小させたいと思います。

    auto sprite = Sprite::create("ID003_Western-Castle_noon.jpg");
    if (sprite == nullptr)
    {
        problemLoading("'ID003_Western-Castle_noon.jpg'");
    }
    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);
    }
    auto scaleRate = visibleSize.height / sprite->getContentSize().height;
    sprite->setScale(scaleRate);

    auto str = String();
    str.appendWithFormat("width %f height %f", sprite->getContentSize().width, sprite->getContentSize().height);
    label->setString(str.getCString());

この画像の範囲をベースにして、画面を作っていきましょうか。

あ、画面をタップしたときにエフェクトかかるようにしたいなぁ。

次回やります。

【目の疲れ対策】部屋の中の明るさも重要だと言うこと

明るければ良いってもんじゃ無いんだね。

オイラが使用しているNEC製のLEDシーリングライトはリモコンで部屋の明るさを4段階に調整できるんです。

今までは、ずっと一番明るい状態で使用していたんですが、

こないだ、少し明るさを暗くしてパソコン作業をしていたところ、いつもより目の疲れが無かったんですよね。

それで、部屋の明るさをいろいろ試してみた結果、以下のことが分かりました。

  • パソコン部屋の窓はカーテン締め切り
  • 午前は一番くらい状態にする
  • 午後は少し明るいくらいにする
  • 夜はディスプレイを暖色にし、部屋も暗めにする

ディスプレイの画面を暖色にするには、f.luxというフリーソフトを使用しています。

https://justgetflux.com

これを常駐させて、起床時間や入眠時間を設定すれば、それに合わせて、例えば、寝る前の時間には暖色に変更する、といった設定ができるようになります。

あと、スマホの画面も、夜は暖色系にしてますし、夜は画面の明るさを暗めにしています。

そのようにしてからは、少し寝付きが良くなったような気がしています。

皆さんも生活スタイルに合わせて部屋の明るさを調節してみるのも良いかもしれないよ。

【クラフトピア】小麦無限栽培・収穫機構

まだ動作は不安定だけど、とりあえず機能したので。

画面では2×2のエリアに小麦畑を設置し、中央にスプリンクラーを設置します。

この状態で小麦を刈り取ると、自動的に水を撒いて、小麦が成長、再び刈り取ることができます。

この刈り取った小麦を、チェストにアブソーバーを取り付けると、アブソーバーが小麦を吸い込んでチェストに格納してくれます。

あとは自動で刈り取る機構ですが、回転のこぎりを使用します。

ただ、壁を取り付けないと、勝手に変な方向に進んでしまうため、壁で囲っておく必要があります。

今回は壁が破壊されないようにトタンの壁を使用しましたが、他の壁ではどうなんでしょうかね?

これが意外なほど機能して、小麦が生長したところから回転のこぎりが刈り取ってくれるんです。

隣で農地を作成し、他の作物を栽培しながら過ごしていると、小麦がいつの間にか溜まっている、という寸法です。

もしかしたらスプリンクラーの設置位置を増やしたり、位置を調整すれば、アブソーバーの位置を調整すれば、もっと広くできるかもしれません。

ただ、チェストを回収すると、アブソーバーが消えるの、なんとかしてくれませんか?

まぁアブソーバー自体がテスト中だからね・・・

もうちょっと研究してみます。

【テクテクライフ】さっぽろ羊ヶ丘展望台

歩いて行ける距離だと思ったので、歩いて行きました。

しんどかった。

みなさんはバスでの移動をオススメします。

バスで行く場合は地下鉄福住駅から直通のバスがあります。

クラーク像、けっこうかっこいいね。

放牧されていた羊。

近くに行くと思った以上に鼻息が荒いです。

フンフンいっているのが聞こえます。

レストランではジンギスカン食べ飲み放題ができます。

1人4100円。

比較的お手頃なお値段ではないでしょうか。

【ラズパイ】【カメラ】プレビュー画面をラズパイから取得・表示(修正)

この記事のソースが余りにも冗長すぎるので、書き換えました。

こんな感じです。

CONTENT_TYPE = {'.html': 'text/html; charset=utf-8', '.txt': 'text/plain; charset=utf-8', '.js': 'text/javascript', '.json': 'application/json',
        '.jpeg': 'image/jpeg', '.jpg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif',
        '.css':'text/css'}



    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == '/Streaming':
            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)
        elif parsed.path.endswith('/'):
            self.send_response(HTTPStatus.OK)
            with open('index.html',mode='br') as f:
                data = f.read()
            self.send_header("Content-type", "text/html; charset=utf-8")
            self.end_headers()
            self.wfile.write(bytes(data))
        else:
            self.send_response(HTTPStatus.OK)
            filepath = '.' + parsed.path
            with open(filepath, mode='br') as f:
                data = f.read()
            self.send_header("Content-type", CONTENT_TYPE[pathlib.Path(filepath).suffix])
            self.end_headers()
            self.wfile.write(bytes(data))

まず、URLが”/”の場合はindex.htmlを返します。

そして、URLが”/Streaming”の場合はカメラの映像をbase64で返します。

それ以外の場合(今回で言うと、jsファイル達)、URLで指定されたファイル名と同じファイルを返します。

ただ、その場合、content-typeを正しいものにしないとブラウザが正しく動いてくれないので、ファイル拡張子に対応する適切なcontent-typeを設定するようにしています。

それを対応づけているのがCONTENT_TYPEです。

こうすることで、今後jsファイル以外のものにも対応出来ます。

一般的なHTTPサーバに比べれば不十分ですが、今回目指しているのはそれではないので、こんなもんで十分でしょう。

ソースはgitHubに公開しました。

https://github.com/takishita2nd/RemoteCamera

【プロジェクトセカイ】一応全曲プレイ一巡して思ったこと

自分は一歌推しです。

一応、今実装されている曲のEXまでの譜面を一通りプレイ終わりました。

今はほぼ毎日新曲が追加実装されているのですが。

ストーリーはなかなか精神えぐってきます。精神疾患者には少々辛い。

楽曲レベルは、ほぼガルパと同じ基準だと思って問題無いでしょう。

マスタークラスになると平気で難易度30以上が出てきますが、おそらくガルパの六兆年(レベル29)より難しいと思います。

クリアできる気がしません。

ライブのリトライ機能はなかなか神仕様ですね。

プレイ中にリトライすると、直接、曲の開始に戻ることができるだけでも嬉しいのですが、

ライブポイント(ブースト)はリザルト画面で消費されるので、リトライしてもリタイヤしてもポイントは減りません。

クリアできるまで何度でも挑戦できます。できるものなら。

ノーツのアイコンが横棒であるためか、他のリズムゲームより目が疲れる気がします。

スキンのカスタマイズとかできれば良いのですが。

老眼には少々きついかもしれません。

バーチャルライブもなかなか良いです。

満員で入れないときはブチ切れそうになりますが。

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