ゲーム作りは楽しい

なんか書く

C++:非virtualデストラクタ継承の話

デストラクタがvirtualでないclassの継承には注意が必要という話を聞いたことがある人もいると思いますがその話をちょっとします

struct A
{
    A() = default;

    ~A() 
    {
            std::cout << "A destructor" << std::endl;
    }
};

struct B:A
{
    B() = default;

    ~B()
    {
        std::cout << "B destructor" << std::endl;
    }
};

int main()
{
    {
        std::unique_ptr<B> a = std::make_unique<B>();
    }
    {
        std::unique_ptr<A> a = std::make_unique<B>();
    }
    return 0;
}

いまAのデストラクタはvirtualではありません。
このときの出力は

B destructor
A destructor
A destructor

になります。

非virtualデストラクタを持つ型からアップキャストした場合、破棄されるときに呼ばれるのは 基底classのデストラクタのみ になるので注意。
じゃあ基底classのデストラクタをvitualにすればいいじゃん? 確かにそうですがたとえば
std::vectorなどのような標準ライブラリのclassなどで変更がきかない場合もあります。
でも、vectorを拡張したいとか思ったことありませんか?

アップキャストせずに使えばもちろん問題はないですがそれでも間違えてやってしまう場合もないとはいえません。
(派生先のデストラクタが何もしてないなら最悪呼ばれなくてもいいっちゃいいのかな?)
そういう時、より安全に使うためにはprotected継承してあげるのがよくある例だったりします。

struct A
{
    A() = default;

    ~A() 
    {
            std::cout << "A destructor" << std::endl;
    }
};

struct B:protected A
{
    B() = default;

    ~B()
    {
        std::cout << "B destructor" << std::endl;
    }
};

int main()
{
    {
        std::unique_ptr<B> a = std::make_unique<B>();
    }
    {
        //std::unique_ptr<A> a = std::make_unique<B>(); これがコンパイルエラーになる
    }
    return 0;
}

こうすることで、そもそもアップキャストして使うことそのものをエラーにできます。 ちなみに、Siv3Dのs3d::Arraystd::vectorをprotected継承してます。

最後に、protected継承したということは、基底classでpublicだったものがすべてprotectedになるので 必要なものはusingしてあげるといいでしょう。

struct A
{
    A() = default;

    ~A()
    {
        std::cout << "A destructor" << std::endl;
    }
    void hoge() {}
};

struct B :protected A
{
    B() = default;

    ~B()
    {
        std::cout << "B destructor" << std::endl;
    }

    using A::hoge;

};

ハッカソンの感想

NITMic Advent Calendar4日目

昨日、第10回名工大ハッカソンinワンダープラネットが行われたのでその感想

名工大ハッカソンとは?

8時間という時間のなかで即席チームでテーマに沿ったゲームを作る
というイベントです

自分は前回まで運営を行っていたので久しぶりに参加側にまわりました
今回は初参加の人も多く来てくれて、イベントとして確実に盛り上がってきているのを感じました。

いつもはその名の通り名工大の教室を借りて行うのですが今回はクラッシュフィーバーなどで有名なワンダープラネットさんの会場を借りて開催されました。
社員の方に審査やメンターをしていただきました!

今回のテーマは「ワンアクション+ふる」でした

「ふる」の解釈の仕方はいろいろあって
雨が降る、シェイクする、いっぱい、古い、告白をふる、奈良県布留市など...

特に多かったのは
異性をふると捉えたチームでした
男や女を振り投げたりビンタしたりと言った感じでした

そんな中自分たちのチームは思いつく「ふる」をたくさん盛り込んだゲームを作りました。

f:id:mahou_ptr:20171204120157j:plain
f:id:mahou_ptr:20171204120219j:plain

上から色々なものが降ってきて
「ふる」ものは、ふるに
「ふるじゃない」ものは、ふらないに
振り分けていきます

例えば
☔は「ふる」なので、ふるに
☀は「ふるじゃない」なので、ふらないに
バットは「ふる」なので、ふるに
バスケットボールは「ふるじゃない」なので、ふらないに
と言った感じです

スマホでの操作も意識して作っていましたが時間が間に合わずPCでの成果発表となりました

結果はなんと優勝!

ハッカソンで優勝はたぶん初めてだったので普通に嬉しかったです

