夏休み1日目

まだ記録管理用のslackbot/アプリも作っていないのでここに記録することになります. 今日は何もしませんでした. @nonamea774 に水飲み鳥を送りつけました. あと,TensorFlowやってる人が多いのでやってみたいと思いました. 特定の絵師の特徴とかを機械学習させたら楽に絵師を検索できたりするのかな. 575とかダジャレとかも判定させたりしたいですね.

まとめ

今日は 9 時間寝ました.

朝6時に寝て昼3時ころに起きたでしょうか.

形式的な朝ごはん,昼ごはんは食べておりません.

昼過ぎに起きると体調はあまり芳しくない様子.

更に追加で22時から25:20まで3:20寝ました.

この睡眠は快適でした.

そりでは,無限に練りをしまつ.

夏休みに入りました

夏休みに入りました.

有意義に過ごしていきたいと思うので日記を描くことにしました.

とはいえ,日記に何をしたのかをインターネッツに書き込むことははばかられます.

ですので,何時間睡眠をとったか,だけを毎日記録していこうと思います.

…それならSlackBot作ってやったほうが早いですね.

じゃあそうします.

まとめ

今日は 9時間寝ました.

寝起きは辛く,快眠ではなかったです.

照明を浴びることにより徐々に目を覚ましました.

起床時刻は朝10時です.

それでは,よい眠りを

KMCとPiet,そして最強のPietの為にdllを動的にC#で読みこむ話

はじめに

この記事はKMC Advent Calendar 2015 18日目の記事です。 前回の記事はwalkureさんによる京大マイコンクラブと旅するわたし - (。・ω・。)ノ・☆':*;':*でした。

KMCID: murataです。
最近Pietのことしか考えてないのでこの記事を書いたら半年ほどPiet禁します。 タイトルの「C#でDllを動的に読み込む話」はC#とかいう難しい言語でちょっとよくわかりにくいので 先に簡単で分かりやすい言語であるPietの話から始めますね。

最近僕が描いたPiet

3つ程描きました。

あぁ^~心がぴょんぴょんするんじゃぁ^~とは (アァーココロガピョンピョンスルンジャァーとは) [単語記事] - ニコニコ大百科に、 他のプログラミング言語はいっぱいあるのにPietだけなかったので描きました。 「あ~心がぴょんぴょんするんじゃ~」と出力します。 Pietはプログラミング出来い人にも画像という冗長性の手段によってコードの意味を伝えられる素晴らしい言語なんです。

髪の毛で72を取ってそれを顔を縦横無尽に横断しながらCHIHAYAという文字列を作って出力し続けています。

gyazo.com
これはここに描いているとおりの文字列を出力するコードです。 好きな文字列をわかりやすく表現出来ますね。 Pietは柔軟にコードを手軽に描ける良い言語なんです。

今年のKMCとPietの活動を振り返る

この記事はKMCアドベントカレンダーなので、 一応今年(2015年)のKMCの大きなPiet活動を簡単に振り返ろうと思います。

時系列順にPiet活動を振り返る

  • 3月 Pietの統合開発環境(IDE)であるPidetPietのエディタを作った話が発表される
    • これにより、開発がスムーズになりPietの開発が加速されました。
  • 5月 Pietを描く新入生プロジェクト発足
    • KMCの新入生に初めてのプログラミングでPietを教える…正気の沙汰ではないですね。 kmc.hatenablog.jp
  • 8月 YAPCでPietの講座が部員によって行われる
  • 11月 NFでPietが展示される
    • NF(京大の学祭)でPietを展示しました。 文字でしかプログラミング出来ないという常識を吹き飛ばすのがなかなか新鮮なのか意外と好評でした。

KMCの部員が開発しているツールを探してみた

Pietの中間言語コンパイラ、テストユーティリティ、インタプリタIDE…十分な開発環境が用意されてますね。 ここまでPietの開発が進んでいるのはKMCだけではないでしょうか?

僕の考えた最強のPiet

こんなに夢のあるPietをさらに実用的な言語にしようと、 僕は二週間くらいかけて最強のPiet拡張を考案しました。 概要だけ言うと数字だけでなくスタックを積んだりDllを扱えて、 ゲームやWebアプリケーションを手軽に作れるようになる予定です。 @Noname774さんのサークルにその仕様書を寄稿させてもらったのでよければお手に取り下さい。

C#でDllを動的に読み込む

僕の考えた最強のPietはC#で作られたPidetをベースに作る予定なので、 同じくC#で実装します。 僕の考えた最強のPietではdllを読み込む機能を搭載する予定です。 そのためにまずはC#で動的にdllを読み込める必要があります。 今回の記事のメインはその読み込み方についてです。 静的に(つまりコンパイル前に予め)読み込むのなら、 DllImport属性を利用することで簡単に利用することが出来ます。 (解説は他所に譲ります)。 しかし、この方法ではコンパイル後にそれで定義していない新しいDllの関数を動的に呼び出すことは出来ません。 ではどうすればいいのでしょうか?

