ゲーム作りは楽しい

なんか書く

レイヤー合成、計算式メモ

随時更新するかも

焼きこみ

float colorBurn(float dest, float src)
{
    return src <= 0 ? 0 : 1 - (1 - dest) / src;
}
float4 colorBurn(float4 dest, float4 src)
{
    float4 color;
    color.r = colorBurn(dest.r, src.r);
    color.g = colorBurn(dest.g, src.g);
    color.b = colorBurn(dest.b, src.b);
    color.a = 1;
    return color;
}

覆い焼き

float colorDodge(float dest, float src)
{
    return src >= 1 ? 1 : dest / (1 - src);
}
float4 colorDodge(float4 dest, float4 src)
{
    float4 color;
    color.r = colorDodge(dest.r, src.r);
    color.g = colorDodge(dest.g, src.g);
    color.b = colorDodge(dest.b, src.b);
    color.a = 1;
    return color;
}

ビビッドライト

float vividLight(float dest, float src)
{
    return src < 0.5 ? colorBurn(dest, 2 * src) : colorDodge(dest, 2 * (src - 0.5));
}
float4 vividLight(float4 dest, float4 src)
{
    float4 color;
    color.r = vividLight(dest.r, src.r);
    color.g = vividLight(dest.g, src.g);
    color.b = vividLight(dest.b, src.b);
    color.a = 1.0;
    return color;
}

ハードライト

float hardLight(float dest, float src)
{
    return src < 0.5 ? dest * src * 2.0: 1 - 2 * (1 - dest) * (1 - src);
}
float4 hardLight(float4 dest, float4 src)
{
    float4 color;
    color.r = hardLight(dest.r, src.r);
    color.g = hardLight(dest.g, src.g);
    color.b = hardLight(dest.b, src.b);
    color.a = 1.0;
    return color;
}

スクリーン

float screen(float dest, float src)
{
    return 1 - (1 - dest) * (1 - src);
}
float4 screen(float4 dest, float4 src)
{
    float4 color;
    color.r = screen(dest.r, src.r);
    color.g = screen(dest.g, src.g);
    color.b = screen(dest.b, src.b);
    color.a = 1.0;
    return color;
}

参考

osakana.factory - ブレンドモード詳説

[CG] 描画モードについて - CG/CG概論

Python3 & OpenCV で画像処理を学ぶ[5] 〜 AfterEffects/Photoshopにある描画モードを実装する - Optie研

C++でコードベースのファイル名を使用したマイグレーションみたいなものを作った

コードベースのマイグレーションみたいなものを作りました。

wandbox.org

以下に

  • 1_Test.cpp
  • 2_Hoge.cpp

がありますが、これのprefixの数字をidとして、カレントバージョンから最新バージョンまで全部実行する仕組みです


1_Test.cpp

#include"Migration.hpp"
#include <iostream>

namespace 
{
    MIGRATION(Test)
    {
        void up() const override
        {
            std::cout << "Up Test" << std::endl;
        }
        void down() const override
        {
            std::cout << "Down Test" << std::endl;
        }
    }_;
}

2_Hoge.cpp

#include"Migration.hpp"
#include <iostream>

namespace 
{
    MIGRATION(Hoge)
    {
        void up() const override
        {
            std::cout << "Up Hoge" << std::endl;
        }
        void down() const override
        {
            std::cout << "Down Hoge" << std::endl;
        }
    }_;
}

呼び出し
main.cpp

int main()
{
    using Migration::MigrationHundler;
    int current = 0;
    std::cin >> current; 
    
    std::cout << "Latest: " << current << std::endl;
    
    std::cout << "-- Migration Up --" << std::endl;
    current = MigrationHundler::Up(current);
    std::cout << "Latest: " << current << std::endl;

    std::cout << "-- Migration Down --" << std::endl;
    current = MigrationHundler::Down(current);    
    std::cout << "Latest: " << current << std::endl;    
    
    std::cout << "-- Migration Down --" << std::endl;
    current = MigrationHundler::Down(current);    
    std::cout << "Latest: " << current << std::endl;      
}

出力

Latest: -1
-- Migration Up --
Up Test
Up Hoge
Latest: 2
-- Migration Down --
Down Hoge
Latest: 1
-- Migration Down --
Down Test
Latest: -1

