じゃがいも畑

開発ネタの記録

Image Composite Editorを使ってゲーム動画からMapを生成する

結構前に深世海にハマってて思いついたので手順をまとめます
Image Composed Editorを使ってパノラマ合成で作ります

用意するもの

  • Map生成用の動画

Map生成の流れ

  1. Switchでゲーム動画を撮影
  2. ScreenToGifで動画フレームの切り出し
  3. Nameryでリネーム
  4. Image Composed Editorで画像の結合

手順

動画の切り出し作業

ScreenToGifを起動して「エディタ」を選択 f:id:whitedog0215:20200620000946p:plain

上のメニューから「ロード」を選択して撮影した動画をインポートする
フレームレートは15fpsぐらいに設定
(多いとその分時間がかかります) f:id:whitedog0215:20200620001224p:plain

画像編集タブから「切り抜き」を選択
合成の時に邪魔になりそうな部分を取り除きます
終わったら適用を押す f:id:whitedog0215:20200620001723p:plain

下のフレーム画像一覧を右クリックすると「フォルダーを表示」というメニューが出るのでクリック
f:id:whitedog0215:20200620001949p:plain

開いたフォルダに入っている画像を一式別のフォルダにコピーします

出力画像のリネーム

Image Composed Editorで読んだときにフレーム順に読み込まれるように名前を連番にします
Nameryを起動して、ScreenToGifで出力したフォルダを選択
ファイルリストを全選択、右側のリネーム設定で「文字列+連番」「開始/桁」を1/4に設定してリネーム実行 f:id:whitedog0215:20200621234501p:plain

Image Composed Editorでパノラマ化

Image Composed Editorを起動して「New Panorama from Images」を選択 f:id:whitedog0215:20200621234809p:plain

ファイルを開くダイアログで、リネーム済みの画像を全選択して「開く」を押す
画像がフレーム順に読み込まれることを確認したら右上の「Next」を押す f:id:whitedog0215:20200621235019p:plain

パノラマの生成が始まるので待つ
画像が少ないほど生成が早いのであまりにも時間がかかる場合はフレーム数を落としたほうがいいかも f:id:whitedog0215:20200621235142p:plain

割といい感じにMapが合成された
右のオプションで補正方法を選べる。気に入ったものを選択して「Next」を押す f:id:whitedog0215:20200621235553p:plain

画像の切り抜き設定。特に切り抜く必要がなければ「Next」 f:id:whitedog0215:20200621235714p:plain

最後に「Export to disk」を押してファイル保存
これでMap生成は完了 f:id:whitedog0215:20200621235805p:plain

長い動画だと合成に時間がかかって精度も落ちちゃうから短い動画で何個もMapを作る感じになるかなー

ワグナス!今年も梅酒を漬けたぞ!

漬けました

左からジン梅酒・ブランデー梅酒・梅シロップ

f:id:whitedog0215:20200608001151j:plain


というわけで以下レシピ

 

○ジン梅酒

・梅1kg

ビーフィーター 1.4l

・氷砂糖1kg

 

○ブランデー梅酒

・梅1kg

・梅酒用ブランデー1.8l

・氷砂糖 1kg

 

○梅シロップ

・梅1.5kg

・氷砂糖1kg

・上白糖 700g

りんご酢 60cc

 

 

○梅の下処理

1. 梅を洗います

2. アク抜きのため水に4時間ぐらいつける

3. 水気を取ってヘタを取る

4. フォークで穴を開ける

5. 一晩凍らせる

 

○漬け方

1. 梅と氷砂糖が層になる感じで交互に詰めていきます

2. 梅シロップは最後に上白糖をドバーッします

3. お酒やりんご酢を最後に入れます

 

こんな感じであとは定期的にかき混ぜて待ってれば完成

ジン梅酒のソーダ割りが楽しみすなあ

深世海 臨時潜水スタンダード 9分切り安定ルート ボス編

前回の続きを書いていきます whitedog0215.hatenablog.jp


攻略といってもそんなに大したことは書いてなくて
パターン化しやすい序盤になるべく体力を削って後は気合で戦う、が基本戦略になります

vs 資源探査機 大型

