MacOSX 上で Nebula Device 2 の build に挑戦中(1)

Nebula Device 2 は update.py を使用してビルド環境を生成する仕組みになっています。

例えば、

python update.py -build makefile nebula2libs nebula2tools nopengl

という指定をする事で、 makefile を使用するビルド環境を用意する事が出来ます。

Nebula Device 2 の描画システムは標準で DirectX9 を使用するのですが、gfx2 ライブラリを自分で用意することで他のシステム上に移植することが出来るようになっています。

幸いなことに OpenGL 用のモジュールが nebula2/code/contrib/nopengl に含まれているので、これを使用することで MacOSX 上でも Nebula Device 2 が動くようになりそうです。

実を言うと update.py で生成する Makefile に OSTYPE=darwin と指定する事で、 MacOS 上でのビルドが行えるようになっているのですが、 Nebula Device 2 自体が古いため、想定されているシステムは darwin8.0 ( MacOSX 10.4 ) までとなります。

ここは頑張らずに linux ( X11 + OpenGL ) の環境で build に挑戦してみることにします。

ソースコードの入手

まずは SourceForge からソースコードを入手します。

svn co https://nebuladevice.svn.sourceforge.net/svnroot/nebuladevice/trunk NebulaDevice2

あとは build するだけ…というわけにはいかず、依存するライブラリも用意する必要があります。

必要なものは以下のものとなります。

  • libogg
  • libvorbis
  • libtheora
  • sqlite
  • XQuartz

というわけで、まずはこれらを build する必要があります。

それぞれの build に関しては、以下のように -m32 を指定しておきます。( Nebula Device 2 内に 32bit 環境前提のコードが含まれている為。)

export CFLAGS="-m32"
export CPPFLAGS="${CFLAGS}"
export CXXFLAGS="${CFLAGS}"

…先は長そう。

ゲーム向きのマップ作成ツール

2Dゲームを作成するには、プレイヤーが動かすキャラクターや敵キャラクターの画像を用意する必要がありますが、それとあわせてそれらのキャラクターが活躍する舞台を用意してあげたいところです。

ゲームによっては、単なる一枚絵の場合もあるのですが、ゲームによっては見た目以上の情報が必要となります。

例えば、

  • 通過出来る
  • 触るとライフが減る
  • アイテムの隠し場所
  • ここまで来たらゴール

といったものがあります。

こういった情報を埋め込むには、手作業で頑張っても良いのですけど、見た目を確認しながらゲームに必要な情報を埋め込めるツールがあると便利です。

というわけで、 Tiled Map Editor というのを見つけたので使用してみました。

tmx こんな画面です。(メニューがさりげなく日本語化されていて嬉しい)

ブロック単位で画像を貼付けていく事が出来るだけでなく、オブジェクト毎にちょっとした値を書き込んでおく事も出来ます。出力は XML, CSV, JSON に対応してして、レイヤーを一枚の画像として出力する事も出来るので、わりと使えそう。

 

 

Nebula Device 2 のビルド方法 (win32)