実装

Migration.hpp

#pragma once
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <optional>

namespace Migration
{
    struct IMigration
    {
    public:
        virtual ~IMigration() = default;
        virtual void up() const = 0;
        virtual void down() const = 0;
    };

    template<int Id>
    struct Migration;

    class MigrationHundler
    {
    public:
        template<int Id>
        static void Regist(IMigration* migration)
        {
            m_migrations[Id] = migration;
        }

        static IMigration* Get(int version)
        {
            return m_migrations[version];
        }
        
        static int Up(int currentVersion)
        {
            int nextVersion = -1;
            std::vector<int> updateVersions;
            for (auto&& m : m_migrations) {
                if (m.first > currentVersion) {
                    updateVersions.push_back(m.first);
                    if(nextVersion < m.first) {
                        nextVersion = m.first;
                    }
                }
            }
            std::ranges::sort(updateVersions);
            for(int v : updateVersions) {
                m_migrations[v]->up();
            }
            return nextVersion == -1 ? currentVersion : nextVersion;
        }
        static int Down(int currentVersion)
        {
            if(m_migrations.find(currentVersion) != m_migrations.end()){
                m_migrations[currentVersion]->down();
            }
            int nextVersion = -1;
            for (auto&& m : m_migrations) {
                if (m.first < currentVersion) {
                    if(nextVersion < m.first) {
                        nextVersion = m.first;
                    }
                }
            }
            return nextVersion;
        }        
    private:
        MigrationHundler() = default;
        MigrationHundler(const MigrationHundler& other) = delete;
        void operator=(const MigrationHundler& other) = delete;
    private:
        inline static std::unordered_map<int, IMigration*> m_migrations;
    };

    template<int Id>
    struct Migration : public IMigration
    {
    public:
        Migration()
        {
            MigrationHundler::Regist<Id>(this);
        }
    };

    namespace detail
    {
        consteval int versionId(const char* path)
        {
            // filename取得
            const char* filename = path;
            while (*path) {
                if (*path++ == '\\') {
                    filename = path;
                }
            }
            // バージョン値取得
            const char* str = filename;
            int value = 0;
            while (char c = *str) {
                if (c <= '9' && c >= '0') {
                    value = (c - '0') + value * 10;
                } else {
                    break;
                }
                ++str;
            }
            return value;
        }
    }
}

#define MIGRATION(name) struct name :  ::Migration::Migration<::Migration::detail::versionId(__FILE__)>

ファイル名からprefixのidへの変換はdetail::versionIdでします。
これをMIGRATIONマクロに隠蔽することでよしなに紐づけてます。

Hundlerへの登録はインスタンス生成時にthisポインタを渡しますので、各実装をしたら一つどこかにインスタンスが必要です。
例では_の変数名で無名名前空間に生成しています

実際の運用について

実際にはカレントバージョンをどこかに永続化する必要があるので何度も更新が走らないようにtxtなりdbなり自由に保存しておきましょう。

メタクラスについて勉強してみました。

メタクラスについて勉強してみた。

class とか structっていうキーワードを使う箇所をユーザー定義したものに変えて

my_class Hoge{};

みたいに使います。
んで、 何ができるかというと

例えばC++ではstructはデフォルトpublic, classはprivateっていう話がありますが、 そーゆーデフォルト時のルールを決めることができたり、違反したらコンパイルエラーにできたりする。
メンバ変数は指定しなければprivateになる。すべてprivateじゃなければコンパイルエラー!みたいな

例だとinterface メタクラスを例に上げていた

$class interface
    {
     // デストラクタ定義
    ~interface() noexcept { }
    constexpr
    {
        // メンバ変数はもったらコンパイルエラー
        compiler.require($interface.variables().empty(), "interfaces may not contain data");
        for (auto f : $interface.functions())
        {
            // コピー、ムーブはコンパイルエラー
            compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a" " virtual clone() instead");
            // アクセス指定子いないならpublicにする
            if (!f.has_access()) f.make_public();
            // public以外があったらコンパイルエラー
            compiler.require(f.is_public(), "interface functions must be public");
            // 純粋仮想関数とする
            f.make_pure_virtual();
        }
    }
};
interface IHoge
{
    void hoge();
};

