2011年09月29日

BMAPCHAR

やる気を奪うマンドクセな所からやっつけていくことにした。

まず、BMAPCHAR。saiで描いた。当然フルカラー。256色?何それ?
20110929.png

フルカラー対応のドット絵ツールとして、edge2とGraphicsGaleを試してみたんだけど、カラーサークルが無いので、色を作るのマンドクセということでsaiで描いた。
マップエディタにチップ番号表示機能があると便利なので追加した。

まだチップの継ぎ目がガタガタなので、そこは流石に直すつもりだけど、まあBMAPCHARはもう基本これで!次!

FieldMap。これもsaiで。
FieldMap.png

キャラチップは多分saiじゃなくてedge2かGraphicsGaleで行くと思う。
posted by owatsalt at 21:11| Comment(14) | TrackBack(0) | OpenFaren

2011年06月05日

マルチディスプレイ環境でViXで大きな画像を開いたとき

ファーレントゥーガにかすりもしていない日記。

自炊(書籍の電子化)をする時、ViXで画像の確認をするのだが、マルチディスプレイ環境で大きな画像を開くと、思い切り画面外にはみ出す大きさのウィンドウを出してくれる。

ViXが開発されたのはマルチディスプレイが珍しい時代だったのだろう。仕方がない。

といって画像を開く度にウィンドウサイズを直すのも面倒。

というわけで

// finvixwin.cpp
#include
#include
#include
#include

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
 LPRECT prect = reinterpret_cast(lParam);
 CHAR text[256];
 if(GetWindowText(hwnd, text, sizeof text)){
  if(std::strstr(text, "- ViX") != NULL){
   MoveWindow(hwnd, prect->left, prect->top, prect->right - prect->left, prect->bottom - prect->top, TRUE);
  }
 }
 return TRUE;
}

int main(int argc, char **argv)
{
 if(argc != 5){
  std::printf("usage:%s \n", argv[0]);
  exit(1);
 }
 RECT rect;
 int w, h;
 if(sscanf(argv[1], "%d", &rect.left) != 1 ||
  sscanf(argv[2], "%d", &rect.top) != 1 ||
  sscanf(argv[3], "%d", &w) != 1 ||
  sscanf(argv[4], "%d", &h) != 1){
  std::printf("failed to get args (invalid number format?)\n");
  exit(1);
 }
 rect.right = rect.left + w;
 rect.bottom = rect.top + h;

 for(;;){
  if(!EnumWindows(EnumWindowsProc, reinterpret_cast(&rect))){
   std::printf("failed to EnumWindows()\n");
   break;
  }
  usleep(50);
 }
 return 0;
}


これをcygwinで

gcc -mwindows fixvixwin.cpp -lstdc++ -luser32 -o fixvixwin.exe

とビルドして


./fixvixwin.exe 32 32 1024 800

と実行するとViXの子ウィンドウが(32,32)の位置に1024x800の大きさで移動する。
実行している間、50ミリ秒ごとに全ウィンドウを検索してタイトルに「- ViX」が含まれるウィンドウを移動させるプログラム。おお泥臭い。

多分フリーソフトで同じようなのはあると思うんだけど、以前にTeraTermがデスクトップ外にウィンドウを開きなさる問題を解決するために作ったプログラムがあったので流用してみた。
posted by owatsalt at 15:17| Comment(0) | TrackBack(0) | OpenFaren

2011年05月05日

チッププレビュー

プレビュー機能の経過。
F5キーでシナリオデータをリロードできるようにしたので、チップ画像とマクロを編集しながらF5キーを押してプレビューを確認できる。
20110505.png

しかしつながるように並べるのが面倒。あらためて分かるあとあとさんの偉大さ。
プレビュー機能じゃなくて確認用マップを1つ用意した方が良いかもしれないが、
シナリオを作りつつ適当にやりやすい方法を考えていきたい。
posted by owatsalt at 20:14| Comment(0) | TrackBack(0) | OpenFaren

2011年04月23日

マップエディタ

ファーレントゥーガのシナリオのグラフィックを描くとき、やる気は
顔絵>キャラのドット絵>>(超えられない壁)>>地形のドット絵
という感じになると思う。

とはいっても地形のドット絵作成は避けて通れないので、
マップエディタに地形プレビュー機能を付けてドット絵作成を楽にする方向で(そういうツールはもうあるのかもしれないけど)。
20110423.png

これは隣接する地形チップが自然に繋がっているかを確認する機能。

この機能のミソは