矢とドリルをメインにして戦います
ボスの攻撃パターンは大体↓な感じ

  • 自爆(緑)
    f:id:whitedog0215:20200511223402p:plain ほとんどモーションがないので食らいやすい
    ボンベもかなり持ってかれるの危ない

  • 自爆(赤)
    f:id:whitedog0215:20200511223319p:plain 予告が出るのでわかりやすい
    攻撃を当てて続けてればやめてくれる?

  • ジャンプ
    f:id:whitedog0215:20200511224001p:plain 踏みつぶされるとダメージ

  • フックショット(上)
    f:id:whitedog0215:20200511224333p:plain 遅延行為
    なるべく上に行かれる前に攻撃して落とそう
    天井に行っちゃったら殴って落とすか、下を通って落ちてくるのを待つかになる

  • フックショット(横)
    f:id:whitedog0215:20200511224208p:plain 地上で立っていれば当たらない
    当たっちゃうと引き寄せてから自爆(赤)を発動するのでブーストで逃げないと危険

ある程度攻撃を当てたらひっくり返ってダメージが入るようになるので、2回ひっくり返して倒すパターンを組んでいきます
(ひっくり返る条件がよくわからん...)

1.ボス部屋に入ったら画像の位置ぐらいに立ち、ボス登場のエフェクトが出たらドリルを発射
f:id:whitedog0215:20200511225422p:plain

2.前ジャンプして2発目を発射、なるべく1発目のドリルと同時にボスに当たるようにする
f:id:whitedog0215:20200511225513p:plain

3.武器を矢に切り替えて攻撃、ボスがひっくり返ってから起きるまで矢を連射
体力を2/3以上削れていれば上出来 f:id:whitedog0215:20200511225954p:plain

4.以降はアドリブ
基本的な戦い方はボスの移動や攻撃に合わせてドリルを1発発射+追撃の矢で頑張ってひっくり返すになります
ひっくり返ったら勝ち確なのでがんばりましょう

vs ダンクルオステウス

ボムと矢をメインにして戦います
攻撃パターンは↓
トルネード突進はされないように頑張る

  • 噛みつき
    f:id:whitedog0215:20200511231537p:plain 無敵空間から噛みついてくる
    避けるのは全然難しくないが、めっちゃ時間を持ってかれる

  • 青玉
    f:id:whitedog0215:20200511231855p:plain こちらに泳いでくるときに1~3個放出する
    主人公を追尾してきて当たるとめちゃくちゃ酸素を消費させられる
    矢で除去しておこう

  • 赤玉
    f:id:whitedog0215:20200511231940p:plain 泳ぎながらたくさん放出してくる。海にゴミを流すな
    範囲内に入ると自爆する機能を持っている
    事故死率が高いので噛みつき攻撃待ち中になるべく破壊しておくのが吉


7個ターゲットを壊せば終わりだけど、1個ターゲットを壊すと30秒ぐらい手を出せなくなる最悪の遅延能力を持ったボス
ボムでまとめてターゲットを破壊しながら残ったターゲットを矢で破壊する、が基本戦略になります

1.ボス部屋に入る前に画像の位置あたりから右下に向かってボム発射
ターゲットを3つぐらい破壊できる
f:id:whitedog0215:20200511233004p:plain

2.1でダメージを与えた直後にボム発射、自分は1枚目の画像のような位置関係が好み
2枚目の画像はボムの爆発と同時に矢でのターゲット破壊も狙っているところ
うまくできるとおいしいです
f:id:whitedog0215:20200511233317p:plain f:id:whitedog0215:20200511233521p:plain

3.以降はアドリブ
噛みつき攻撃を回避、青玉を矢で除去して最後のボムでターゲット破壊を狙いましょう
2と同様に矢でもターゲット破壊を狙います
ターゲットが残り1個ならボムなしでいいと思います

道中と合わせてボス編もうまくできるようになれば7分台は安定してくると思います
みんなでやろう臨時潜水TA

てかもっと深世海の攻略記事増えてもいいと思うからみんな書いてよ
俺も書いたんだからさ

最近臨時潜水ばっかりやってたから本編2週目に戻るぞー

深世海 臨時潜水スタンダード 9分切り安定ルート 道中編

深世海で検索しても全然攻略記事がなかったので自分で書きます
これが一番簡単で早いと思います

(この記事は攻略のネタバレを含んでいます)

故郷エリア

最初の分岐を左側に進み、壁を破壊
右に進み、岩を砕いてから矢を取ります
左に歩きつつ、ボンベが降ってくるので取ります
f:id:whitedog0215:20200506234200p:plainf:id:whitedog0215:20200506234110p:plainf:id:whitedog0215:20200506234033p:plain

手前のサンゴを矢で倒し、滑りながらサンゴの間を抜けて右へ
サメと資源採掘機 歩型はスルーして左のルートに進んでいきます
f:id:whitedog0215:20200506234359p:plainf:id:whitedog0215:20200506234457p:plain