class IHoge
{
    public:
    virtual ~IHoge() = 0;
    virtual void hoge() = 0;
};

みたいになるという感じですかね

未来の話なのでどうなることかわからんが、面白そうだった

参考

https://www.fluentcpp.com/2017/08/04/metaclasses-cpp-summary/

C++でDIするヘッダーオンリーライブラリを作りました。

C++でDIするヘッダーオンリーのライブラリを作りました。

github.com

Zenject(Extenject)などから影響を受けてます。

C++でC#のasみたいな書き方する遊び(糞)

template<class T>
struct as_op
{};

template<class T>
constexpr as_op<T> as_obj{};

template<class T, class U>
auto operator | (T* ptr, const as_op<U>& op) {
    return dynamic_cast<U*>(ptr);
}
#define as | as_obj

struct Super{virtual ~Super()=default;};
struct A : Super{
};
int main()
{
    Super* super = new A{};
    
    auto a = super as<A>;
    
    delete super;
}

2020年 7月~9月 ゲーム/アニメ感想

このシーズンはめっちゃインプットした。主にアニメ。
進捗ダメですになりました。

今期遊んだゲーム

すいません。まだクリアしてないです。
開けてなかったのをようやく開けてプレイした。

もともとドット絵だったものをここまでしっかり3Dアクションにしてすごいなと思ったりした。
またクリアしたときに改めて感想を書こう

  • ロックマンXDiVE

こちらについては継続中。
感想は前回あげたので省略とする

さて、ようやく日本でもでるらしい。 が、当然アジア版のデータを引き継ぐことはできないので、わざわざ日本版をやることはなさそうだ。
いわゆるおま国アプリで、日本だけ遅れて出ることになった 遅れて出す分、レベルバランスなどの調整を期待したいが、もし何も変わってなかったら本当に意味がない。
あとはイベントが専用のものがでたりして、日本先行のものがなにか入るか気になる所です。 ひとまず日本版のリリースが楽しみですね(私は遊ばない)

これについても数か月前に一度触れてはいるが、改めて全タイトルクリアしたのであげることにする。 具体的には

これらの6作品をすべて1からラスボスクリアまでプレイした。(ゼクスの裏ボスオメガはやってない)
僕が今回はじめて遊んだ作品はロックマンゼクス アドベントのみなのでここではそこをつまむとする。

ロックマンゼクス アドベント
こちらは続編がでるまで遊ばないと思っているうちに何年もたってしまい、、いいかげん遊ぶ機会に恵まれたので遊べた。

いろんなキャラに変身できて楽しいゲームである。
ゲームオーバーがゼロ1の頃みたいにセーブしたところからやり直しなのが地味に面倒くさい。
こまかいミッションがあったりすので、それらの達成もすべてリセットされてしまうのだ。
最近は残機がなくなったゲームも多くなってきており、ユーザーがこの手のリトライにストレスを感じているのを思う。

あとゼクスのラスメン。セルパンカンパニーが廃墟みたいになって出てくるところがすごくエモかった。

こちらはSwitchのスーファミで遊んだ
いわゆる落ちものパズル系のゲームです。(下から上がってくるのだけど)
兄とめっちゃ対戦したが、なかなか難しく全然勝てなかった。 この手のゲームはいつやっても楽しめるのでいいと思う。(対戦相手がいれば)

カービィファイターズの2がでた!!(Zとはなんなのか)
カービィシリーズはなぜか、配信します。今日!みたいなことをしだすので…仕事中の私はビックリしてしまった。
ゲームはカービィファイターズにストーリモードやオンライン対戦を加えたものだった。