function mapchip_preview()
 local chipw,chiph = api_get_mapchip_size()

 api_draw_mapchip_preview(chipw*2 + chipw/2, 0, 32) -- 荒れ地 右下:草原
 api_draw_mapchip_preview(chipw*3 + chipw/2, 0, 33) -- 荒れ地 左下:草原

 api_draw_mapchip_preview(chipw, chiph, 20) -- 荒れ地
 api_draw_mapchip_preview(chipw*2, chiph, 22) -- 左:荒れ地 右:草原
 api_draw_mapchip_preview(chipw*3, chiph, 1) -- 草原
 api_draw_mapchip_preview(chipw*4, chiph, 24) -- 左:草原 右:荒れ地
end

こういうマクロ(Luaスクリプト)で表示しているという点。

すなわち、BMAPCHAR画像のチップの並びがどうあろうとも、シナリオ作成者がマクロを編集して好きなようにプレビューに並べられるという感じで。

で、以前に触れた、マップの自動整形機能もマクロで実現すれば、BMAPCHAR画像にチップを追加した時もシナリオ作成者がマクロを編集して自動整形機能を拡張できるという感じになると。

とは言ってもまずはデフォルトシナリオのBMAPCHARをきちんとプレビューや自動整形できるようにしないと。
posted by owatsalt at 19:55| Comment(0) | TrackBack(0) | OpenFaren

蔵書検索

OpenFarenにもファーレントゥーガにも関係ない話題で申し訳ないのだけど、日記のような感じで。

自炊(書籍・漫画の電子化)を趣味にしているのだが、文庫本などは本で読むよりもKindleで読んだ方が楽なので、読んでない本でも電子化してしまう。
そうするとブッ○オフに行った時などダブリ買いしてしまう恐れがあるので、出先から自宅にある本を検索したい。

そこで、次のようなシステムを作ってみることにした。

・適当なGMailのアカウントを作る。
・蔵書を検索したい時は携帯からそのGMailアカウントに検索キーワードをメールする。
・自宅サーバではcronで定期的に起動するスクリプトが、そのGMailアカウントからメールを受信して、蔵書一覧からgrepした結果を携帯に返送する。