.Net製のDllの場合

.Net製Dll、つまりC#VB.Netで作成されたdllの場合は比較的楽に呼び出すことが出来ます。

public static object Load_DotNet_Dll(string dllpath,string ClassName ,string FuncName, object[] Params) {
    try {
        var t = Assembly.LoadFrom(dllpath).GetType(ClassName);
        var obj = Activator.CreateInstance(t);
        return t.GetMethod(FuncName).Invoke(obj, Params);
    } catch {return 0;}
}

(usingは省略しました)。 使うときには、

Load_DotNet_Dll("Plugins/TestDLL.dll", "TestDll.CsDll.LangA",new object[] { 5, "RA" });

このように文字列と引数の配列だけを用います。 これで動的に好きなdllを呼び出せるようになります。 (この例では自作DllをPlugins下にTestDLL.dllという名前で配置していて、 そのDll内で定義された、TestDll名前空間のCsDllクラスのLangA関数を引数 5 と "RA" で呼び出しています。) .Net製dllは型など色々な情報がそのまま入っているため、扱いが容易なのですね。

C製のDllの場合

C製のDll(kernel32.dll,winmm.dllなど)はちょっと手間が必要です。 関数ポインタを得る為に kernel32.dllからLoadLibrary,FreeLibrary,GetProcAddressを呼び出す必要があります。 さらに引数に応じた関数デリゲードは動的に作成しなければならないのでなんかめんどかったです。 デリゲードをジェネリックで作成すると一見成功するように思えますが、そうすると いざ使う時に型がジェネリックのままなので使うことが出来ないです。

C#でLoadLibraryを使用してアンマネージDLLを使用する - 閑古鳥 C# GetDelegateForFunctionPointer with generic delegate - Stack Overflow

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", SetLastError = true)]
internal static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

public static class DelegateCreator {
    private static readonly Func<Type[], Type> MakeNewCustomDelegate 
        = (Func<Type[], Type>)Delegate.CreateDelegate(
            typeof(Func<Type[], Type>),
            typeof(Expression)
                .Assembly
                .GetType("System.Linq.Expressions.Compiler.DelegateHelpers")
                .GetMethod("MakeNewCustomDelegate", BindingFlags.NonPublic | BindingFlags.Static));
    public static Type NewDelegateType(Type ret, Type[] Params) {
        Type[] args = new Type[Params.Length+1];
        Params.CopyTo(args, 0);
        args[args.Length - 1] = ret;
        return MakeNewCustomDelegate(args);
    }
}


public static object Load_C_Dll(string dllpath,string func , object[] Params) {
    try {
        var Types = Params.Select(arg => arg.GetType()).ToArray();
        IntPtr handle = LoadLibrary(dllpath);
        IntPtr fadd = GetProcAddress(handle, func);
        Type t = DelegateCreator.NewDelegateType(typeof(IntPtr), Types);
        object res = Marshal.GetDelegateForFunctionPointer(fadd, t).DynamicInvoke(Params);
        FreeLibrary(handle);
        return res;
    } catch { return 0; }
}

私達はこの関数を定義したのでもうこれからは、 Load_C_Dll("user32.dll", "MessageBoxA", new object[] { IntPtr.Zero, "Hello World.", "Caption", (uint)0 }) のようにすることでコンパイル後でも、実行中の好きな時に好きなDllを呼び出すことが出来ます!

まとめ

このDll機能を利用して僕は最強のPietを作るつもりなので乞うご期待ですよ。

ついでに宣伝

https://play.google.com/store/apps/details?id=com.Paradigm.Ikada https://lh3.googleusercontent.com/1QTRWS-ETw4ul_5SHEA5RjG0E49JrxsT-wIGhOxvUIJ_tgVIo9cgunlJet19O94Wffme=h900 最近運ゲー排除マインスイーパーをAndroidアプリにした話と市場に対する雑感 - DNEK's blogみたいに自作ゲームを宣伝するのが流行っているっぽいので僕も最近作ったパズルゲームのAndroid版を公開します。 よかったら遊んでステージ作れるんで投稿して下さい。

最後に

明日の記事は、Kazakamiさんによる「shellチャンネルについて」です。 好きなコマンドが何もかも気にせず好き放題打てる夢の様なチャンネルShellチャンネルの話ですね! 期待しています!!!!!

シェーダ周りを色々調べたのでまとめてみた

KMCでのグラフィックのプロジェクトでは、 毎回担当者が講座をします。 僕は今回担当でシェーダーについて調べてたので軽くブログに書こうかな ということで書きます。