ストーリーモードはタワーを連戦で登っていき一番上のボスを倒したらクリアみたいなモードで、これが5章まである。
今作はバディと共に戦う2vs2が基本なのでAIの仲間と、もしくはコントローラーを貸して二人で戦うことになる。
一戦終わるごとにアイテムルームでバフのアイテムや回復アイテムを1つ選ぶことができる。こちらがランダム要素なので本当に運が悪いとどんなに頑張っても、ほぼ勝てないような状況にもなることもあるのがつらかった。
途中で負けても何度でもやり直せるが、5章だけは3回負けたらゲームオーバーで1階からやりなおしになる。(ちなみに5章は50階まである)
最初これはムズイ…とおもい心臓バクバクになって5章クリアしたのだが、後でTwitterのフォロワーに負けそうになったらリセットすればいいと教えてもらい怖いものがなくなった。
このゲーム中断セーブがあるので、負けそうになったらやめてしまえばいいんですよね…、(ちなみに負けた場合その瞬間にセーブが走るので手遅れで、負ける前にリセットならセーフ)

途中でひとりでモードが解禁されたのだが、こちらが結構つらい
トリデラにもあったが、そっちもそうだった気がするが 終盤1vs3で戦うことになるが相手はパターン化された大ボスではなく一人ひとりがAIで動くので、時に絶対攻撃をよけられない状況なんて多々ある ひたすらリンチされてしまうので、何度も挑戦しては敗北を繰り返すと、だんだんこれ何が楽しいのという感情になる
しかもこれタイムアタックで、時間によってプラチナメダルがあるんですよ…

オンラインに関しては特にレートとかもなくやりこむ要素はない、また一人モードはなく必ず2vs2のマッチングになる。 こちらはおまけ要素くらいに思えばいいだろう。 また、もらえる経験値も多いと書いてある割にストーリーのほうが多いので、特別やる理由は何もなかった。

100%について
私は2週間ほどこのゲーム以外ろくに何もせずに累計65時間遊び続けて100%になった…疲れた
対戦後に経験値がもらえ、ランクがあがる。ランクが上がると能力やステージなどが開放されていくのだが、これが100まで上がる。 これを100まであげるのにかなり時間がかかる。おかげで私は土日もろくに休めないでいたわけだ。

また、つらいといったひとりでモードを全能力でむずかしい以上をクリアする必要がある。どうして…
めちゃむずじゃないだけマシではある。

このゲーム100%にするのはかなりの根気を求められる。私はもはやシリーズ愛の使命感で頑張れたに過ぎない。
ともかく楽しいゲームではあった。
プレイアブルにマホロアいたのでカビマホで口移しする遊びができた。


ここからは個人製作のフリーゲームとか

  • 置いテク(最終更新版)

チルゴロウさんが作成していたパズルゲーム。こちらは未完成ではあるがとのことで公開されたのでプレイしてみた。
私のキャラ、「プリル」ちゃんも参戦していたのでずっとプリルちゃんを使っていた。

こちらはテトリスのミノみたいなものを正方形の盤面に埋めていくというシンプルなゲーム。
でもすごく楽しい。さらにキャラごとにでてくるピースがちがっていたり、スキルがあって相手を邪魔したりといろんな要素がある。
期待していただけに開発中止になったのはすごく残念な気持ちだ。

しかしこの人の作るゲームは安定して細かい動きが作りこまれているのがよい。(たぶん結構使いまわしてると思う)
あとリソースも専用の拡張子にしているようだ、裏で何やってるのかはよく知らない。

  • 群青禍刻ノ魔人(ブルーアワーインカネーション)

こちらはフリーのアクションゲーム。作者がカービィロックマンXに影響されて作ったと言っていたので、カービィロックマン好きな私はやるべきでは?と思いプレイした。
あと、今自分が作ってるアクションゲームも両作品の影響を受けている作品なので、いろいろ参考になるかと思い。

基本アクションは壁キックやダッシュといった確かにXっぽい動きができた。攻撃は敵をつかんで敵に投げたりするのだけどこの辺は確かにカービィぽかった
なんかクラッコみたいなボスもいた。

ボスもちゃんとパターン化されていてしっかりした攻略ができたのでゲームとしてとても普通に楽しむことができた。
ボリューム感は2, 3時間もあればクリアできてしまう程度ではあったがサクッと遊ぶ分にはちょうど良かった。

今続編も開発中らしいです。

今期見たアニメ

作者が女の子描きたくなったのかな?と思わずにはいられない女子チームになってしまっていた。 なんだろう。なんなんだろう。需要はあるのかもしれないがなんだか違う気がした