サンゴの手前で少し浮遊してタイミングをずらしてからサンゴの間を進みます
1本目のつららに乗り、下向きに矢を打つとうまく通り抜けることができます
つららエリアを抜けると左隅に穴があるのでそこから下へ抜けていきます
f:id:whitedog0215:20200506234556p:plainf:id:whitedog0215:20200506234626p:plainf:id:whitedog0215:20200506234657p:plain

大海溝エリア

吊にフックショットを当てて落下していくだけです
砕いた岩に当たるとダメージを受けるので早めにフックショットを離して吊とは距離を取っておきましょう
底まで下りたら酸素残量をキープしながら右へ
f:id:whitedog0215:20200507104121p:plain

古代遺跡エリア

遺跡は真ん中のルートを通ります
酸素をキープできていれば補給なしで進んで大丈夫です。もし足りなければ通路そばの岩を砕いて補給
f:id:whitedog0215:20200507114714p:plain

真ん中ルートの底に着いたらスイッチを押して左へ進み、ウツボの下を通過
上に進んで岩を砕いて補給、そのまま右へ
ウツボが2匹いるところはウツボの下をくぐってからブースト使いながら下へ
f:id:whitedog0215:20200507114832p:plainf:id:whitedog0215:20200507114918p:plainf:id:whitedog0215:20200507115019p:plain

スイッチを押し、ドリルとボンベを取ります
早速ドリルで地面を砕いて道を作ります。この時岩を狙うようにすれば1発で済むのでGood
f:id:whitedog0215:20200507111023p:plainf:id:whitedog0215:20200507111055p:plain

雑魚ボス部屋の前ですが、矢は足りているので取らなくて大丈夫です
2体いますが矢を3発ずつすべてきっちり当てて倒しましょう
f:id:whitedog0215:20200507111745p:plain

沈没船エリア

ボスを倒したときに出る泡を纏い、ブーストを使って下に進んでいきます
ボムが欲しいので分岐は右へ
f:id:whitedog0215:20200507112119p:plain

丸形の通路に入りボンベをスルーして右上へ(より安定させたい場合は取って大丈夫)
オニキンメ?が2体いる場所はブーストを使いながら棍棒で殴るようにすると進みやすいです
通路を抜けてボムを取得
f:id:whitedog0215:20200507112844p:plainf:id:whitedog0215:20200507112923p:plain

水面で酸素を補充してから潜り、天井に沿って進んで生体調査機(洗脳)の上側を通過
ここでブーストを使ってしまうと酸素が足りなくなるため使わないようにします
(運が悪く生体調査機(洗脳)に殴られることもありますが、ボンベが足りてるのでそのまま進んで大丈夫です)
そのあとのくらげエリアは壁に沿って進んで抜けます
f:id:whitedog0215:20200507113232p:plainf:id:whitedog0215:20200507113423p:plain

粘菌ゾーンはブーストを使って抜けていきます
1体目、2体目は画像のあたりでブーストを使えばボムを温存して進むことができます
酸素がやばいのでボンベを拾ってから吊につかまって左へ
f:id:whitedog0215:20200507114102p:plainf:id:whitedog0215:20200507114126p:plainf:id:whitedog0215:20200507114308p:plain

海底火山エリア

吊からフックショットを離したら右側の通路へボムを撃ち、岩を砕いて酸素を補給
粘菌がおとなしくなってから通路を進み、フックショットで爆弾を破壊
左側の地面を破壊してもう一度フックショットで爆弾を破壊
ボンベを取りつつ壁を滑っていくと地面に穴が開きます
f:id:whitedog0215:20200507222007p:plainf:id:whitedog0215:20200507222121p:plainf:id:whitedog0215:20200507222227p:plain

粘菌回避のため右へ進むとスケーリーフットがまとわりついてくるので棍棒で倒します
f:id:whitedog0215:20200507115925p:plain

左に進んで2体の資源探査機 小型の間ぐらいにボムを撃ちこみます
資源探査機 小型の左側に回り込んでから矢を撃って1体目を倒し、残った2体目も棍棒で倒します
f:id:whitedog0215:20200507121810p:plainf:id:whitedog0215:20200507121156p:plainf:id:whitedog0215:20200507121335p:plain

下へ進むとボンベと岩があるのでとりあえず補給
f:id:whitedog0215:20200507122011p:plain