さいごに
今回で10回目となる名工大ハッカソンですが、毎回最後に言っているとおり本当に回を重ねる度に作品のクオリティが上がっているのを感じます
今回どこのチームも遊べる段階までいけていましたし細かいとこも手が回っていたように感じました。

今後も第11回へと続いていくと思うので今回参加されなかった人も興味があれば是非参加してみてください!
ほかの学校の方との交流にもなって刺激ももらえます!

PS. 帰りにミスタードーナツでタダ飯を貰い忘れたのがその日一番のショックでした

ブログを作って記事を書こう!

NITMic Advent Calenderが今日からスタート! 

1日目はマホウさんです。

今回、プログラマーだけでなく絵師さんや音屋さんたちも参加できたほうが良いと思って Adventer というサービスを使ってみたのですが、直接記事を書く機能が存在してなくて、リンクを与える形式になっているので、すでに自分の記事を書ける環境を持ってない人の場合少し手間がかかってしまいます。(最悪DropboxとかのURLでもいいんだぜ)

そこで、この際いっそ ブログを初めてみてはどうでしょうか? という話をします

この記事もまさに、はてなブログで書かれています。 他にも、AmebaとかFC2とか、名前くらいは聞いたことあるんじゃないかな?と思います
ちなみにYahooブログはオススメしません…

学んだことを記事として自分なりにまとめることで理解を深めたり、たんに趣味の話をしたり、日記を書いたり、使い方はいろいろあります。

でも、ブログを始めたからといって無理に書く必要はありません!
僕も全然ブログが続かない人です><
ふと思い立った時に情報を発信する手段として ブログは持っている分に損はない のです!

この記事を見てくれた君もブログを作って、是非カレンダーを埋めていってほしいぞい

もっと気軽に記事が書けるサービス知ってたら教えてください!

ちなみにプログラマーの場合

ブログを持たなくても

  • Qiita
  • Gist

等で気軽に記事をかけます

さいごに

今回NITMicでもやってみることになった「アドベントカレンダー」ですが、個人的な年末の楽しみになっていたりもします。
某専門学校もQiitaでOB,OGも含めたアドベントカレンダーをやっているので、いいなぁと思い老害でありながら勝手に作っちゃいました!
時期的には工大祭後早々でもあり、中間試験も忙しい時期でしょうが皆で技術の共有とかができるいい機会なので来年以降も続いていったらいいなぁと思ってたりします!

PS. 星のカービィバトルデラックス買って徹夜でやってたのと、カラフルトーンのアプデ準備でまる2日寝てない状態なのでくそねむいですzz
もう冬だけど秋アプデしました、よければどうぞ⇒ ColorfulTone

自作列挙型 enum to string メモ書き

自作列挙型を作っていますが

enumから文字列への変換をめちゃスマートに扱えるように実装できたと思ったがMSVCでしかコンパイルできないコンパイラ依存になってしまった

メモ程度にコードをあげておきます

 

#pragma once
#include<string>
#include<unordered_map>

#define EXPAND( x ) x
#define IE_FOR_EACH_1(_macro,e1)_macro(e1)
#define IE_FOR_EACH_2(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_1(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_3(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_2(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_4(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_3(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_5(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_4(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_6(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_5(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_7(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_6(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_8(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_7(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_9(_macro,e1,...) _macro(e1) EXPAND( IE_FOR_EACH_8(_macro,__VA_ARGS__) )
#define IE_FOR_EACH_10(_macro,e1,...)_macro(e1) EXPAND( IE_FOR_EACH_9(_macro,__VA_ARGS__) )

//必要次第追加
#define IE_GET_FOR_EACH(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,NAME, ...) NAME
#define IE_FOR_EACH(macro,...) EXPAND(IE_GET_FOR_EACH(__VA_ARGS__,IE_FOR_EACH_10,IE_FOR_EACH_9,IE_FOR_EACH_8,IE_FOR_EACH_7,IE_FOR_EACH_6,IE_FOR_EACH_5,IE_FOR_EACH_4,IE_FOR_EACH_3,IE_FOR_EACH_2,IE_FOR_EACH_1)(macro, __VA_ARGS__))