まぁともかく内容は面白い メジャーという感じ
こちらはまだ放送中

かぐや様が可愛かった

なんとなくまどマギが見たくなったので劇場版を見て、あ~こんな感じだったなと懐かしく思いつつも
実はまだ見たことなかった新編を初めて見ました。
渚ちゃんって、あいつだったんだな(見て知った)

新編で、さやかと杏子が仲良くやってるのが良かった。とにかく良かった。 あと、さやかちゃんがオクタヴィア使いこなしてるのかっこよかった。

これ、続きやるんかな? なんかあるみたいだけど

  • マギアレコード

上の流れで見ました。
ゲームはすこしやってたけどすぐやめたので内容は全く知らなかったのですが
こっちはだいたい2話完結くらいでいろんな「うわさ」をテンポよく解決していく感じのアニメだった。 世界観こそまどマギだけど、話の構成は元がソシャゲというのもあり別物って感じがした。
しかし、杏子、さやか、まみさんとかも登場するのがいいですね。

まどマギで世界について考えるのはもはや難しいのだけど、この世界どこの軸だよって感じだ(いずれわかるんだろう)

いい加減みました。 キャラはもともと見たことあるやつとかいたけどほぼなんも知らん状態から見ました。 昔ジョジョみたいって聞いたことあったけど、あ~そういう意味ねってなりました。

なんかすごくいいところでアニメが終わってしまい、そりゃ原作に流れるよ~

  • Dr.STONE

最近のジャンプ先品気になるの流れで見ました。
これ面白い。難しいこと言ってるんだけど、わからなくてもまぁ面白い。
こーゆー世界の終わりからやり直す感じワクワクします。
冬に2期やるらしいので楽しみです。

最近のジャンプ先品気になるの流れで見ました。 私は人が食われる作品は嫌いじゃないのでこの絶望感が良かった。 このあとどうなるのだろうと気になるけど こちらも2期があると思うので楽しみです。

伊藤誠殺されるシーンしか知らなかったのですけど鬱アニメランキングでわりと見かけたから見てみることにしました。 まどマギとか見てたら、もっとこういう鬱なのちょうだいってなったんですよね…
普段はこーゆーエロゲのアニメとかみないんですけどね…

う~ん、伊藤誠がクズでした。

  • ぼくらの

鬱アニメランキングでよく見かけたので見てみたのですけど、僕の感覚がくるってるのでそこまででしたね。
どちらかというと「なるたる」みたいなショッキングなもののが好きかもしれない

あと、原作と終わり方違うそうで、そーゆーのやめてほしいと思っちゃいます。

これは鬱ではないのですけど、なんかグロよりで見ました。
あと僕の好きなゆゆゆと同じタカヒロIVプロジェクトのひとつで前から気になっていたのです。 実際には当時見たことあったのですが、ちゃんと見てはいなかったので記憶にあまりありませんでした。

これも原作とだいぶ終わりのほうが違うそうで、そーゆーの本当好きじゃないです。
原作では主人公生きてるのにアニメでは主人公死ぬってどゆことよ??

おススメされたので見始めた作品。 1話ではロボットと怪獣か戦うアニメかと思ったのですが、2話で世界観がわかった。
普通に面白かったです。
口に出して言いたいですね、「バグはこの世界に必要だ」

普段こーゆーラノベのアニメとか全然みないんですけど、興味本位で見てみたんです。グロそうだったので
主人公とか登場人物が殺されたり死んだりしまくるのですけど、主人公とかヒロインとか精神くるって発狂したり病んだり姿とかもいいですね。
これ2期が分割されてるみたいで、ふつ~に何事もなく夏分終わってしまったけど、じゃあ続き冬からねって、そんな放送形態もあるんだぁと驚きました。 (普段あまりアニメ見ないから知らないでけでよくあるのかな?)

とりあえず面白いことが分かったのと
みんながレム好きな理由がわかった。

1話だけ見ました。だって見たことないなと思ったから。 アニメの原点ですからね。
顔がとびだして目が置いて行かれる表現がすごく面白かったのが印象に残りました。

たまたま10話かなんかだけを、なんとなく見てみただけですが一応書いておきます。 普通にかいけつゾロリでした。