まあWebサーバとかにすると、認証とかセキュリティを考慮しなきゃいけないの('A`)マンドクセなのでこのような形態に。

Perlで適当に作ってみた。
findbook.pl

設定ファイル「findbook.txt」をこんな感じで書く。booklist.txtにはUTF-8(BOMなし)で書籍名と著者名が書いてある感じで。

SmtpServer=smtp.gmail.com
Pop3Server=pop.gmail.com
User=oreoreore
Password=orenopasswd
From=oreoreore@gmail.com
Accept= orenokeitai@doftbank.au.jp , orenopc@someisp.com
BookListFile=/mydoc/booklist.txt


このようにcronで3分ごとに実行するように設定して動かす。

*/3 * * * * /home/ore/findbook.pl /home/ore/findbook.txt >>/home/ore/findbook.log 2>&1


GMailは平文のPOPとSMTPを許可していないので、送受信の方法をぐぐるのに結構時間を費やして、作るのに一日ぐらいかかった。
あと、最初、メールからデコードした文字列はUTF8フラグが付いていて、蔵書一覧ファイルから読み込んだ文字列にはUTF8フラグが付いていないので比較に失敗する。というミスをして結構はまった(スクリプトに binmode($fp, ":encoding(utf8)"); を入れていなかった)。

多分無いかと思うけどスクリプトの改変転載とかは自由です。というかぐぐったコードのコピペがかなりあるし。
「そんなん既にある」とか「こうした方がずっと便利」とか「おいおいこういうセキュリティホールがあるじゃねえかよ」といったご指摘などあればコメントしていただけると嬉しいです。
posted by owatsalt at 19:41| Comment(0) | TrackBack(0) | 日記

2011年02月26日

Gtk::RadioToolButton

こういう、どれか一つにチェックが付くようなメニューをgtkmmで出す時は、
20110226_2.png

こういう風にGtk::RadioMenuItem::Groupの変数を1つ宣言して、

Gtk::RadioMenuItem::Group m_groupEditTool;
Gtk::RadioMenuItem m_miEditCompatiblePen;
Gtk::RadioMenuItem m_miEditPen;
Gtk::RadioMenuItem m_miEditRect;
Gtk::RadioMenuItem m_miEditRectFill;


こういう風にGtk::RadioMenuItemのコンストラクタの引数にGtk::RadioMenuItem::Groupを渡してやればよい。

OfEditorWindow::OfEditorWindow() :
m_miEditCompatiblePen(m_groupEditTool),
m_miEditPen(m_groupEditTool),
m_miEditRect(m_groupEditTool),
m_miEditRectFill(m_groupEditTool)


さて、ではこういうどれか一つが押された状態になるボタンを作るときは?
20110226_1.png

メニューの時と同じように作れるだろう。と考えるのが当然ですね!

Gtk::RadioToolButton::Group m_groupEditToolButton;
Gtk::RadioToolButton m_btnEditCompatiblePen;
Gtk::RadioToolButton m_btnEditPen;
Gtk::RadioToolButton m_btnEditRect;
Gtk::RadioToolButton m_btnEditRectFill;


OfEditorWindow::OfEditorWindow() :
m_btnEditCompatiblePen(m_groupEditToolButton),
m_btnEditPen(m_groupEditToolButton),
m_btnEditRect(m_groupEditToolButton),
m_btnEditRectFill(m_groupEditToolButton)


不正解。

これだと、何故かそれぞれのボタンが独立したトグルボタンの動きをする。
つまりボタンがちゃんとグループになっていないのだ。

では、別の書き方なら?
Gtk::RadioToolButton::Groupを宣言するのをやめ、最初のボタンからget_group()した値を残りのボタンにset_group()する。

Gtk::RadioToolButton m_btnEditCompatiblePen;
Gtk::RadioToolButton m_btnEditPen;
Gtk::RadioToolButton m_btnEditRect;
Gtk::RadioToolButton m_btnEditRectFill;


Gtk::RadioToolButton::Group grp = m_btnEditCompatiblePen.get_group();
m_btnEditPen.set_group(grp);
m_btnEditRect.set_group(grp);
m_btnEditRectFill.set_group(grp);


これも不正解。

これだと、何故か最初と最後のボタンだけがグループになり、他のボタンは独立したトグルボタンの動きをする。

正解は、

Gtk::RadioToolButton::Group grp = m_btnEditCompatiblePen.get_group();
m_btnEditPen.set_group(grp);
grp = m_btnEditPen.get_group();
m_btnEditRect.set_group(grp);
grp = m_btnEditRect.get_group();
m_btnEditRectFill.set_group(grp);

こうでした。
これでちゃんと狙ったボタンがグループになります。

gtkmmは取っつきはいいんだけど、こういう理不尽な隠れノウハウが多いというか。
posted by owatsalt at 19:11| Comment(0) | TrackBack(0) | OpenFaren

2011年02月09日

レイアウト

パレットの縦置き横置き切り替えに対応してみた。
20110209.png

こういう2つの領域を分割表示する画面部品を、gtk+ではPanedと言うのだが、
縦置き用Panedと横置き用Panedを2つ作って、マップ表示領域とパレットを両方のPanedに入れ、
Panedの一方をhide()して他方をshow()すれば良いのかと最初は思ったのだけど、
それだと何故か両方のPanedが表示されなかった。

多分1つのWidgetを同時に2つのPaned(Container)に入れるのは駄目で、
Panedの切り替え時はちゃんと一方のPanedから中身をremove()して他方にadd()するべきみたい。
posted by owatsalt at 22:18| Comment(0) | TrackBack(0) | OpenFaren

2011年02月06日

マップエディタの方向性

マップエディタの開発を始めてからすごくやる気が出た。やる気と進捗は比例しないけどorz
ちなみに無駄にタブ型で違うシナリオのマップを同時に開けるようになっている。

マップエディタはMinGWのgccでビルドして動かせるので、eclipseで開発して時々Visual C++ 2008でビルドしてみるという感じ。
eclipseはあまり使ったこと無いんだけど、今の仕事がWebアプリの保守で、eclipseでJavaソースを扱うこともあるので、eclipseの機能について分からないことがあったら仕事の振りをして業務中に調べると言うことも可能……!

さて、バトルマップを作る作業はすごく大変そうなので、例えば海と荒れ地を適当に配置して範囲指定して「整形」コマンドを実行すると自動で整形できるようにしたい。だがしかしBMAPCHAR.BMPを見ても分かるとおり全て自動というのは不可能。なので大雑把には整形できて、細かい所は人間が直すという感じで。

それにしても街と城壁の「順番」が鬼門(ファーレントゥーガエディタのエリア編集でマップ上に番号が出るやつ)。これって多分あらかじめ壁や街の配置を決めておいて一気に描くのだろうけど……編集しやすくする方法が思いつかない。とりあえず同じように作るしかないか。
posted by owatsalt at 20:03| Comment(4) | TrackBack(0) | OpenFaren

Gtk::CheckMenuItem

まだこれっぽっちしか進んでいないマップエディタ。

20110206.png

この画像の「グリッド」のように、チェックが付くメニューはgtkmmにもGtk::CheckMenuItemという物がある。

ここは公式のExampleを見て欲しいのだが、
" <menuitem action='FileNewFoo'/>"

という風にメニューを定義する文字列を書いて
Gtk::UIManager::add_ui_from_string()
に渡せば簡単にメニューを作れる。

さて、Gtk::CheckMenuItemを作るには
" <checkmenuitem action='FileNewFoo'/>"

と書けばいいと思うでしょう。私もそう思って書いてみたら、


(ofeditor.exe:4356): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g-markup-error-quark
code : 3
what : 1 行目 99 文字目の予想外の開始タグ 'checkmenuitem'


というエラーになって通らない。
何で通らないのか!!と絶叫したいけど、通らない物はしょうがないので他の方法でチェックメニューを付けてみる。

結論から言えばこのような感じでGtk::CheckMenuItemを追加できる。

  Gtk::MenuItem* menuView = reinterpret_cast<Gtk::MenuItem*>(uimanager->get_widget("/MenuBar/MenuView"));

  if(menuView != NULL){
    Gtk::Menu::MenuList &menulist = menuView->get_submenu()->items();
    menulist.push_back(Gtk::Menu_Helpers::CheckMenuElem("Grid", sigc::mem_fun(*this, &OfBMapEditor::OnMenuGrid)));
  }

void OfBMapEditor::OnMenuGrid()
{
  printf("called");
}


結論だけ書くと簡単に見えるけど、この方法に辿り着くまで3〜4時間ぐらいかかった……!
大体何で最初の方法で通らないのよ……
Inkscapeというソフトもgtkmmを使っているので、ソースをダウンロードして参考にしようとしてみたけど、このソフトではまた別の方法でGtk::CheckMenuItemを使っていたので参考にならなかった。具体的にはこのソフトはgtk+のC言語文法の関数とgtkmmのクラスを織り交ぜて使っているので、イベントハンドラにクラスのメンバ関数(上記の例だとOfBMapEditor::OnMenuGrid())を登録する方法が分からなかったのだ。


別件で、gtk+にはGTK_IS_MENU()といったマクロがあって、ウィジェットを指すポインタが実際には何(メニューとかボタンとか)を指しているかを検査できるんだけど

gtk::Widget *w = xxx;
if(GTK_IS_MENU(w)){
}

と書いてしまうと、コンパイルは通るけど常にGTK_IS_MENU()の結果は偽になる。

正しくは

gtk::Widget *w = xxx;
if(GTK_IS_MENU(w->gobj())){
}

になる。

GTK_IS_xxxはgtk+のマクロであってgtkmmのマクロではないから、gtkmmの型のポインタを渡しても正しく動くわけがないのはとっても当たり前なんだけど、これで結構はまった。
こんな間抜けをやる人はあまり居ないと思うけど一応注意を喚起しておきたい。
(このブログにgtkmmで検索して来る人が割と居るので)
posted by owatsalt at 18:15| Comment(0) | TrackBack(0) | OpenFaren

2011年01月13日

Visual C++ 2008

前回の続き。
ビルドを速くしたいというわけで、Visual C++ 2008 Express Editionにしてみた。
そしてopenfaren本体のコンパイルオプションに /MP4 を付けてみると……
何と効果覿面、2005では3分も掛かったビルドが1分弱に!!

デュアルコアでこれなのだからクアッドコアならさぞかし……!

しかし実行してみるとwavのロードに失敗した。
Mix_LoadWAVがこんな感じのエラーになる。ぐぐるとファイルが無い時のエラーっぽい。
Mix_LoadWAV_RW with NULL src

何故失敗するのか分からないのでSDL_mixerを最新版にしてみたり試行錯誤したが、
結局はファイル名が日本語のファイルを読めない。ということが判明。

Visual C++ 2005の時は
std::locale::global(std::locale("japanese"));
しないと標準C++ライブラリのofstreamとかが日本語のファイル名を扱えない、
という問題があったが……2008で何か事情が変わったのか?

とりあえずエラーになる箇所に
std::locale::global(std::locale("japanese"));
を入れてみたが、特に変わらず。

ためしに日本語のファイル名をSJISで渡していたのを、utf-8に変換して渡してみると読み込みに成功するようになった。

まあ……いいでしょう……元々openfaren本体には、linux上で動かすときはファイル名をEUCやUTF-8で扱う機能が備わっていますからね……Windowsで扱うファイル名の文字コードを変えればよいこと……

ところでこんな動作をしてくれるからには文字コードがUTF-8のソースもちゃんとコンパイルできるようになったんでしょうね!?(Visual C++ 2005はちゃんとコンパイルできない)
posted by owatsalt at 23:18| Comment(0) | TrackBack(0) | OpenFaren