マスクしながらでも運動がしたい人はこれだね。

こちらのブログの情報を元に、実際に購入しました。

http://kamechari.blog.jp/archives/1077373761.html

上の写真はフェイスマスク。

自転車載りガチ勢が使用しているもので、本来は口の中に虫が入るのを防ぐためのもの何ですが、通気性がかなり良いので使用している人が多いみたいです。

でも、これだけだと、唇が布に付くのが嫌!という人も多いので、下の写真のアイテムも使用します。

下の写真はフェイスガード。

主にサバゲーの時に使用するものなのですが、口の鼻の周りの空間を確保してくれるので、フェイスマスクと併用して使用している自転車乗りも多いらしい。

つけて見るとこんな感じ。

まぁ、マスクより防御力は劣りますが、飛沫感染は防ぐことができますし、何より楽に呼吸することができます。

自転車は思った以上に運動量が多いし、呼吸も激しくなるので、実際に使用して、マスクよりも遙かに楽でした。

お値段もAmazonで2000円程度で買えますし、繰り返し使えますので、自転車で運動不足解消をしたいなら買って良いのでは無いでしょうか??

かめちゃりさん、情報ありがとうございます!

【C#】【ピクロス】【ALTSEED】解析パターンその2

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

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

https://github.com/takishita2nd/Picross

つぎはどう攻めていくかというと、ここに注目しましょう。

ここも塗れるのが確定していますよね。

ここを塗るための条件を確認しましょう。

マスクされていないマスを数え、連続したマスの数と、範囲の数が全て一致した場合、確定とする。

つまり、

マスクされていないマスが2個、1個、2個と並んでいて、これらが全て左の数字と一致するため、この開いているマスは全て塗ることができます。

これをコーディングします。

    // 解析パターンその2
    private void pattern2()
    {
        // Row
        pattern2Row();
        // Col
        pattern2Col();
    }
        private void pattern2Row()
        {
            int row = 0;
            foreach (var rowlist in rowNumbers)
            {
                if (rowlist.IsAnalyzed())
                {
                    row++;
                    continue;
                }

                // マスクされていない連続したマスを数える
                int col = 0;
                int count = 0;
                List<int> countList = new List<int>();
                while (col < colNumbers.Count)
                {
                    if (_bitmapData[row, col].IsMasked() == false)
                    {
                        count++;
                    }
                    else
                    {
                        if (count != 0)
                        {
                            countList.Add(count);
                            count = 0;
                        }
                    }
                    col++;
                    if(col == colNumbers.Count)
                    {
                        countList.Add(count);
                    }
                }
                // 数えた数字が全て一致すれば確定とする
                bool result = true;
                if (rowlist.AnalyzeDatas.Count != countList.Count)
                {
                    row++;
                    continue;
                }
                for (int i = 0; i < countList.Count; i++)
                {
                    if (rowlist.AnalyzeDatas[i].Value != countList[i])
                    {
                        result = false;
                    }
                }
                if (result)
                {
                    // 開いているところを塗る
                    col = 0;
                    while (col < colNumbers.Count)
                    {
                        if(_bitmapData[row, col].IsValid() == false)
                        {
                            _bitmapData[row, col].Paint();
                        }
                        col++;
                    }
                    rowlist.Analyzed();
                }
                row++;
            }
        }

        private void pattern2Col()
        {
            int col = 0;
            foreach (var collist in colNumbers)
            {
                if (collist.IsAnalyzed())
                {
                    col++;
                    continue;
                }

                // マスクされていない連続したマスを数える
                int row = 0;
                int count = 0;
                List<int> countList = new List<int>();
                while (row < rowNumbers.Count)
                {
                    if (_bitmapData[row, col].IsMasked() == false)
                    {
                        count++;
                    }
                    else
                    {
                        if (count != 0)
                        {
                            countList.Add(count);
                            count = 0;
                        }
                    }
                    row++;
                    if (row == rowNumbers.Count)
                    {
                        countList.Add(count);
                    }
                }
                // 数えた数字が全て一致すれば確定とする
                bool result = true;
                if (collist.AnalyzeDatas.Count != countList.Count)
                {
                    col++;
                    continue;
                }
                countList.Reverse();
                for (int i = 0; i < countList.Count; i++)
                {
                    if (collist.AnalyzeDatas[i].Value != countList[i])
                    {
                        result = false;
                    }
                }
                if (result)
                {
                    // 開いているところを塗る
                    row = 0;
                    while (row < rowNumbers.Count)
                    {
                        if (_bitmapData[row, col].IsValid() == false)
                        {
                            _bitmapData[row, col].Paint();
                        }
                        row++;
                    }
                    collist.Analyzed();
                }
                col++;
            }
        }

