レベルのサムネイル自動生成(1)
ユーザーが自作レベルをSTEAM上で公開する場合、
一目でどんなレベルかを把握できるようなサムネ画像があると便利だ。
ということで、レベルを1枚の画像として表示するプログラムを作っている。
ひとまず、1つのセルを1ドットで表してみた。
ブログのために拡大しているが、もとは128x128の小さい画像だ。
ちょっと問題なのは、遊ぶ前からレベルの構造が見えてしまい、ネタバレになってしまう点。
もちろん、ユーザー側で任意の画像を用意したりできるようにできるつもりだけど、
労力無しでサムネが用意されたほうが良いだろう。
一度、サムネの役割をまとめてみる。
- サムネを見て、そのレベルを見て面白そうと思える。(STEAMからレベルを落とす場面)
- レベルの選択画面で、サムネを見て、レベルを識別できる。(ゲーム内でレベルを選択する場面)
- ネタバレにならないこと。(レベルを初めて遊ぶ場面・探索しきっていない場合)
こう考えると、ゲーム画面のスクショっていう選択肢があってもいいかも。
簡単にスクショをサムネにできる仕組みがあったらいいな。
画像生成に戻って、この画像の問題点は2つ。
- レベル構造が鮮明すぎて、ネタバレになってしまう。
- 画像を縦に並べるので、マップが広いと下が切れてしまう。
1については、画像をゆがませたり、上に汚れみたいなエフェクトをかけたりして、不鮮明にするとか?
結構手間かかりそうでやだなあ。
2については、複数の長方形(1つのマップ)をどううまく配置するかっていう課題だ。
検索すると、”長方形詰込み問題”として解法が出てくるけど、
まあ、今回はそんな大仰なもんでもないので、適当に詰め込んでみよう。
http://repo.lib.hosei.ac.jp/bitstream/10114/8970/1/13_s_m_nozawa.pdf
http://www.orsj.or.jp/~archive/pdf/bul/Vol.50_05_335.pdf
次回は、いい感じに配置できた画像を公開する予定。
EIN(米国納税者番号)の取得
海外でゲームを販売することになり、
EIN(米国納税者番号)が必要になった。
これを取得しないと二重課税になる。
つまり、アメリカで30%の源泉徴収をされ、さらに日本で税金を引かれてしまう。
アメリカの源泉徴収を回避するために必要。
すごくとまどったので、今後迷う人のためにまとめておく。
方法について
EINはIRS(内国歳入庁)で発行してもらう。
方法は以下のとおり。
# | 方法 | メリット | デメリット |
---|---|---|---|
1 | 電話 | 即時発行! | 英語でやりとり |
2 | SS-4を書いてFAX送信 | 英語での会話不要・手軽 | 届いたか確認できない・記入ミスの場合やり直し |
3 | SS-4を書いて郵送 | 英語での会話不要 | 届いたか確認できない・記入ミスの場合やり直し・面倒 |
3はメリットないので、1か2で迷うと思うが、1と2の合わせ技がよい。
SS-4を書いてから電話し、オペレーターからFAX番号を教えてもらい、そこに送る。
それでも多少の英語での会話が必要だけども。
僕は事前にFAXを送ってから電話したが、オペレーターが送信した文書を探せないので、これはNGだった。
SS-4の書き方
省略します。検索すると色々でてきます。
下記サイトからダウンロードできます。
Form SS-4, Application for Employer Identification Number (EIN)
国際電話について
アメリカへの国際電話なので料金に注意。
Skypeだと安い。
Skypeは、相手の国によって料金が決まるんだけど、
このときは、2.26円/分だった。
Skypeクレジット500円で十分。
国際FAXについて
僕の家はFAXが無かったので、ローソンのFAXを利用して送った。
電話中に外出して、その間待ってもらった。
これ、ちょっと迷惑だったかも。ごめんよ。。
家にFAXがあれば、その場で送るのがよい。
しかし、家庭用の電話は、国際FAXに対応していないものがあるらしいので注意。
また、インターネットFAXというのもあるようだけど、
月額とかだし、色々と調べた結果、やめておくことにした。(適当なこと書けないので、詳しい理由は書かない。)
まあ2の方法でもよいのかな。
返信が来ないとかのトラブルもあるようだけど、
期間的に余裕があるならば。
LeapMotionをHaskellで動かすための準備 その2
前回の続き。
今回はHaskellでLeapMotionを動かすところまでやる。
具体的には、HaskellでFFIを通してc++用のLeapMotoinSDKを使う。
まずは普通にc++でLeapMotionSDKを使ってみる。
step4.cc
#include <iostream> #include "Leap.h" using namespace Leap; Controller *new_controller(void){ return new Controller(); } void delete_controller(Controller *controller){ delete controller; } int num_hands(const Controller *controller){ return controller->frame().hands().count(); } int main() { Controller *controller = new_controller(); while(true){ std::cout << "num hands: " << num_hands(controller) << std::endl; sleep(1); } delete_controller(controller); return 0; }
Haskellから呼べるように、手の数を得るための関数を書いている。
LeapMotionのヘッダファイルを"include/Leap.h"に用意し、コンパイルする。
g++ step4.cc -I./include -o step4 libLeap.dylib
実行してみる。
num hands: 0 num hands: 0 num hands: 1 num hands: 1 num hands: 2 num hands: 0
手を検出して手の数が表示された。
では、これをHaskellで実行するように改造する。
先ほどのstep4.ccのメイン関数以外を抜き出して、extern "C"で囲って、wrapper.ccとして保存する。
wrapper.cc
#include "Leap.h" using namespace Leap; extern "C" { Controller *new_controller(void){ return new Controller(); } void delete_controller(Controller *controller){ delete controller; } int num_hands(const Controller *controller){ return controller->frame().hands().count(); } }
LeapMod.hs
{-# LANGUAGE ForeignFunctionInterface #-} module LeapMod where import Foreign.Ptr import Foreign.C data LeapController = LeapController data LeapFrame = LeapFrame foreign import ccall "wrapper.h new_controller" cNewController :: IO (Ptr LeapController) foreign import ccall "wrapper.h delete_controller" cDeleteController :: Ptr LeapController -> IO () foreign import ccall "wrapper.h num_hands" cNumHands :: Ptr LeapController -> IO CInt numHands :: Ptr LeapController -> IO Int numHands controller = do num <- cNumHands controller return $ fromIntegral num
そしてそれをmain関数からループ内で呼ぶコードを書く。
Main.hs
import Control.Monad import Control.Concurrent import LeapMod main = do ctrl <- cNewController forever $ do threadDelay $ 1 * 1000 * 1000 num <- numHands ctrl putStrLn $ "num hands: " ++ (show num)
controllerをdeleteする場所が無いのが気になるものの、とりあえずこれで準備はできた。
コンパイルしてみる。
g++ -c -I./include wrapper.cc -o wrapper.o ghc --make -main-is Main Main.hs -o ex_step4 libLeap.dylib -lstdc++ wrapper.o
実行する。
num hands: 0 num hands: 0 num hands: 1 num hands: 1 num hands: 2 num hands: 0
同じ結果を得ることができました。
これでHaskellからLeapMotionを触れることがわかりました。
あとは、適当にラッパーを充実させてやれば、色々できそうです。
LeapMotionをHaskellで動かすための準備 その1
HaskellでOpenGLを動かせてテンションがあがってしまったので、そのままLeapMotionも購入してしまった。この勢いで、Haskellで動かそうと思う。
でも大きな問題があって、LeapMotionのSDKの対応言語が、JavaScript、C#、Python、ObjectiveC、C++、JAVA(、その他)などで、Haskellがかすりもしていない。
色々調べたところ、下のような方法でできるかもということが分かった。
LeapMotionのライブラリを利用するラッパーをc++で作成し、それをHaskellからFFIで利用し、LeapMotionの機能を使う。
。。。本当にできるのか?
未知の世界すぎる。段階を踏んで成功に近づこう。
具体的には以下のステップとした。
- ステップ1
FFIを使ってHaskellからC言語で書かれたプログラムを利用してみる。
- ステップ2
FFIを使ってHaskellからc++で書かれたプログラムを利用してみる。
- ステップ3
図中の構造をシンプルなケースを作って試す。
- ステップ4
実際にLeapMotionのラッパーをc++で作成してHaskellから呼ぶ。
ステップ1
hoge.h
int square(int x);
HogeMod.hs
{-# LANGUAGE ForeignFunctionInterface #-} module HogeMod where import Foreign.C foreign import ccall "hoge.h my_square" c_square :: CInt -> CInt sqr :: Int -> Int sqr x = fromIntegral $ c_square (fromIntegral x)
そして、メイン関数で呼ぶ処理を書く。
ステップ2
FFIを使ってHaskellからc++で書かれたプログラムを利用
今度はC言語ではなくc++のプログラムをFFIで呼んでみる。
まず、クラスを使ったc++のプログラムを書く。
BigEaterは整数を食いまくる。
big_eater.h
class BigEater { public: BigEater(void); void eat(int x); int energy(void) const; private: int energy_; };
big_eater.cc
#include "big_eater.h" BigEater::BigEater(void) : energy_(0) {} void BigEater::eat(int x) { energy_ += x; } int BigEater::energy(void) const { return energy_; }
こいつを利用するためのラッパー関数を書く。
Haskellから直接クラスは生成できないから。(たぶん)
wrapper.h
#include "big_eater.h" extern "C" { BigEater* new_big_eater(void); void delete_big_eater(BigEater* big_eater); void eat(BigEater* big_eater, int x); int energy_of(const BigEater* big_eater); }
wrapper.cc
#include "wrapper.h" BigEater* new_big_eater(void) { return new BigEater(); } void delete_big_eater(BigEater* big_eater) { delete big_eater; } void eat(BigEater* big_eater, int x) { big_eater->eat(x); } int energy_of(const BigEater* big_eater) { return big_eater->energy(); }
Haskellでこれらを読み込めるようにする。
BigEaterMod.hs
{-# LANGUAGE ForeignFunctionInterface #-} module BigEaterMod where import Foreign.Ptr import Foreign.C data BigEater = BigEater foreign import ccall "wrapper.h new_big_eater" cNewBigEater :: Ptr BigEater foreign import ccall "wrapper.h delete_big_eater" cDeleteBigEater :: Ptr BigEater -> IO () foreign import ccall "wrapper.h eat" cEat :: Ptr BigEater -> CInt -> IO () foreign import ccall "wrapper.h energy_of" cEnergyOf :: Ptr BigEater -> CInt
メイン関数で使わせる。
Main.hs
module Main where import BigEaterMod main = do let ptrBigEater = cNewBigEater print . fromIntegral . cEnergyOf $ ptrBigEater ptrBigEater `cEat` 1 print . fromIntegral . cEnergyOf $ ptrBigEater ptrBigEater `cEat` 5000 print . fromIntegral . cEnergyOf $ ptrBigEater cDeleteBigEater ptrBigEater
コンパイルする。
g++ -c big_eater.cc wrapper.cc ghc --make -main-is Main Main.hs -o ex_big_eater -lstdc++ big_eater.o wrapper.o
実行する。
./ex_big_eater 0 1 5001
よしよし。
というか、newしたらdeleteしなきゃってのをhaskell使ってて気にするのはやっぱり気持ち悪い。
しょうがないんだけど。
ステップ3
シンプルなケースを作って試す
ステップ2のコードを流用し、BigEaterをライブラリとして作成し、ラッパーをコンパイルしてオブジェクトファイルを作り、Haskellから呼ぶ。
まず、BigEaterのライブラリファイルを作る。
g++ -dynamiclib big_eater.cc -o big_eater.dylib
これで big_eater.dylib が作成された。
次にwrapperのオブジェクトファイルを作成する。
g++ -c -o wrapper.o wrapper.cc
wrapper.oができた。
ghc --make -main-is Main Main.hs -o ex_big_eater big_eater.dylib -lstdc++ wrapper.o
実行ファイルができたので実行してみる。
./ex_big_eater 0 1 5001
よしよしよし。
これで、c++のライブラリをhaskellから利用できることが確認できた。
このライブラリをLeapMotionのものに変えて、ラッパーを書けばできそうな感触をつかんだ。
これ以降はまだ試していない。
長くなってしまったし、とりあえずここまでにしとこう。
今回は、以下のサイトを参考にさせていただきました。
FFI Introduction - HaskellWiki
HaskellとメタセコイアとOpenGL
Haskellでメタセコイア形式のモデルを解析してOpenGLで表示してみた。
なぜHaskellか
まあ趣味ですよね。
3Dプログラミングなら普通はc++ですよね。速いですもんね。
Haskellにはまった経緯なんですが、仕事でバグの出ないプログラムを探求してたら、参照透過性っていうキーワードに出会って、そのままずるずると純粋関数型ワールドに突入してしまったわけです。今では信者です。周りからはあいつ暴走してるよやばいよって思われてます。きっと。ちなみにOCamlも触ってみたんだけど構文がちょっとと思ってしまいました。たぶん慣れなんでしょうけどね。
メタセコイア形式のモデル読み込み
メタセコイアは和製3Dモデリングソフトです。昔触ったことがあったのと、独自形式の出力ファイルがテキストファイルであり読み込みやすそうなので、ひとまずこれを表示してみることにした。
HaskellのパーサーライブラリParsecを使って読み込みました。強力です。素敵です。
結果
まず、Haskellの公式チュートリアル(
OpenGLTutorial1 - HaskellWiki
)を写経して下のものができました。
次に、立方体にライトを当てて、
最後に、メタセコイアで適当なモデルを作ってレンダラ関数に食わせてひとまず完了。
リーゼントの顔っぽい何かです。実は出っ張ってる部分はリーゼントって呼ばないことを今知りました。ショックです。
ちなみに寄り目で見ると飛び出して見えます。
モデルの回転も視点の移動も、c++の時とほぼ同じようにできました。
ライティング(陰影付け)に関してはちょっと違いました。こちらの方がぶーたれてますね。
OpenGL and Haskell | Two Guys Arguing
参考にさせてもらいました。感謝。
まとめ
HaskellでOpenGLを扱うのは、c++とそんなに変わらない感覚でできることがわかりました。
ただ、大きいモデルを読み込んでみると、今は座標などをリストで扱っているため、当然のごとく重くなりました。配列で実装するなど工夫が必要そうです。
でも、重くならないような処理にとどめておけば、Haskellっぽい、というか関数型の特徴を生かしたプログラミングが許されるはずなので、高効率かつ柔軟な3Dプログラミングができて、プロジェクトががんがん進むんじゃないかと妄想中です。
まあとにかく、意外にあっさりいったので、このままLeapMotionとOculusRiftで仮想世界にまで突っ込んでみたいですね。
2013年のまとめとこれから
去年は個人的な面でものすごく動きのあった1年だった。
このブログでは、生物を再現したゲームの作成過程を書いていたが、途中であることを悟ってしまった。
これが完成する頃には僕はおじいちゃんになってるなと。
こんなん仕事の合間にできるようなもんじゃないやい。
というわけで一旦方向転換をしたり、いろいろ試行錯誤していた。
ひとまず、2013年に自分の中で起こったことを、メモっておく。
- 生物を再現し、物理エンジンで動くゲームを作成しようと思い立つ。
- ゲーム作成の過程を記しておこうと思い、このブログを作成。
- Sony製の物理エンジンEasyPhisicsをゲームに導入してみる(未発表...)。
- ここまでやって、生物ゲーム作成がとても片手間でできるような問題でないことに気づく。
- ひとまず、以前から画策していた、もっと小さなプロジェクトを進めることを決める。
- プロジェクトのプラットフォームとしてはWEBに決める。
- javascriptをいじり、使えない言語だと誤解する。
- 仕方ないので、google製の言語dartでアプリケーションを作り始める。
- 一方、本業では色々なLL言語を渡り歩く(perl->python->ruby)
- 結局ruby信者になった。
- rubyが関数型言語の考え方を取り入れていることを知り、関数型言語に興味を持つ。
- 関数型言語であるLispプログラマとして有名なPaulGrahamの本を読み、Lispに興味を持つ。
- Lispの入門書LandOfLispを買ってきて、CommonLispをかじり、オブジェクト指向信仰から目を覚ます。
- そろそろWEBアプリ(ゲーム)を自分で作ってみようと思い立ち、自宅のWindowsマシンにLinux(CentOS)を導入してサーバーを構築(途中)。
- javascriptを関数型的に実装すれば、気持ちよくプログラミングできるんじゃないかと考え、一度は使えない言語だと思ったjavascriptで作り始める(<-いまここ)
特に関数型プログラミングを知ったことが大きく、自分がいかに小さな世界でプログラミングしてたかにびびった。
ひとまず、去年dartで作っていたアプリケーションは、早々に出そうと思う。
今年の目標も。
- dartで作ったアプリケーションをChromeWebStoreで売る。
- WEBゲーム作成(ゲームのアイデアは既にある。サーバー関係がさっぱりなので、ここを勉強する目的も兼ねて。)
- CommonLispでなんらかのアプリケーションを作成。
- CommonLispでOpenGLを動かす。
- 小さくても何らかの成果物を作成した時点でブログで紹介してみる。
次の記事ではdartで作ったアプリケーションの公開を報告したい。