C++ / OpenSiv3D でゲームボーイエミュレータを作り始めてから 3 か月経ちました。私がはじめに目指していた、市販のゲームをいくつか動かしてみたいという目標を超えて、思っていたよりもたくさんの機能を実装することができました。
続きを読む →タグ: C++
C++でゲームボーイエミュレータを自作しています
今月から、C++とOpenSiv3Dでゲームボーイのエミュレータを作り始めてます。
エミュレータといえば、学生時代に友人がファミコンのエミュレータを自作していて、マッパーがどうのこうの言ってたのを思い出すのですが。そのころ自分はろくにプログラミングができなかったので、いったいどうやればエミュレータというものが作れるのか、資料を見せてもらっても何もイメージできなかったのを覚えています。
エミュレータ開発に少し興味はあったものの、それ以降はまったく情報収集せず時は過ぎ……。
そして最近になって、ゲームボーイエミュレータを自作している人の記事を見かけたのがきっかけになり、なんとなく自分でも作れるんじゃないかと思い始めて情報収集を始めました。
続きを読む →バレンタインにプロ生ちゃんのゲーム作りました
プロ生ちゃんが開催するバレンタインのイベント「プロ生ちゃんチョコプログラミングコンテスト」をTwitterで見かけたので、ミニゲームを作って参加してみました。
続きを読む →Siv3D+PokéAPIでクイズゲームを作りました
OpenSiv3D v0.6.6 + PokéAPI で「ポケモンフレーバーはかせ」というゲームを作りました。
続きを読む →Catch2で気軽にテストかける環境@Visual Studio 2019
忘れないうちに殴り書きしておこうと思います。
続きを読む →C++で定義したenumをそのままの名前でLuaで使いたい(Boost.Preprocessor)
例えばC++で次のように列挙体を定義して、そのままの名前でLuaスクリプト側でも使いたいわけです。
enum Enum1 { E1 = 0x200, E2, E3, E4, };
↓↓↓こう書きたい↓↓↓
if foo == E2 then bar() end
でもそれをやるには、定義した列挙体を全部Luaのグローバル変数として登録しなければなりません。
luabind::object g = luabind::globals(L); g["E1"] = E1; g["E2"] = E2; g["E3"] = E2; …
enum定義した後で、Luaの方にも登録しなければなりません。
列挙体を1個増やすと、ソースを2箇所直さないといけない…。
これをいちいちやるのは、列挙体がたくさんあるととても面倒なので、なんとかならないものかと思っていたのですが、Boost.Preprocessorを使って楽になりそうだったので試してみました。
C++ + Lua for WindowsでMetaluaを使う
C++へLuaを組み込んでいる場合にMetaluaを使用するやりかたがわかったのでメモしておきます。LuaはLua for Windowsの5.1.4を使っています。
ちなみにMetaluaというのは、Luaにマクロ等の拡張機能を追加できるものです。Lua for Windowsに最初から入っているのですぐ使用できます。
まずはMetaluaの文法に則ってスクリプトを書きます(とりあえず script.mlua とします)。このままでは実行出来ませんのでMetaluaでコンパイルします。コマンドプロンプトにて以下を実行します。
metalua script.mlua -o script.luac -v --no-runtime
※–no-runtimeパラメータは状況により付けたり付けなかったり
この”metalua”というのはLuaのインストール先にあるバッチファイルです。見つからないというエラーが出る場合はパスを通してください(Win7ならC:\Program Files (x86)\Lua とかですね)
パラメータ -o でコンパイル後のファイル名を決めています。-v は進捗状況を細かく見たいという指定です。
最後の –no-runtime ですが、これはコンパイル後のスクリプトが自動でMetaluaライブラリをロードしないようにするオプションです。これを付けないと、コンパイル後のスクリプトに require “metalua.runtime” が付加されます。その場合、今回はC++からLuaスクリプトを呼び出すという前提なので、C++側の実行ファイルと同じフォルダにMetaluaライブラリが一式揃っていないとエラーになってしまうので注意してください。もちろん、–no-runtimeを付けた場合は他の方法でMetaluaライブラリをロードしておく必要があります。自分はprecompiler.luaを使ってruntime.luaがロードしている3つのファイル(base.lua, string2.lua, table2.lua)をコンパイルしておきC++に組み込む形にしました。具体的にはLuaインストール先のluaフォルダで以下を実行します。
lua precompiler.lua -o metalua -l metalua/?.lua metalua/base.lua metalua/string2.lua metalua/table2.lua
するとmetalua.cとmetalua.hが生成されるのでC++プロジェクトに追加し、そのファイル内に定義されている関数をlua_open()の後くらいに実行することでライブラリをロードできます。
そしてmetaluaコマンドにより生成されたファイルを読み込み、luaL_loadbuffer(), lua_pcall()して無事実行できました。
Boost.Preprocessorを少しだけ使ってみる
使ったこと無いなーと思いまして、触り程度にちょっとだけ
例えば以下のように、ある一部分を除いてほぼ同じ内容の関数をたくさん定義しなきゃいけない場合
void test1() {
cout << "A" << endl;
}
void test2() {
cout << "B" << endl;
}
…(以下延々と続く)…
[/cpp]
Boost.Preprocessorのリファレンスをだらだら眺めながら、以下のように書いてみました。
ちゃんと上記のように展開されるようです。
[cpp]
#define SEQ1 (test1) (test2) (test3) (test4)
#define SEQ2 (A) (B) (C) (D)
#define MACRO(r,data,i,elem) \
void elem () { \
cout << BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(i,SEQ2)) << endl; \
}
BOOST_PP_SEQ_FOR_EACH_I(MACRO, _, SEQ1)
[/cpp]
BOOST_PP_SEQ_FOR_EACH_Iを使ってMACROをSEQ1の数だけ展開して、
そのMACROの中ではインデックスiを使ってSEQ2にアクセスする感じで。
STRINGIZEは、標準の#xみたいなやつですね。
今の自分には使う機会が思いつきませんが、いつか必要になった時のとっかかりになればという事で。
Seleneでドットサイズ2倍で描画したい
ドット絵のドット感を目立たせたいがために、グラフィックの1ドットを画面上では2×2ドット(とかそれ以上)の大きさで描画したい。
最初から2倍に拡大した画像を作るというのも一つの手ですが、あとから3倍に拡大表示したくなったりしそうです。例えばStudio PixelさんのGuxt(ガスト)というゲームでは1~5倍まで好きな拡大率を選ぶことができます。
ということで今回は、現在使用中のゲーム用ライブラリSeleneにて、320×240の解像度で描画したものを2倍に拡大して640×480で画面に出力する方法を書いてみようと思います。今回描画するものは2Dスプライトのみですが、ほかのもの(線とか)も同じやり方でなんとかなると思います。
※現在Seleneのサイトがいろいろとリンク切れしているみたいですが、ファイル自体は存在するみたいです。
Seleneライブラリは http://www.moon.sakuraweb.com/download/SeleneSDK-01.24l.exe からダウンロードできます。