数える→数を確認する→塗るの順で処理しています。

少しデータの持ち方も変えています。

    private List<AnalyzeListData> rowNumbers;
    private List<AnalyzeListData> colNumbers;
    class AnalyzeListData
    {
        private bool _analyzed;
        public List<AnalyzeData> AnalyzeDatas;

        public AnalyzeListData()
        {
            _analyzed = false;
            AnalyzeDatas = new List<AnalyzeData>();
        }

        public bool IsAnalyzed()
        {
            return _analyzed;
        }

        public void Analyzed()
        {
            _analyzed = true;
        }
    class AnalyzeData
    {
        private bool _analyzed;
        public int Value { get; }

        public AnalyzeData(int value)
        {
            Value = value;
            _analyzed = false;
        }

        public bool IsAnalyzed()
        {
            return _analyzed;
        }

        public void Analyzed()
        {
            _analyzed = true;
        }

    }

どのデータを塗ったかどうかを確認できるようにしています。

実行結果はこうなりました。

うん、順調ですね。

【C#】【ピクロス】【ALTSEED】解析パターンその1

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

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

https://github.com/takishita2nd/Picross

さぁ、解析処理を作っていくぞ。

例題として、こちらの問題を用意しました。

データを入力。

まず、ピクロス解法の定石パターンとして、確実に塗れるところから塗っていくというもの。

この例題からすると、

この赤い部分は全て塗れるのは、すぐに分かりますよね。

さらに、

ここも塗れるのは分かりますでしょうか。

例えば、[1,4,3]と合った場合は、

■×■■■■×■■■

と10マスが確定しますよね?

これを公式化すると、

数字の合計+(数字の数ー1)=マスの数

※1+4+3+(3-1) = 10

となった場合、その列または行の塗れるマスは自動的に確定します。

これを実装します。

        // 解析パターンその1
        private void pattern1()
        {
            // Row
            pattern1Row();
            // Col
            pattern1Col();
        }

        /**
         * Rowに対して解析パターン1を適用
         */
        private void pattern1Row()
        {
            int row = 0;
            foreach (var rowlist in rowNumbers)
            {
                int total = 0;
                foreach (var v in rowlist)
                {
                    total += v;
                }
                total += rowlist.Count - 1;
                if (total == colNumbers.Count)
                {
                    // 塗れるマス確定
                    // リストを反転コピー
                    List<int> revRowList = new List<int>();
                    foreach (var v in rowlist)
                    {
                        revRowList.Add(v);
                    }
                    revRowList.Reverse();

                    int col = 0;
                    foreach (var v in revRowList)
                    {
                        int c;
                        for (c = 0; c < v; c++)
                        {
                            _bitmapData[row, col + c].Paint();
                        }
                        if(col + c < colNumbers.Count)
                        {
                            _bitmapData[row, col + c].Mask();
                            c++;
                        }
                        col += c;
                    }
                }
                row++;
            }
        }

        /**
         * Colに対して解析パターン1を適用
         */
        private void pattern1Col()
        {
            int col = 0;
            foreach (var collist in colNumbers)
            {
                int total = 0;
                foreach (var v in collist)
                {
                    total += v;
                }
                total += collist.Count - 1;
                if (total == colNumbers.Count)
                {
                    // 塗れるマス確定
                    // リストを反転コピー
                    List<int> revColList = new List<int>();
                    foreach (var v in collist)
                    {
                        revColList.Add(v);
                    }
                    revColList.Reverse();

                    int row = 0;
                    foreach (var v in revColList)
                    {
                        int r;
                        for (r = 0; r < v; r++)
                        {
                            _bitmapData[row + r, col].Paint();
                        }
                        if (row + r < rowNumbers.Count)
                        {
                            _bitmapData[row + r, col].Mask();
                            r++;
                        }
                        row += r;
                    }
                }
                col++;
            }
        }

列の数字データは右から順に並んでいるので、これを反転させる必要があります。

ただ、直接Reverse()を使用すると、インプットデータが壊れてしまうので、コピーを作成してからReverse()を使用します。

あとは、Listの先頭からピクロスのルールに従って塗っていきます。

実行結果はこうなりました。

解析がしやすくなるように、塗れないマスは×を表示するようにしました。

まぁ、ここまでは順調ですな。

【マインクラフト】Realmと自前サーバ、どっちが良いの?

みんなそんなにマイクラサーバを立てたいのか。

マインクラフトのサーバを自前で利用することのメリット。

それはハードウェアがあれば無料で運用することができる。

しかし、ハードルはいくつかありまして、

まず、サーバをどこに設置するか。

自宅にサーバを設置する場合、プレイヤーは同じLANの中からアクセスしなければならない。

自宅サーバを外部に開放する場合は、それなりの専門知識が必要だし、セキュリティリスクも発生します。

そこでVPSにサーバを設置するという方法もあります。

VPSを提供するサービスの中には、マインクラフト用テンプレートがあらかじめ用意されているものもあり、それを利用すれば、簡単にマインクラフトサーバを立ち上げることができます。

では、料金的にどうなのか?

Realmを使用する場合、統合版では10プレイヤー用が月470円、10プレイヤー用が月930円です。

Java版の場合は10プレイヤー用が月904円で提供されています。

VPSを使用する場合、Conohaだと月880円~で利用できます。

https://www.conoha.jp/vps/function/minecraft/

プレイヤーの制限はありませんが、利用プレイヤーが増えれば、それだけ要求されるスペックが高くなり、その分コストは高くなります。

これだけ見ると、VPSの方が遙かにコストが高いっすね。

サーバが重くなると、地形の描画に時間がかかったり、ゲームが少し前の状態に巻き戻ってしまう、などの動作異常が頻発します。

特にエリトラで飛行する場合は注意。

たぶん推奨スペックでもエリトラで地図作成する場合はかなりサーバに負荷がかかります。

と言うことで、まとめ。

自宅ネットワークでプレイ→自前サーバ

遠隔地から少人数でプレイ(10人まで)→Realm

大人数でプレイ(11人以上)→VPS

マニアックで物好きな人→VPS

サーバの運用が分からない人→Realm

一人でプレイする人→ローカルで良いんじゃない?

【C#】【ピクロス】【ALTSEED】解析結果をUIに反映させる

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

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

https://github.com/takishita2nd/Picross

実際に解析を行うクラスを作成していきます。

まずは解析中の状態を保持するクラスを定義します。

class BitmapData
{
    public int Row { get; }
    public int Col { get; }
    // 塗るで確定
    private bool _isPaint;
    // 塗らないで確定
    private bool _isFilter;

    public BitmapData(int row, int col)
    {
        Row = row;
        Col = col;
        _isPaint = false;
        _isFilter = false;
    }

    public bool IsPainted()
    {
        return _isPaint;
    }

    public bool IsFilted()
    {
        return _isFilter;
    }

    public bool IsValid()
    {
        if(_isPaint | _isFilter)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

多分、解析に必要なデータは、塗ったマスか、塗ることができないマスか、まだ確定していないマスか、の三つが必要になると思います。

なので、それらの状態を保持し返す事ができるメソッドを一通り用意してみました。

とりあえず、これでいいや。

必要になったら、その都度追加していく。

これを使用します。

class PicrossAnalyze
{
    List<List<int>> rowNumbers;
    List<List<int>> cowNumbers;
    BitmapData[,] _bitmapData;

    public PicrossAnalyze(List<List<NumberSquare>> rowNumberSquares, List<List<NumberSquare>> colNumberSquares)
    {
        _bitmapData = new BitmapData[rowNumberSquares.Count, colNumberSquares.Count];
        for(int r = 0; r < rowNumberSquares.Count; r++)
        {
            for(int c = 0; c < colNumberSquares.Count; c++)
            {
                _bitmapData[r, c] = new BitmapData(r, c);
            }
        }

        rowNumbers = new List<List<int>>();
        foreach(var rowList in rowNumberSquares)
        {
            List<int> list = new List<int>();
            foreach(var s in rowList)
            {
                list.Add(s.GetValue());
            }
            rowNumbers.Add(list);
        }

        cowNumbers = new List<List<int>>();
        foreach (var colList in colNumberSquares)
        {
            List<int> list = new List<int>();
            foreach (var s in colList)
            {
                list.Add(s.GetValue());
            }
            cowNumbers.Add(list);
        }
    }

    public bool[,] Run()
    {
        // モック
        bool[,] ret = new bool[10, 10] {
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true },
            {true, false, true, false, true, true, false, true, false, true }
        };

        return ret;
    }
}

コンストラクタで必要なデータを渡し、必要なデータを取り出します。

とりあえず、この処理はここまで。

先に解析結果をUIに反映させる処理を書きましょう。

表示するデータは、とりあえず固定値を返すモックにしておきます。

これをUI側に実装します。

        anlyzeButton.SetAction(() =>
        {
            PicrossAnalyze picross = new PicrossAnalyze(rowNumberSquare, colNumberSquare);
            bool[,] ret = picross.Run();
            for(int row = 0; row < rowNumberSquare.Count; row++)
            {
                for(int col = 0; col < colNumberSquare.Count; col++)
                {
                    if(ret[row,col] == true)
                    {
                        drawSquares[row][col].Paint();
                    }
                }
            }
        });

実行結果はこんな感じになります。

解析状況を可視化しなければ、解析処理を作成するのに困るので、先にこちらの処理を作成した、と言うわけです。

次回は実際に問題データを入力して、簡単なロジックから作成していきましょう。

新型コロナウイルス感染症緊急経済対策の特別定額給付金申請(札幌市の場合)

札幌市のHPが更新され、5月18日から申請の送付を行うとのことです。

https://www.city.sapporo.jp/2019n-cov/hokenfukushi/teigakukyuhu.html

オンライン申請は5月18日頃に受け付けが開始出来る見込み、とのことです。

その前に。

上にいろいろと注意事項が書いてありますが、

オンライン申請するにはいろいろと条件があるようで、

ざっくり言うと、

e-Taxできる状態ならオンラインで受け付けるよ

ということです。

上で書いてる、電子証明書とは、e-Taxで使用するもので、マイナンバーカード発行と同時に申請した(様な気がする)ものです。

これが有効期限内である必要があります。

有効期限が切れていた場合は、区役所に行って更新する必要があります。

手続き自体は窓口で暗証番号を入力して当日完了しますが、混雑が予想されるため、大人しく郵送にした方が良いと思います。

あ、有効期限が切れた場合は、更新のお手紙が届くと思うよ。

暗証番号忘れた人は論外。

PCで申請する場合はカードリーダーが必要になります。

カードリーダーが無い場合は、NFCに対応したスマートフォン(iPhone等)があればスマホで申請できます。

最近のスマホだったら大抵対応しているよ。

ここまで読んで、理解できない人は、郵送で手続きしてください。

【バンドリ】【ガルパ】真の効率曲

たぶん、多くのバンドリーマーは、ガルパで「効率曲」というと、「天下トーイツAtoZ」が連想されると思う。

いや、間違ってはいないのだが。

答えはこちらのリンク先にありまして、

https://appmedia.jp/bang_dream/730842

このページの真ん中当たりに、効率曲ランキングみたいなものがリストで掲載されています。

このページ、ブックマークに入れておくと便利よ。

新曲が追加されると、随時更新されるので。

効率曲というのは、まぁ、一言で言うと、1回のライブで高得点が狙える曲のこと。

1回のライブで高得点が出る、ということは、周回すれば、イベントポイントをたくさん稼げる、と言うことです。

しかも、高得点が出るということは、ハイスコアレーティングの更新にも役に立ちます。

ただ、ライブ中に死亡してしまうのは論外として、ミスが多くなってしまうと効率曲を周回する意味が無くなってしまいます。

協力ライブで、自分がクリアできても、他プレイヤーが死んでしまっては意味が無いので。

なので、比較的簡単な、楽曲レベルが低い曲の方が良い。

効率曲のリストを見てみると、上位の方に高難易度の曲が集中していると思います。

なので、オイラは、これらを考慮した上で、簡単かつハイスコアが狙える真の効率曲の調べてみました。

実際にプレイしてハイスコアレーティング算出しています。

Poppin’Party

  • Jumpin'(レベル26)
  • B.O.F(レベル25)
  • Home Street(レベル25)

Afterglow

  • アスノヨゾラ哨戒班(レベル26)
  • 瞬間センチメンタル(レベル26)
  • 午後の待ち合わせ(レベル26)

PastelPalettes

  • 天下トーイツAtoZ☆(SP レベル25)
  • ふわふわ時間(レベル25)
  • 春擬き(レベル25)

Roselia

  • Hacking to the Gate(レベル25)
  • シャルル(SP レベル25)
  • 残酷な天使のテーゼ(レベル25)

ハロー、ハッピーワールド!

  • 太陽曰く燃えよカオス(レベル26)
  • コレカラ(レベル25)
  • ゴーカ!ごーかい!?ファントムシーフ!(SP レベル25)

Morfonica

  • chAngE(レベル26)
  • ブルームブルーム(レベル26)
  • 秒針を噛む(レベル26)

RAISE A SUILEN

  • ヒトリノ夜(レベル26)
  • EXPOSE ‘Burn out!!!'(レベル26)
  • UNSTOPPABLE(レベル26)

その他

  • す、好きなんかじゃない!(レベル25)
  • 大盛り一丁!ガルパ☆ピコ(レベル26)
  • クインティブル☆すまいる(レベル25)

このあたりなら、ハイレベルプレイヤーでなくてもハイスコアが狙えますし、効率よく周回できると思います。

ただし、協力ライブで同じ曲ばかり選んでいると、他プレイヤーを苛つかせて切断する可能性があります。

みんなAtoZばかり選んで「またか・・・」って思ったことありますよね??

なので、そこら辺はうまくバランスを取って。

【C#】【ピクロス】【ALTSEED】セーブ、ロード機能を追加

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

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

https://github.com/takishita2nd/Picross

前回、汚いUIをどうしようか、ということを書きましたが、

見た目は後回し、という方針で行こうと思います。

さっさとUIを作って、解析ロジックに取りかかりたい、というのが本音です。

今回は、デバッグで必要になるであろう、セーブ、ロード機能を作成していきます。

デバッグの度に数字を入力するの、めんどくさいんで。

まずは、ボタン配置。

            // 解析ボタン
            var anlyzeButton = new Button(10, 50, "解析");
            anlyzeButton.Show();
            asd.Engine.AddObject2D(anlyzeButton.getBackTexture());
            asd.Engine.AddObject2D(anlyzeButton.getTextObject());
            buttons.Add(anlyzeButton);
            anlyzeButton.SetAction(() =>
            {
            });

            // セーブボタン
            var saveButton = new Button(10, 90, "セーブ");
            saveButton.Show();
            asd.Engine.AddObject2D(saveButton.getBackTexture());
            asd.Engine.AddObject2D(saveButton.getTextObject());
            buttons.Add(saveButton);
            saveButton.SetAction(() =>
            {
                FileAccess.Save(rowNumberSquare, colNumberSquare);
            });

            // ロードボタン
            var loadButton = new Button(10, 130, "ロード");
            loadButton.Show();
            asd.Engine.AddObject2D(loadButton.getBackTexture());
            asd.Engine.AddObject2D(loadButton.getTextObject());
            buttons.Add(loadButton);
            loadButton.SetAction(() =>
            {
                FileAccess.Load(ref rowNumberSquare, ref colNumberSquare);
            });

入力データを保存、読み取りするコードを書いていきます。

[JsonObject("dataModel")]
class Data
{
    [JsonProperty("rowdata")]
    public List<List<int>> RowData { get; set; }
    [JsonProperty("coldata")]
    public List<List<int>> ColData { get; set; }
}
class FileAccess
{
    private const string _filename = "save.dat";

    public static void Save(List<List<NumberSquare>> row, List<List<NumberSquare>> col)
    {
        if (File.Exists(_filename) == true)
        {
            File.Delete(_filename);
        }
        Data data = new Data();
        data.RowData = new List<List<int>>();
        foreach(var r in row)
        {
            List<int> list = new List<int>();
            foreach(var s in r)
            {
                if(s.GetValue() != 0)
                {
                    list.Add(s.GetValue());
                }
            }
            data.RowData.Add(list);
        }
        data.ColData = new List<List<int>>();
        foreach (var c in col)
        {
            List<int> list = new List<int>();
            foreach (var s in c)
            {
                if (s.GetValue() != 0)
                {
                    list.Add(s.GetValue());
                }
            }
            data.ColData.Add(list);
        }
        var str = JsonConvert.SerializeObject(data);
        using (var stream = new StreamWriter(_filename, true))
        {
            stream.Write(str);
        }
    }

    public static void Load(ref List<List<NumberSquare>> rowList, ref List<List<NumberSquare>> colList)
    {
        foreach(var r in rowList)
        {
            foreach(var s in r)
            {
                asd.Engine.RemoveObject2D(s.getBackTexture());
                asd.Engine.RemoveObject2D(s.getTextObject());
            }
        }
        foreach (var c in colList)
        {
            foreach (var s in c)
            {
                asd.Engine.RemoveObject2D(s.getBackTexture());
                asd.Engine.RemoveObject2D(s.getTextObject());
            }
        }

        string str = string.Empty;
        using (var stream = new StreamReader(_filename, true))
        {
            str = stream.ReadToEnd();
        }
        var data = JsonConvert.DeserializeObject<Data>(str);
        rowList = new List<List<NumberSquare>>();
        {
            int row = 0;
            foreach (var r in data.RowData)
            {
                List<NumberSquare> list = new List<NumberSquare>();
                int col = -1;
                foreach (var v in r)
                {
                    var s = new NumberSquare(row, col);
                    s.SetValue(v.ToString());
                    asd.Engine.AddObject2D(s.getBackTexture());
                    asd.Engine.AddObject2D(s.getTextObject());
                    list.Add(s);
                    col--;
                }
                {
                    var s = new NumberSquare(row, col);
                    s.SetValue("0");
                    asd.Engine.AddObject2D(s.getBackTexture());
                    asd.Engine.AddObject2D(s.getTextObject());
                    list.Add(s);
                }
                rowList.Add(list);
                row++;
            }
        }
        colList = new List<List<NumberSquare>>();
        {
            int col = 0;
            foreach (var c in data.ColData)
            {
                List<NumberSquare> list = new List<NumberSquare>();
                int row = -1;
                foreach (var v in c)
                {
                    var s = new NumberSquare(row, col);
                    s.SetValue(v.ToString());
                    asd.Engine.AddObject2D(s.getBackTexture());
                    asd.Engine.AddObject2D(s.getTextObject());
                    list.Add(s);
                    row--;
                }
                {
                    var s = new NumberSquare(row, col);
                    s.SetValue("0");
                    asd.Engine.AddObject2D(s.getBackTexture());
                    asd.Engine.AddObject2D(s.getTextObject());
                    list.Add(s);
                }
                colList.Add(list);
                col++;
            }
        }
    }
}

保存処理は、入力したデータをJsonに変換して、保存させます。

ロード処理は、一旦数字入力マスを全て削除し、管理データを作り直します。

C#ってrefを付けないとオブジェクトの参照渡しできないんですね。

まだまだ勉強しなくちゃいけないことが多いなぁ。

まだ問題とか、不具合あるかもしれないけど、それはその都度修正していくきます。

この昨日は完成後に削除する予定なので。

さて、次回からいよいよロジックに着手できるー!

【C#】【ピクロス】【ALTSEED】数字入力マスに数字を入力する

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

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

https://github.com/takishita2nd/Picross

前回追加した数字入力マスに数字を入力する処理を作っていきます。

数字入力はサイズ変更ダイアログと同じパレットを使用します。

            // パレット
            Palette palette = new Palette();
            palette.SetEngine();
            palette.Hide();

数字入力マスをクリックすると、パレットを表示させます。

パレット表示中は、マウスカーソルの所にある数字マスのテクスチャを色つきに変更します。

そして、数字をクリックすると、その数字が数字マスに入ります。

パレットの外をクリックすると、パレットを閉じ、入力終了になります。

これをコードに書いたらこうなりました。

            while (asd.Engine.DoEvents())
            {
                asd.Vector2DF pos = asd.Engine.Mouse.Position;
                if (!dialog.IsShow())
                {
                    if (!palette.IsShow())
                    {
                        foreach (var rowList in rowNumberSquare)
                        {
                            foreach (var s in rowList)
                            {
                                s.UpdateTexture(pos);
                            }
                        }
                        foreach (var colList in colNumberSquare)
                        {
                            foreach (var s in colList)
                            {
                                s.UpdateTexture(pos);
                            }
                        }
                        foreach (Button button in buttons)
                        {
                            button.UpdateTexture(pos);
                        }
                    }
                    else
                    {
                        palette.UpdateTexture(pos);
                    }
                }
                else
                {
                    dialog.UpdateTexture(pos);
                }

                if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
                {
                    if (!dialog.IsShow())
                    {
                        if (!palette.IsShow())
                        {
                            int rowIndex;
                            int colIndex;
                            rowIndex = 0;
                            foreach (var rowList in rowNumberSquare)
                            {
                                colIndex = -1;
                                foreach (var s in rowList)
                                {
                                    if (s.IsClick(pos))
                                    {
                                        selectedNumberSquare = s;
                                        selectedRowIndex = rowIndex;
                                        selectedColIndex = colIndex;
                                        palette.Show(pos);
                                    }
                                    colIndex--;
                                }
                                rowIndex++;
                            }
                            colIndex = 0;
                            foreach (var colList in colNumberSquare)
                            {
                                rowIndex = -1;
                                foreach (var s in colList)
                                {
                                    if (s.IsClick(pos))
                                    {
                                        selectedNumberSquare = s;
                                        selectedRowIndex = rowIndex;
                                        selectedColIndex = colIndex;
                                        palette.Show(pos);
                                    }
                                    rowIndex--;
                                }
                                colIndex++;
                            }
                            foreach (Button button in buttons)
                            {
                                if (button.IsClick(pos))
                                {
                                    button.OnClick();
                                }
                            }
                        }
                        else
                        {
                            if (palette.IsClick(pos))
                            {
                                string v = palette.GetClickValue(pos);
                                updateTextValue(selectedNumberSquare, v);
                            }
                            else
                            {
                                palette.Hide();
                                if(selectedNumberSquare != null)
                                {
                                    if(selectedNumberSquare.GetStringValue() != string.Empty)
                                    {
                                        if (selectedRowIndex >= 0)
                                        {
                                            var square = new NumberSquare(selectedRowIndex, selectedColIndex - 1);
                                            asd.Engine.AddObject2D(square.getBackTexture());
                                            asd.Engine.AddObject2D(square.getTextObject());
                                            rowNumberSquare[selectedRowIndex].Add(square);
                                        }
                                        else if (selectedColIndex >= 0)
                                        {
                                            var square = new NumberSquare(selectedRowIndex - 1, selectedColIndex);
                                            asd.Engine.AddObject2D(square.getBackTexture());
                                            asd.Engine.AddObject2D(square.getTextObject());
                                            colNumberSquare[selectedColIndex].Add(square);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        dialog.OnClick(pos);
                    }
                }

実行結果はこんな感じになります。

数字入力を終えると、さらに入力スペースが増えるように細工しています。

ただ、このあたりの処理は変更するかもしれません。

ここどうするのが良いのかなーと言うのを未だに考えています。

【ラズパイ】Sense HATのジャイロセンサー

Sense Hatのジャイロセンサーを使っていろいろやってみようと思ったものの、思ったような結果が得られなかったので、もっとドキュメントを読み込んでいこうと思います。

ドキュメントはこれ(英語)。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/sensors/movement.md

Sense HatにはIMUというものが搭載されているらしい。

IMUにはジャイロセンサー、加速度センサー、方位磁石が搭載されています。

向きは、Pitch、Roll、Yawの三つの軸で表されます。

まぁ、これはこないだ見た。

この動画で三つの軸の関係性が分かります。

これに関するサンプルプログラムがありました。

使い方書いてあるけど、このやり方では動かなかったので、実際に試したやり方を書いておきます。

> git clone git://github.com/astro-pi/apollo-soyuz
> cd apollo-soyuz
> sudo pip3 install pi3d
> sudo ./soyuz.py

SDカードスロットがメインブースターになるイメージです。

実際に動かしてみました。

Roll軸で回転させてみたところ、それに伴って向き自体が左右に動いている事が分かりました。

Sense Hat(IMU)に搭載されているジャイロセンサーは宇宙船を操作することに特化されていて、単純に傾けたときの3軸の角度が得られる訳では無い(ような気がする)。

宇宙船補正みたいなものがあるんじゃないか。

しらんけど。

多分、思ったような数値が出なかったのは、このせいなんだろうな。

そうだよな、Sense Hatって宇宙の科学実験用のアタッチメントだもんな。

まぁ、ちょっと宇宙船の技術に触れられたのは良かったと思う(という風に、前向きに捉える)。