Shader?

  • Shade(陰影)を持たせて立体的に魅せたりリアリティを持たせたりする技法
  • 物体の面の情報とか頂点の情報とかで色や頂点を操作出来るので応用方法は様々

応用例

  • トゥーンシェーディング

  • 水面の表現

    • 反射・水紋・屈折などを計算してリアルな水面を再現している
    • 例:World of Warships worldofwarships.com

基本的な仕組み

  • WebGL(ブラウザで高性能描画が出来るやつ)の解説サイトが凄く良かったです。 wgld.org
  • w020 ~ w024, w042 ~ w048 あたりを見れば基本は分かりますし、それ以外にも参考になるものはとても多いサイトです。

絵を描く時に活かす

どのくらいShaderを使うと変わるの

実際のゲームへの応用

Unityで活かす

CCDxLib72を使って過去に作ったゲーム3種をAndroidに移植してみた

はじめに

前回の記事で、Cocos2dxで動くDxLibの関数群のライブラリであるCCDxLib72を公開しました!
今回の記事は、それで実際にGooglePlayに出したところまで解説します!
chy72.hatenablog.com

完成品

最初に完成品を見せるのが一番だろうということで。

①GreedGreen

https://play.google.com/store/apps/details?id=suken.greedgreen
https://lh3.googleusercontent.com/fyqJneg92hJImrRrwKXALhyQpeXOn07YnSZ3-qDwI8ht03HSC_p55jPHMYJ9idDzq88=h900

高校生の後輩がDxLibで作成したゲームです。
全体的にすっきりとしていて、操作ももともとマウス操作なのでスマホにそのまま移植しても綺麗に動きました。
紹介する三作品の中で一番スマホで遊びやすくてオススメです。

②Celestial

https://play.google.com/store/apps/details?id=suken.celestial&hl=ja
https://lh3.googleusercontent.com/zyX1fGTCfVDCSXOdmCQHwB_3EkruLHJDsMYC-Fwflq2BNwBr3e-iQVao8_AbPmVGXA=h900

僕が高校3年の頃にDxLibで作成したゲームです。
とりあえずWindows版のまま殆ど手を加えずに移植したので、操作性・見やすさは難ありです。
(絵も音楽も自分で作ったのと、受験期だったという理由で、作品のレベルに関してはご容赦ください)

③日本史クイズ

https://play.google.com/store/apps/details?id=suken.historyquiz
https://lh3.googleusercontent.com/PA0aPALf8wZKA53tjPIDx8Gg8wm0H1dlU-SySnCvSa02ckgmUmU5A0grqoDx1n4qvQ=h900

これも後輩がDxLibで作成したゲームです。
操作はもともとマウス操作だったので、スマホにそのまま移植しても操作はできてよかったのですが、スマホの小さい画面では見づらいかもしれないです。

元となるゲームを用意

github.com
(残り2つの作品は、もともと自分が作ったゲームではない(後輩が作った)ので、コードを公開するのも気が引けるので…)
まずは、元となるDxLibで動くゲームを用意します。

移行

まずは、cocosのプロジェクトを作成します。
最初のHelloWorldSceneがAndroidでも動くところまでは自力でお願いします。
移行した時に躓いたところを中心に列挙します。

コードのリファクタリング

  • Data という名前の変数をもともと使用していました。しかしCocosにもDataというクラスはあるので、そのDataという変数を一括でcDataという名前に置き換えました。
  • ShiftJisでもともとコードを保存していましたが、DrawStringで文字化けが発生するのでUTF-8(コードはBOMあり、読み込むテキストファイルはBOMなし)に変更しました。
  • #define RED とかしていたのですが、それがCocosのColor3Bクラスの REDと競合したので sRED とかに変えました
  • windows.h(ShellExeCuteに利用)など、Windows専用のヘッダーはincludeしないようにしました
  • main.cpp というファイルを使っていたのですが、cocosのmain.cppと競合したので、main2.cppという名前に変更しました。

bmppng

BGMの読み込み

  • 内部ではSimpleAudioEngineというものを利用して音を鳴らしているのですが、メモリに先立って読み込めるのは確か10秒程度までの効果音なので、10秒以下の効果音を読み込む前に SetCreateSoundDataType(DX_SOUNDDATATYPE_MEMNOPRESS) を、10秒以上のBGMを読み込むときはSetCreateSoundDataType(DX_SOUNDDATATYPE_MEMPRESS)を宣言します。

ファイル入出力変更

  • 普通にfopenなどをしたいところですが、Resourcesに同梱してアプリに入れるデータは、読み込みしかできないこと、AndroidのManagerを利用してしか読み込めないということがあるので、それ専用の機能としたFileRead~~ の関数に書き換えます。
  • また、書き換えるデータ(セーブデータなど)は、専用の場所に新しくファイルを作成するため、専用の関数UserDatafopenにfopenを変更します。(移行は普通にfseekとかもできます)fopenをしたくない場合は、getUserDataPath()を利用して、書き換え可能なパスを取得して使います。