溶岩の上を滑って進み、溶岩の噴出を待ってからジャンプ
そのあとに下にブーストすることでうまく抜けられます
f:id:whitedog0215:20200507122318p:plainf:id:whitedog0215:20200507122449p:plainf:id:whitedog0215:20200507122351p:plain

右側の溶岩に沿ってゆっくり下りていき、資源探査機 小型のフックショットを誘導して左に切り返し
溶岩の噴出を待ってから左に進みます
最後の矢で下に道がある溶岩を破壊してボス前最後の補給エリアに到着!
f:id:whitedog0215:20200507144848p:plainf:id:whitedog0215:20200507144948p:plainf:id:whitedog0215:20200507145548p:plain

酸素と矢とドリルを補給してボスに挑みましょう
早くて5分ぐらい、グダグダになっても6分ちょっとでここまで来れると思います
f:id:whitedog0215:20200507150007p:plain

あとはボスを3分で倒すだけ!できらぁ!

※追記
ボス編を書きました

whitedog0215.hatenablog.jp

豆苗 成長記録のまとめ

豆苗育てて14日目においしくいただきました

よくね?

f:id:whitedog0215:20200426001647g:plain

以下まとめ

  • いちごパックの大きくてそこの浅いタイプが豆苗育成にぴったり
  • 水と日光だけで育つ
  • 水は毎日変える(根本部分だけ水につかるようにする。種は水の上)
  • ほどほどに日に当てるとよい
  • 日に当てる側は定期的に入れ替えたほうが伸びそう(入れ替えないと日に近いほうが背が低くなる)

ごちそうさまでした

C# WPF enumに属性を付けてComboBoxにバインドして便利に使う

参考元

こちらの記事を参考にさせていただきました

qiita.com

qiita.com

できること

↓のような感じで項目名と属性で追加情報を付けたenumを定義しておけば

        public enum Fruit
        {
            未選択,
            [Price("\\150"), Color(KnownColor.Red), ResourceName("apple.png")]
            りんご,
            [Price("\\80"), Color(KnownColor.Yellow), ResourceName("banana.png")]
            ばなな,
            [Price("\\120"), Color(KnownColor.Orange), ResourceName("orange.png")]
            みかん
        }


項目名をそのままコンボボックスで使ったり、追加情報を簡単に取得することができるようになります f:id:whitedog0215:20200421235318g:plain

ソースコード

ソースコードはこちら github.com

ポイント

属性の定義方法や必要な拡張メソッド等は参考記事を参照してください

(参考記事内のコードスニペットattrgを使用させていただきました)


  • 定義した属性をenumに付与しています
  • enumの項目名に名前、属性には価格、色、リソースの画像を付けています
        public enum Fruit
        {
            未選択,
            [Price("\\150"), Color(KnownColor.Red), ResourceName("apple.png")]
            りんご,
            [Price("\\80"), Color(KnownColor.Yellow), ResourceName("banana.png")]
            ばなな,
            [Price("\\120"), Color(KnownColor.Orange), ResourceName("orange.png")]
            みかん
        }


  • enumで列挙した値をすべて取り出して、コンボボックスのデータソースに追加します
            DataSource = new ReactiveCollection<Fruit>();

            foreach (Fruit g in Enum.GetValues(typeof(Fruit)))
            {
                DataSource.Add(g);
            }


  • コンボボックスの選択が切り替わったときに呼ばれるメソッドです
  • 新しく選択されたenumの値が"g"に入っているので、enumの拡張メソッドを使って追加情報を取り出しています
            SelectedItem.Subscribe(g =>
            {
                ItemName.Value = $"Item : {g}";
                ItemPrice.Value = $"Price : {g.GetPrice()}";
                ItemColor.Value = $"Color : {g.GetColor()} ";
                SelectedColor.Value = g.GetColor().ToMediaColor();
                ItemImage.Value = new Uri($"..\\Resource\\{g.GetResourceName()}", UriKind.Relative);
            });

ReactivePropertyの便利メソッド(ToReactivePropertyとToReactivePropertyAsSynchronized)

名前が長くて呼び出し方をよく忘れてしまいますが、ViewModelとModelで片方向・双方向バインドができてとても便利です

なるべく短くまとめたいと思います

ToReactiveProperty系メソッド

  • ToReactiveProperty
  • ToReadOnlyReactiveProperty
  • ToReadOnlyReactivePropertySlim

Modelの値が変更されたとき、ViewModelへの通知を行います(片方向)

こんな感じでボタンを押すとTextBlockに値のカウントを増やす動きを作ります