#define IE_MAPPING_ENUM_VAL(name) \
[]()\
{\
   struct Check\
   {\
       int v=0;\
       template<class... Args>\
       Check(const Args& ...args)\
       {\
           constexpr int size = sizeof...(args);\
           if constexpr(size == 1)\
           {\
               v = name;\
           }\
           if constexpr(size == 2)\
           {\
               int name;\
               v = name;\
           }\
       }\
   };\
   if constexpr(ie::detail::NameCheck(#name))\
   {\
       return Check(1).v;\
   }\
   else\
   {\
       return Check(1, 2).v;\
   }\
\
   return 0;\
}()

#define IE_MAPPING_TO_STRING(name) {IE_MAPPING_ENUM_VAL(name), ie::detail::MappingEnumString( #name )},

namespace ie
{
    namespace detail
    {
        struct Value
        {
            constexpr Value() = default;
            constexpr Value(const int& other) :
                value(other)
            {}
        protected:
            int value = 0;
        };

        constexpr bool NameCheck(const char* test)
        {
            for (int i = 0; test[i] != '\0'; ++i)
            {
                if (test[i] == '=')
                {
                    return false;
                }
            }
            return true;
        }
        std::string MappingEnumString(const std::string& str)
        {
            return str.substr(0, str.find('='));
        }
    }
}


#define INTEGER_ENUM(...)\
struct : ie::detail::Value{\
   using  _ENUM=enum { __VA_ARGS__ };\
   using Value::Value;\
   decltype(auto) operator +=(int value) { *this = this->value + value;    return *this; }\
   decltype(auto) operator -=(int value) { *this = this->value - value;    return *this; }\
   decltype(auto) operator *=(int value) { *this = this->value * value;    return *this; }\
   decltype(auto) operator /=(int value) { *this = this->value / value;    return *this; }\
   decltype(auto) operator %=(int value) { *this = this->value % value;    return *this; }\
   decltype(auto) operator ++() { *this = this->value + 1; return *this; }\
   decltype(auto) operator --() { *this = this->value - 1; return *this; }\
   decltype(auto) operator ++(int) { auto ret = *this; *this = this->value + 1; return ret; }\
   decltype(auto) operator --(int) { auto ret = *this; *this = this->value - 1; return ret; }\
   constexpr operator _ENUM()const{ return static_cast<_ENUM>(value); }\
   std::string to_string()const\
   {\
       static std::unordered_map<int, std::string> map\
       {\
           IE_FOR_EACH(IE_MAPPING_TO_STRING, __VA_ARGS__ )\
       };\
       if (map.find(value) == map.end())\
       {\
           return "Unknown:" + std::to_string(value);\
       }\
       return map.at(value);\
   }\
}

使い方は

using Example = INTEGER_ENUM(
    A,
    B,
    Default = A
);

int main()
{
    Example a = Example::Default;

    std::cout<<a.to_string();
//出力 A
    return 0;
}

とやるだけで非常にシンプルです。 INTEGER_ENUMマクロが無名構造体を生成してto_string()メソッドも自動生成してくれるというものですが MSVCのラムダ内ならメンバtemplateが使えることや、templateの文法エラーのチェックタイミングなどの関係でほかのコンパイラでは使用できません

ゲームジャムは楽しいよ

みなさんゲームジャムをご存知でしょうか?

限られた時間のなかで即席チームでゲーム開発するイベントみたいなものです!

 

僕は名古屋でハッカソンという名の実質ゲームジャムを運営していて、先日このイベントが行われました。

これが第9回目になるのですが40人を越える名古屋の学生が集まり、就活支援の方やゲーム会社の方にも協賛をいただいて盛り上がった一日になりました。

当日僕は運営をしていて作品は作っていないので見ててうずうずしていましたが、8時間という限られた時間のなかでどのチームも楽しそうに制作してるのを感じられました。

 

こーゆーイベントはなかなか見つからなかったりもするかもですが、いい経験にもなると思いますし、楽しいと思います。

特に2019卒の学生さん向けに今年の夏からも多くのゲーム会社がインターンだったりゲームジャムを開催すると思います。

是非みなさんも機会があればゲームジャムとかにでてみてはいかがでしょうか?

 

 

 

 

四分木空間分割やってみた

アクションゲーム作るマンだから、空間分割をやってみました。

参考サイトは大正義

http://marupeke296.com/COL_2D_No8_QuadTree.html

です。

f:id:mahou_ptr:20170322054803p:plain上のスクショだとA30とB30の判定で試した奴なので、速度差がわかりにくいですが、10000*10000で試したりすると多少早くなります

判定のチェック回数自体が減っているのは一目でわかりますね!

 

作ったclassとかは後日

曲と同期するためのclassを作る

音楽ゲームを作る時などに役立つ、曲と同期するための記事を書きました

qiita.com