操作方法変更

  • Androidにはキーボードはないので、新たに作成したエミュレート用の関数を宣言します。
  • これが一番重要なのですが、ここが一番スマホとパソコンとの大きな違いなので、もともとマウスで操作するゲームをタッチ操作に置きかえるのならともかく、キーボードで操作するゲームをタッチしかないスマホに置きかえると、単純に置き換えただけでは操作性を激しく損なう(このゲームがよく分かる例)ことを注意してください。

ロジック変更

  • InitやCCDxStartやCCDxLoopを使う形に変更します。
  • ProcessMessage,ScreenFlipでループを作って利用しているコードがあると思いますが、CCDxLib72では、ProcessMessageに当たるものがなく、CCDxLoopを抜けるということでしかProcessMessageやScreenFlipすることができません。
  • そういう部分がもしもあれば、ロジックを考えて書き直すしかありません。(通常は、ゲーム全体として一つの大きなループでしかないと思うので、その場合は必要ありません)
  • 理由としては、cocos2dxの方へCCDxLoopを抜けたあとに制御を返して、他の処理(イベント処理やFPS制御やDxLibでいうProcessMessageや他のSceneの処理)をしてもらって描画するという形をとっているからです。
  • ProcessMessageに当たる関数を作成することも考えたのですが、それをすると他のcocos2dxの機能(Widgetなど)が使えなくなったり、バージョンアップで動かなくなったり、マルチプラットフォーム対応が難しくなったりしそうだったので、これに関してはご容赦ください。代わりにただのSceneとしてしかCCDxLibは存在しないので、他のcocosの機能は使い放題だと喜んでください!
  • メモ:この処理をうまく非同期にできれば、可能かもしれません、強い方、実践してください。

完成

以上の変更(cocosの機能に関する変換(png,BGM,UTF8),マルチプラットフォームに関する変換(fopen,Emulate),ProcessMessage)を行い、cocos compile -p android で、コンパイルして、Googleに3000円投げてアカウント開いてGooglePlayにapkを投げて必要事項を記入したらすぐ公開です!

思ったこと

DxLibで作成したゲームは、どうしてもPC用に最適化されていて、コードをそのまま写しただけだとどうしても操作性がやや難になってしまいます。画面も小さくなるので意識していないと見辛くなることもしばしばです。なので、このライブラリでは移植の大部分を手助けすることはできますが、根幹の操作性だとかユーザビリティというところまではどうしても対処できないということを思いました。
やはり、ユーザーのことを考えるなら、苦を覚悟して手をかなり加える必要があるのかもしれません

スマホ向けにDxLibのコードがそのまま動く! Cocos2dxで動かせるDxLib、「CCDxLib72」を公開します!

2017/10/25追記

DXライブラリ置き場 Androidアプリ開発の注意点など
公式でAndroid版が出たようなので、そちらを使用すべきです。
僕が作った以下で紹介するライブラリはもうメンテナンスされておらず、
今後もするかどうかも未定である点からも公式のものを使うべきです。
しかしながら、cocos2dxでラップした以下の版を使いたい方も
いるやもしれませんのでこの記事はこのまま残しておきます。


これは何?

Cocos2dxの機能でDxLibの関数群(現在72個)をラップしたものです。

何が出来るの?

DxLibは通常Windowsでしかビルド出来ません。
しかしこれを使えば、同じC++で書かれているcocos2dxを利用して、
DxLibのコードを殆どそのままでスマホ向け等にゲームをビルド出来ます!
使用許諾などはいらないので、好きに使ってください。

開発環境の整え方

リポジトリ https://github.com/Muratam/CCDxLib72 のReadMeに記入していますが、
例えばAndroidに向けてビルドする手順の概略としては、

  • python,cocos2dxをインストールして、cocos2dxのプロジェクトを新規作成する。
  • CCDxLib72 をダウンロードして Classesに入れて、同梱のButtonExample.pngをResourcesに入れる。
  • 書いたDxLibのコードをClassesフォルダに入れて、ゲームで読み込むファイルをResourcesフォルダに入れる。
  • 同梱のReadMe.mdを見ながらコードをマルチプラットフォーム用に書き直す。(例えばファイル入出力やユーザーの入力操作)
  • cocos2dxへの移行のヒントはReadMe.md にも書いてあります。
  • cocos compile -p androidAndroid向けにビルドで完成!

紹介スライド

www.slideshare.net

cocos2dxのui::Button で一つの画像で半透明とかするコード

cocos2dxのui::Button は割と便利なんですが、作成時の引数には(スプライトではなくて)画像の名前で指定します。
押していないときは半透明、押しているときはそのまま描画、みたいにするコードです。

gist.github.com