f:id:whitedog0215:20200317012102g:plain

まずはサンプルコード

  • ViewのButtonとTextBlock
<Button Width="100" Height="40" Content="Button" Command="{Binding ButtonCommand}" FontSize="20"/>
<TextBlock Text="{Binding Counter.Value}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="50"/>
  • ModelとViewModel
    public class Model : BindableBase
    {
        private int pushCount;
        public int PushCount
        {
            get { return pushCount; }
            set { SetProperty(ref pushCount, value); }
        }
    }

    public class MainWindowViewModel : BindableBase
    {
        public ReactiveCommand ButtonCommand { get; } = new ReactiveCommand();
        public ReadOnlyReactivePropertySlim<int> Counter { get; }
        public MainWindowViewModel()
        {
            var model = new Model();

            this.ButtonCommand.Subscribe(() =>
            {
                model.PushCount++;
            });

            this.Counter = model.ObserveProperty(x => x.PushCount).ToReadOnlyReactivePropertySlim();
        }
    }
  • 大事なポイント
this.PushCount = model.ObserveProperty(x => x.PushCount).ToReadOnlyReactivePropertySlim();

ModelはINotifyChangedを継承する必要があります(BindableBaseはINotifyChangedを継承したPrismのクラス)

ObservePropertyから変更通知を受け取りたいプロパティを指定してToReactivePropertyします

こうすることで

  1. ボタンが押されたらModel.PushCountの値を変更
  2. Model.PushCountがViewModelCounterへ変更を通知
  3. 表示の更新

という動きが実現できます

ToReactivePropertyAsSynchronized

  • ViewModelの値が変更された時、Modelに変更の通知
  • Modelの値が変更された時、ViewModelに変更の通知

を行います(双方向)

f:id:whitedog0215:20200317215148g:plain

  • TextBoxに入力した文字と同じ文字をTextBlockに表示
  • VMボタンを押すとVMと入力
  • Mボタンを押すとMと入力

サンプルコード

  • Viewのそれぞれ
<TextBox Width="200" Height="40" Text="{Binding Input.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="20"/>
<TextBlock Text="{Binding Output.Value}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"/>
<Button Width="100" Height="40" Content="VM" Command="{Binding ViewModelChangeCommand}" FontSize="20"/>
<Button Width="100" Height="40" Content="M" Command="{Binding ModelChangeCommand}" FontSize="20"/>
  • ModelとViewModel
    public class Model : BindableBase
    {
        private string input;
        public string Input
        {
            get { return input; }
            set { SetProperty(ref input, value); }
        }
    }

    public class MainWindowViewModel : BindableBase
    {
        public ReactiveProperty<string> Input { get; }
        public ReadOnlyReactivePropertySlim<string> Output { get; }
        public ReactiveCommand ViewModelChangeCommand { get; } = new ReactiveCommand();
        public ReactiveCommand ModelChangeCommand { get; } = new ReactiveCommand();
        public MainWindowViewModel()
        {
            var model = new Model();

            this.Input = model.ToReactivePropertyAsSynchronized(x => x.Input);

            this.Output = model.ObserveProperty(x => x.Input).ToReadOnlyReactivePropertySlim();

            this.ModelChangeCommand.Subscribe(() =>
            {
                model.Input = "M";
            });

            this.ViewModelChangeCommand.Subscribe(() =>
            {
                this.Input.Value = "VM";
            });
        }
    }
  • 大事なポイント
this.Input = model.ToReactivePropertyAsSynchronized(x => x.Input);

INotifyChangedを継承したModelからToReactivePropertyAsSynchronizedを呼び出し、双方向バインドしたいプロパティを指定します

こうすることで

  1. TextBoxに文字を入力するとViewModel.Inputの値が変更
  2. ViewModel.InputがModel.Inputに変更を通知
  3. Model.InputがViewModel.Outputに変更を通知(表示の更新)

という動きができています。さらにボタンを押したときには

  • Mボタンの場合

  • ボタンが押されたらModel.Inputの値を変更

  • Model.InputがViewModel.InputとViewModel.Outputに変更を通知(TextBoxとTextBlockの表示更新)

  • VMボタンの場合

  • ボタンが押されたらViewModel.Inputの値を変更(TextBoxの表示更新)

  • ViewModel.InputがModel.Inputに変更を通知
  • Model.InputがViewModel.Outputに変更を通知(TextBlockの表示の更新)

という動きになります

わざわざモデルの値を見に行く必要がなくなるので便利