The Nebula Device 2 というゲーム開発用ライブラリがあります。かなり古いライブラリで更新がとまっている[1. 後継ライブラリとして http://code.google.com/p/nebuladevice/ があります。]のですが、内部仕様が好みで使っています。

自分用のメモとして以下にビルド方法を記述してみたりして。

以下のソフトウェアをインストール

  • VisualStudio 2008
  • DirectX SDK June 2010
  • Python 2.7
  • wxPython
  • ドキュメントの生成を行う場合は、追加で以下も必要です。
    • doxygen
    • HTMLHELP Workshop

SourceForge からソースをチェックアウト

svn co https://nebuladevice.svn.sourceforge.net/svnroot/nebuladevice/trunk

依存するファイルを追加でダウンロード

Nebula Device 2 は幾つか依存するライブラリ[1. ogg と sqlite3]があります。自前で持ってきても良いのですが、SourceForge から以下の名前でダウンロードする事が出来ます。

  • nebula-vc8-deps-20070409.zip
  • mangalore が必要な場合は、追加で以下も必要です。
    • mangalore-vc8-deps-20070407.zip

nebula2/buildsys3/generators に vstudio9 用の設定を追加する。

_WIN32_WINNT=WINVER; を vcproj に書き出さないようにするためと、Visual Studio 2008 でも build が行える様に、以下の Python コードを追加で配置します。

[wpdm_file id=12]

update.py を実行

python update.py

みたいな感じで実行すると、 Nebula 2 Build System が立ち上がりますので、 vstudio9 を選択した後に、ビルドしたいものにチェックを入れます。

基本部分だけなら nebula2libs, nebula2tools のみにチェックを入れてから、 RUN ボタンを押します。

VisualStudio に DirectX SDK のパスを追加

  • #include <dxerr9.h> の箇所を #include <dxerr.h> に変更。
  • DXGetErrorString9 を DXGetErrorString に変更。

ソリューションを開いてビルド

正常にビルドが完了していれば、 build/vstudio9/inter フォルダにライブラリが生成され、 bin フォルダに実行ファイルが生成されます。

Windows の環境設定

VMWare 上に OS を導入した後、自分は以下の様なソフトウェアを導入しています。

VisualStudio 2008 Professional

そんなの入れて使いこなせてるの?みたいな気もしますけど、まずはこれを入れています。DirectX の開発や Python モジュールの作成であれば Express Edition でも良いのですが、ごく稀に Crystal Reports を使用する事もあります。

DirectX SDK June 2010

手持ちのライブラリが DirectX 9.0 ベースですので、こちらも必要になります。

Windows8 では、個別提供はされずに Platform SDK に纏められて提供されるようです。

Altap Salamander

愛用している二画面ファイラーです。

EmEditor

スクリプトの作成は大抵このエディタを使用しています。

Python 2.7.2

スクリプトを書く際は大抵 Python 言語を使用しています。世の中は Python 3 系なのかもしれませんが、手元のライブラリや組み込みで使用している Stackless が 2.7.2 なので、バージョンを合わせています。

  • ちなみにインストールしているライブラリは以下のような感じです。
    • setuptools
    • Python Image Library
    • PyOpenGL
    • wxPython

 

以前であれば、デザイン関係のツールとして CorelDraw もインストールしていたのですけど、現在は Mac に移行してしまったので、 Windows 環境にはプログラム関係がインストールされています。

VMWare Fusion5 に Windows7 をインストール

自宅で使用している PC は iMac 一台だけなのですけど、DirectX のアプリケーションを開発する時には Windows 環境が必要となります。

intel Mac であれば Boot Camp を使用することで Windows を導入する事が出来ますが、再起動が必要となるため、自分は VMWare を使用しています。

VMWare はエミュレータですので、 Boot Camp に比べると当然重くなってしまうのですが、いまのところ作成しているアプリケーションは動作してくれているので愛用しています。重いといっても、自分が使用するには十分な性能が出ています。

vmware_score エクスペリエンス インデックス は 4.7 でした。

OS のインストールよりも、その後の環境設定の方が大変だったり。

 

WordPress の Twitter 投稿用プラグインを導入しました

タイトルにあるように、 WordPress にプラグインを導入しました。

WordPress は Twitter 関係のプラグインが多数存在しているのですが、うちのサイトでは Social プラグインを導入しています。

はじめは Simple Tweet が良さそうに思えたのですが、実際に使ってみると自動投稿以外の設定が行えないため、自分の好きなタイミングで投稿可能な Social にしました。

……のですが、こちらもすこしばかり問題があります。

Version 2.7 を使用しているのですが、投稿時の文章の抜粋を作成する際に日本語の文字数を正しくカウント出来ずに、Tweet 時の文章が壊れてしまいます。(詳しく調べたわけではないのですけど、先頭 n 文字で切り出す処理を行っているらしき場所で、文字数ではなくバイト数をカウントしているのではないかと思われます。)

ブログ本文を投稿しない様にすれば問題はないため、件名のみを Tweet する設定で利用しています。

 

今日の RapidMiner

今日もすこしばかり RapidMiner を使用してみました。

前の記事ではデータが何も無いと言う事で Google Trends を使ってデータを生成していたのですけど、 Utility -> Data Generation に色々なデータをランダムに生成してくれる機能がありました。(しかも、チュートリアル用のサンプルデータも幾つか付属してます。)

というわけで…前回よりもまともなものを組んでみました。

s1

やっている事は、

  • Generate Direct Mailing Data を使用してデータを生成。
  • Naive Bayes, Naive Bayes (kernel), Decision Tree のモデル精度を比較。
  • Decision Tree を使用して学習モデルを生成後、別のデータを与えて正答率をチェック。

といったことをしています。

s2s3

自分が組み立てたプログラムでは、100件のサンプルを使ってモデルを生成し、別の100件の予測をしています。

(正解率は 85 〜 90% ぐらいでした。)

使い方がわかってくると面白いかも。

形態素解析を利用したウェブサービス

Twitter に形態素解析をしてくれるウェブサービスの事が流れていたので、自作の小説「魔法少女リリカルなのはA’s FanFiction」を試してみました。

説明によると、Yahooデベロッパーネットワークが公開している形態素解析を使っているようです。

結果は以下の様になりました。
地の文中心の文体のようです。
かな:漢字の比率は読みやすい範囲だと思われます。
1つ1つの文章の長さは平均的です。
読みやすいと思います。
文体やテンポにもよりますが、平均と比べやや副詞が少ないようです。
指示語によって文章がうまく流れています。
接続詞が多めに挿入されています。
文章運びがやや論理的かもしれません。
体言止めはほとんど使われていません。
連用中止法の使用頻度は平均の範囲内です。
自立語における名詞の比率は平均の範囲内です。
名詞比率は文章が説明的・要約的かどうかに関係します。
物事を形容する言葉と動きの描写の比率は平均的な範囲です。
MVRが低いと動き中心、高いと形容中心となります。

形態素解析については詳しくないのですけど、上の結果を読むと「平凡な文章だけど理屈っぽい、または説明的」といったところでしょうか。

あくまで解析なので、文章を構成する要素から判定しているだけなのでしょうけど、今読み返してみると情緒的なものはあまりなくて、状況をなぞっているだけな文章ではあるので、わりとあっているかも。

D3.js の動作確認が手軽に出来るサイト

D3.js の動作を比較的簡単に確認出来るサイトを見つけたので、覚え書きとしてリンク。

Tributary

D3.js に特化した jsdo.it といったところでしょうか。

Rickshaw

時系列で並んだデータをプロットするのに適したライブラリです。 D3.js を直接使用するよりも容易に利用する事が出来ます。

Nvd3

こちらも D3.js を使用したライブラリです。

D3.js でここ10年間のアニメ放送日をプロット

今日も D3.js で遊んでみました。

前回と同じく Example に掲載されている CalenderView そのままです。

 今回は動かないデモ

上図の様な表示は、数年間分の情報をまとめて表示するのに便利ですので、

一年間をプロットするカレンダー表示を使用して

  • TV放送開始(赤)
  • 映画(緑)
  • OVA等の発売

を10年分表示させています。(データは .lain を参考にしました。カテゴリ分類はちょっと適当かもしれません。)

こうやってみると、やはり番組改編期に集中しているのがよくわかります。

前述したページでは、 2000年(74本)から2010年(187本)に増えているのですが、CalenderView をそのまま使用しただけでは、アニメの放映数をうまく表現出来ていないですね。今回の様な場合は、同日に放送する番組数に応じて色を濃くする、といった処理をするのが良さそうです。

D3.js を使ってみる。

データを視覚化すると、よりわかりやすい説明が出来るようになったり、いままで見えなかったものがより見えるようになります。

そういった用途に便利なライブラリのひとつに Data-Driven Documents というものがあります。D3.js は JavaScript ライブラリとして提供されていて、様々なデータを視覚化する際の手助けをしてくれます。

描画ライブラリですので、JSONを渡すだけで奇麗なチャートを描画してくれるわけではなく、どんな図を描くかはSVG等を使用して自前で行う必要があります。

使えると便利だと思うのですが、使えるようになるまではかなり時間がかかりそうです。そんなわけで、まずは既存のコードをいじってみる事にして Les Misérables Co-occurrence のデモを使って遊んでみました。

 実際に動くデモ

上の図は、魔法少女リリカルなのは A’s -THE GEARS OF DESTINY- の対戦カードを表示させてみたものです。左上のリストボックスを使用する事で「名前」「対戦数」「グループ」で並び替える事が出来ます。

ちなみにグループは以下の様にしてみました。

  • 時空管理局
  • フローリアン姉妹
  • 王様とその仲間
  • 八神家
  • 別シリーズ[1. Vivid, Force]の登場人物
  • その他[2. リニスとプレシア]

データ入力に間違っていなければ、八神家同士(ユーリを除くと王様たちも)では戦ってないんですね。

さすが仲良し家族?

CherryPy を CGI として実行する方法

Python でウェブアプリケーションを作成する方法というのはたくさんあります。

私が好んで使用しているのは Pyramid(Pylons) や Zope なのですが、もっと小さなアプリケーションを作成、言ってしまえば1ファイルで完結してしまう様なものを作るにはちょっと大げさすぎる気もしています。

CGI として Python スクリプトに実行権限を与えてやるのが最も簡易的な方法なのですが、 Python の場合は WSGI という機能があり CGI で直接呼び出すよりも、より良い方法が存在しています。

CGIでの呼び出し
print "Content-type: text/plain"
print
print "Hello World!"
 wsgiでの呼び出し
#!/usr/bin/env python
import wsgiref.handlers

def application( environ, start_response ):
  start_response( "200 OK", [ ( "Content-Type", "text/plain" ) ] )
  return [ "Hello World!\n" ]

if( __name__ == "__main__" ):
  wsgiref.handlers.CGIHandler().run( application )

コードは長くなっていますが、 wsgi の方が単純な標準入出力を返すよりもプログラミングらしいかと思います。

CherryPy

と、前置きが長くなってしまいましたが、 CherryPy という Python モジュールで作成したアプリケーションを CGI で実行したい、という話です。

CherryPyの例
#!/usr/bin/env	python
# -*- coding: utf-8 -*-
#
# ------------------------------------------------------------------ import(s)
import	sys
sys.path.append( "./eggs/CherryPy-3.2.2-py2.7.egg" )
sys.path.append( "./eggs/Jinja2-2.7_devdev_20121117-py2.7.egg" )

import	wsgiref.handlers
import	cherrypy
import	jinja2

# ------------------------------------------------------------------ global(s)
oCJinja2Env	= None

# ------------------------------------------------------------------- class(s)

# ----------------------------------------------------------------------------
##
#
class Test( object ):

	@cherrypy.expose
	def index( self ):
		oCTemplate	= oCJinja2Env.get_template( "index.jinja2" )
		return( oCTemplate.render() )

if( __name__ == "__main__" ):
	global	oCJinja2Env

	oCJinja2Env	= jinja2.Environment( loader = jinja2.FileSystemLoader( "res/templates" ) )

	wsgiref.handlers.CGIHandler().run(
		cherrypy.Application( Test(), script_name = None, config = None )
	)

# ---------------------------------------------------------------------- [EOF]

上記のようにすると、 CherryPy を使用したウェブアプリケーションを CGI として実行する事が可能になります。

でも今は Amazon Web Services や Windows Azure などを利用するのが一般的かもしれませんので「CGI だけでなんとかしなければ…」といった場面は少ないかもしれません。

今日の NodeBox

単純に乱数をプロットしているだけのプログラムです。

自分が Python コードを記述するときは from を使用することがほとんどないのですけど nodebox.graphics とあちこちに記述するのはさすがに冗長すぎるかも。

#!/usr/bin/env	python
# ============================================================================
# ------------------------------------------------------------------ import(s)
import	sys
import	nodebox.graphics

# ------------------------------------------------------------------- param(s)

# ============================================================================
##
#
def draw( oCCanvas ):

	nodebox.graphics.background( 0, 0, 0, 0.1 )

	nodebox.graphics.stroke( 1, 1, 1, 1.0 )
	nodebox.graphics.strokewidth( 1 )
	nodebox.graphics.fill( 0, 0, 0, 0 )

	nodebox.graphics.rect( 160, 120, 320, 240 )

	nodebox.graphics.line(   0, 240, 640, 240 )
	nodebox.graphics.line( 320,   0, 320, 640 )

	nodebox.graphics.fill( 1, 1, 1, 1.0 )

	for n in range( 32 ):
		nX		= nodebox.graphics.random( 320.0 ) + 160
		nY		= nodebox.graphics.random( 240.0 ) + 120
		nSize	= nodebox.graphics.random(  32.0 )

		nodebox.graphics.push()
		nodebox.graphics.translate( nX, nY )
		nodebox.graphics.ellipse( 0, 0, nSize, nSize )
		nodebox.graphics.pop()

# ============================================================================
##
#
def main():

	nodebox.graphics.canvas.name	= "Demo02"
	nodebox.graphics.canvas.fps		= 60
	nodebox.graphics.canvas.size	= ( 640, 480 )
	nodebox.graphics.background( 1, 1, 1, 1 )

	nodebox.graphics.canvas.run( draw )

if( __name__ == "__main__" ):
	main()

# ---------------------------------------------------------------------- [EOF]

サークルと全く関係ない情報が増えてきたから、トップページからは外した方がよいかも…と思ったら、標準では記事のフィルタリングって出来なそう。

 

今日の NodeBox

NodeBox のチュートリアルを少しばかり書き換えただけなので、コード自体には面白みに欠けるかも。

#!/usr/bin/env	python
# ============================================================================
# ------------------------------------------------------------------ import(s)
import	sys
import	nodebox.graphics
import	nodebox.graphics.physics

# ------------------------------------------------------------------- param(s)
oCFlock			= None

# ============================================================================
##
#
def draw( oCCanvas ):
	global	oCFlock

	nodebox.graphics.background( 1, 1, 1, 0.25 )

	oCFlock.update( cohesion = 0.05 )

	nColor	= 0
	for boid in oCFlock:
		nodebox.graphics.push()
		nodebox.graphics.translate( boid.x, boid.y )

		fScale	= boid.depth * 2.0
		if( fScale < 0.75 ):
			fScale	= 0.75

		nodebox.graphics.scale( fScale )
		nodebox.graphics.rotate( boid.heading )

		nC	= nColor % 3
		if( nC == 0 ):
			nodebox.graphics.fill( 1, 0, 0, 0.25 )
		elif( nC == 1 ):
			nodebox.graphics.fill( 0, 1, 0, 0.25 )
		elif( nC == 2 ):
			nodebox.graphics.fill( 0, 0, 1, 0.25 )

		nodebox.graphics.ellipse( 0, 0, 16, 16 )
		nodebox.graphics.pop()

		nColor	+= 1

# ============================================================================
##
#
def main():
	global	oCFlock

	oCFlock				= nodebox.graphics.physics.Flock( 64, 0, 0, 640, 480 )
	oCFlock.sight	= 640

	nodebox.graphics.canvas.name	= "Demo01"
	nodebox.graphics.canvas.fps		= 20
	nodebox.graphics.canvas.size	= ( 640, 480 )
	nodebox.graphics.canvas.run( draw )

if( __name__ == "__main__" ):
	main()

# ---------------------------------------------------------------------- [EOF]

単純な描画を行うにはかなり適しているかも。

 

NodeBox for OpenGL

pyglet について調べていたら NodeBox for OpenGL というライブラリがあるのを知りました。 NodeBox でやる事を Python ライブラリの形で実装しているようで、 pyglet を直接使うよりも便利そう。

ちなみに NodeBox というのは、ビジュアルプログラミング環境の一つで、データを可視化したり VJ 素材を作成したりするのに利用するソフトウェアです。(Mac でいうと Quartz Composer が近いかもしれません。)

というわけで、まずは pyglet と NodeBox for OpenGL による開発環境を用意することに。(ちなみに手元の環境は MacBookPro)

virtualenv, virtualenvwrapper

単純にモジュールをインストールしてしまっても良いのですけど、 easy_install や pip を行うと、 Python のライブラリフォルダにモジュールが入ってしまいます。

一時的な環境構築の場合は、環境を分離したいところ。

というわけで virtualenv を入れる事で環境を切り替えられるようにします。

easy_install virtualenv
easy_install virtualenvwrapper

インストール完了後は、.bash_profile あたりに以下の様な記述を追記します。

export WORKON_HOME=~/vEnv
source /usr/local/bin/virtualenvwrapper.sh

準備が出来たら、 新しくターミナルを開くか bash .bash_profile 等で設定を反映させて、作成した環境の名前を指定してやります。

Mizunagis-MacBook-Pro:~ mizunagi$ mkvirtualenv --system-site-packages NodeBox
New python executable in NodeBox/bin/python
Installing setuptools............done.
Installing pip...............done.
virtualenvwrapper.user_scripts creating /Users/mizunagi/vEnv/NodeBox/bin/predeactivate
virtualenvwrapper.user_scripts creating /Users/mizunagi/vEnv/NodeBox/bin/postdeactivate
virtualenvwrapper.user_scripts creating /Users/mizunagi/vEnv/NodeBox/bin/preactivate
virtualenvwrapper.user_scripts creating /Users/mizunagi/vEnv/NodeBox/bin/postactivate
virtualenvwrapper.user_scripts creating /Users/mizunagi/vEnv/NodeBox/bin/get_env_details
(NodeBox)Mizunagis-MacBook-Pro:~ mizunagi$

次回の利用時からは、 workon NodeBox と入力する事で環境を切り替える事が出来ます。

pyglet

自分の環境 ( Mac OS X 10.7.5 ) では、easy_install pyglet でインストールを行っても OSError が発生してしまうため、手動でインストールする事にします。

以下のURLを参考にしたのですが、そのままだと setup.py になぜか cocoa が指定されていないため、インストールしても動作しません。( 2012-10-27現在)

ですので、 hg checkout cocoa-port を行った後に setup.py を開き、 pyglet.window.cocoa を Packages に追加しておきます。

そんなこんなでひとまず動作するようになりました。(GUIモジュールが正常に動作していないようにみえるけど…)

2012-10-28追記

NodeBox for OpenGL の GUI モジュールではなくて、 pyglet の input に問題があるみたい。

バックアップを兼ねて作成した egg ファイルはこちら。

nodebox_opengl-1.7-py2.7.egg

[wpdm_file id=1]

pyglet-1.2dev-py2.7.egg

[wpdm_file id=2]

 

ちょっとした描画を行うプログラム

簡単な描画を行えるプログラムを作る必要が出てきたので、以前使用したことがあるライブラリを調べなおしてみることにしました。

描画といっても線を引く程度ですので、 Windows であれば GDI を使用すれば(今だと Windows Presentation Foundationかも)済んでしまいそうですけど、使い慣れた言語を使用したいところ。

そんなわけで、使用経験があるのは PyGame と wxPython なのですが、今回の目的には pyglet も向いていそう…とかなんとか言っているうちに時間がなくなって、 OpenGL か Irrlicht というのがわりといつもの(ダメな)パターンだったり。

 

技術評論社「間違いだらけのソフトウェア・アーキテクチャ」

表紙がオライリー風味というだけで買ってみました。

中身は会話形式で記述されていて、軽く読めるのが嬉しい。

この本の登場人物が

  • シニア・マネージャ
  • 宇宙人
  • アジャイル教の教祖
  • IT雑誌の記者
  • SE
  • 新人

といった面々だけど、誇張されている部分があるとはいえ結構それっぽく感じてしまうようなしまわないような…

UML や ER 図を作成する事はあるけど、 VDMSPIN は使用したことがないなぁ。便利そうな気はするけど、まずは開発者間の共通認識として利用できる状況がつくりだせないと難しいかも。そういった点からは DSM は導入しやすそう。

どちらかと言えば自分も古くさい側の人間だし、主流の開発手法には疎いから、笑われる側になってしまうのも時間の問題かもしれないな。

 

ソースコードのハイライト表示

コードハイライトをするためのプラグインを導入してみました。(コード自体は適当なものを貼り付けています。)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import csv

oCSV = csv.reader( open( "filename.csv", "r" ), )
listResult = []

for tplRecord in oCSV:
  strLayout = tplRecord[ 0 ]
  strCircle = tplRecord[ 1 ]
  strWriter = tplRecord[ 2 ]
  strURL = tplRecord[ 3 ]
  strURL = strURL.strip()
  listResult.append(
    '{ "layout" : "%s", "circle" : "%s", "writer" : "%s", "url" : "%s" },' % (
      strLayout,
      strCircle,
      strWriter,
      strURL,
    )
  )

listResult.sort()

for strData in listResult:
  print "\t\t" + strData

個人的には派手すぎるハイライト表示に感じるけど、ひとまずはこれで良いかな。