oyagame 0.0.3.0α
2008年5月10日
Pygame入門を参考にしながら、どんなことができればSDLがちゃんと使えたことになるか確認しながら開発を行っている。前回の0.0.2.3αでは、ウィンドウが表示できることが分かった。次は、このウィンドウに画像を表示させるというところだろう。
実行結果:
まずはこのコードの2行目、『execute SDL.ConstVBS』で、SDL_DOUBLEBUFなどの定数が利用できるようになったことがポイント。JScriptでは、『eval(SDL.COnstJS);』と記述すればよい。ただ、5行目がひどい。SDL_LoadBMPがまだ実装できていなくて、その理由は、SDL_LoadBMPがSDL.dllからエクスポートされている関数ではなくて、マクロで記述されているものであるからである。上記のコードは、そのマクロ定義に従って書いているもの。SDL.UpperBlitの部分も同じで、マクロ定義に関連するところ。これらはちょっとひどいので、後でなんとかしなければならない。
マクロ関連は後で直すことにして、とりあえず画像を動かすことができるかどうかを調べたのが、次のコード。このコードをテストするに当たって、タイマーをサポートするようにしている。
タイマーの利用は、call back 関数を使うことになっているので厄介かかなと思ったけれど、SDLの仕様書では、
The timer callback function may run in a different thread than your main program, and so shouldn't call any functions from within itself. You may always call SDL_PushEvent, however.
となっている。なら、call backをWSHで記述することはできないし、どうせPushEventしか使えないのなら、それ専用の call back 関数をoyagameの中に用意すれば良いはずである。次のようにした。
ここで、このcall back関数に引き渡されている2つのパラメータ、interval と、*param の両方ともユーザーイベントのパラメータとして保存しているので、すべての用途に対応できるはず。
これで、無事タイマーの実装も確認できた。ここまでくれば、基本設計は問題ないはず。気分よく、先のマクロ関連の問題を解決した後に作成したのが次のコード。
矢印キーを押すことで、画像を自由に動かすことに成功。上記VBScriptのコードも、無理なく記述することが可能になっている。ほぼ、完成だろう。
次に取り組んだのが、文字の表示。これはSDL本体では実装されていないようで、別途SDL_ttfというライブラリを使う必要があるらしい。そこで、SDL.dll 以外の DLL も呼び出せるようにし、その機能を用いて文字を表示させたテストコードが次。
実行結果:
TTF.RenderText_Solidの戻り値が整数なので、SDL.CreateStructureを用いて構造体オブジェクトに変換している。ここの仕様をどうしようか迷っているが、おそらくこのままにすると思う。SDL.dll 以外の機能を使う場合はこのような変換が必要と決めておくことで、仕様として統制が取れるからである。
まだ、SDL_ttf用の定数が使えないが、これは後のバージョンでサポートする予定。SDL_ttf, SDL_image, SDL_mixerの3つは良く使いそうなので、サポートすることになりそう。
次の予定としては、何か一つゲームをVBScriptかJScriptに移植して動作確認を取ること。これが済めば、正式版として公表かな。
あと、すぐにはやらないが、pygame互換のインターフェースが使えるようにもしたい。pygame入門のページをみていると、pygameのインターフェースは結構よさそうなので。
もう一つやりたいのは、ボタンやテキストボックスなどのコントロールを表示させること。SDL_EventStateでシステム固有のイベントをトラックするようにすれば、SDL_SysWMEvent構造体でmsgを取得可能のはず。ここで、msg が WM_CREATE のときに、CreateWindowすればよいのではないかと思う。ただ、ボタンをクリックしたときや、テキストボックスを変更したときなどのイベントをすべてフォローできるかどうか分からない(おそらく、すべては無理;wparamとlparamが受け渡されないようだ)。
<%media(20080508-oyagame_0030a.zip|oyagame0.0.3.0αはここからダウンロードできます。)%>
set SDL=CreateObject("sfcmini.oyagame") execute SDL.ConstVBS SDL.Init(SDL_INIT_EVERYTHING) set surface=SDL.SetVideoMode(200,100,32,SDL_RESIZABLE+SDL_HWSURFACE+SDL_DOUBLEBUF) call SDL.WM_SetCaption("Hello oyagame",0) set temp=SDL.CreateStructure("SDL_Surface",SDL.LoadBMP_RW(SDL.RWFromFile("block.bmp", "rb"), 1)) set image=SDL.ConvertSurface ( temp, surface.format, SDL_SWSURFACE ) SDL.FreeSurface(temp) call SDL.UpperBlit(image,image.clip_rect,surface,surface.clip_rect) SDL.Flip(surface) set ev=SDL.CreateStructure("SDL_Event") do SDL.WaitEvent(ev) select case ev.type case SDL_KEYDOWN if ev.key_keysym_sym=SDLK_ESCAPE then exit do end select loop until ev.type=SDL_QUIT WScript.Quit
実行結果:
まずはこのコードの2行目、『execute SDL.ConstVBS』で、SDL_DOUBLEBUFなどの定数が利用できるようになったことがポイント。JScriptでは、『eval(SDL.COnstJS);』と記述すればよい。ただ、5行目がひどい。SDL_LoadBMPがまだ実装できていなくて、その理由は、SDL_LoadBMPがSDL.dllからエクスポートされている関数ではなくて、マクロで記述されているものであるからである。上記のコードは、そのマクロ定義に従って書いているもの。SDL.UpperBlitの部分も同じで、マクロ定義に関連するところ。これらはちょっとひどいので、後でなんとかしなければならない。
マクロ関連は後で直すことにして、とりあえず画像を動かすことができるかどうかを調べたのが、次のコード。このコードをテストするに当たって、タイマーをサポートするようにしている。
set SDL=CreateObject("sfcmini.oyagame") execute SDL.ConstVBS SDL.Init(SDL_INIT_EVERYTHING) set surface=SDL.SetVideoMode(200,100,32,SDL_RESIZABLE+SDL_HWSURFACE+SDL_DOUBLEBUF) call SDL.WM_SetCaption("Hello oyagame",0) set temp=SDL.CreateStructure("SDL_Surface",SDL.LoadBMP_RW(SDL.RWFromFile("block.bmp", "rb"), 1)) set image=SDL.ConvertSurface ( temp, surface.format, SDL_HWSURFACE ) SDL.FreeSurface(temp) call SDL.AddTimer(60,SDL.NewTimerCallBack,0) set ev=SDL.CreateStructure("SDL_Event") do call SDL.FillRect(surface, surface.clip_rect, 0) call SDL.UpperBlit(image,0,surface,image.clip_rect) SDL.Flip(surface) image.clip_rect_x=image.clip_rect_x+1 SDL.WaitEvent(ev) select case ev.type case SDL_USEREVENT call SDL.AddTimer(60,SDL.NewTimerCallBack,0) case SDL_KEYDOWN if ev.key_keysym_sym=SDLK_ESCAPE then exit do end select loop until ev.type=SDL_QUIT WScript.Quit
タイマーの利用は、call back 関数を使うことになっているので厄介かかなと思ったけれど、SDLの仕様書では、
The timer callback function may run in a different thread than your main program, and so shouldn't call any functions from within itself. You may always call SDL_PushEvent, however.
となっている。なら、call backをWSHで記述することはできないし、どうせPushEventしか使えないのなら、それ専用の call back 関数をoyagameの中に用意すれば良いはずである。次のようにした。
static Uint32 NewTimerCallback(Uint32 interval, void *param){ SDL_Event ev; ev.type=SDL_USEREVENT; ev.user.type=SDL_USEREVENT; ev.user.code=interval; ev.user.data1=param; int Stack[1]={(int)&ev}; return CallSDL(L"PushEvent", 1, Stack ); }
ここで、このcall back関数に引き渡されている2つのパラメータ、interval と、*param の両方ともユーザーイベントのパラメータとして保存しているので、すべての用途に対応できるはず。
これで、無事タイマーの実装も確認できた。ここまでくれば、基本設計は問題ないはず。気分よく、先のマクロ関連の問題を解決した後に作成したのが次のコード。
set SDL=CreateObject("sfcmini.oyagame") execute SDL.ConstVBS SDL.Init(SDL_INIT_EVERYTHING) set surface=SDL.SetVideoMode(200,100,32,SDL_RESIZABLE+SDL_HWSURFACE+SDL_DOUBLEBUF) call SDL.WM_SetCaption("Hello oyagame",0) set temp=SDL.LoadBMP("block.bmp") set image=SDL.ConvertSurface ( temp, surface.format, SDL_HWSURFACE ) SDL.FreeSurface(temp) call SDL.AddTimer(7,SDL.NewTimerCallBack,0) set ev=SDL.CreateStructure("SDL_Event") key=0 do call SDL.FillRect(surface, surface.clip_rect, 0) call SDL.BlitSurface(image,0,surface,image.clip_rect) SDL.Flip(surface) SDL.WaitEvent(ev) select case ev.type case SDL_USEREVENT call SDL.AddTimer(7,SDL.NewTimerCallBack,0) case SDL_KEYUP if ev.key_keysym_sym=key then key=0 case SDL_KEYDOWN key=ev.key_keysym_sym case SDLK_ESCAPE exit do end select select case key case SDLK_UP image.clip_rect_y=image.clip_rect_y-1 case SDLK_DOWN image.clip_rect_y=image.clip_rect_y+1 case SDLK_RIGHT image.clip_rect_x=image.clip_rect_x+1 case SDLK_LEFT image.clip_rect_x=image.clip_rect_x-1 end select loop until ev.type=SDL_QUIT WScript.Quit
矢印キーを押すことで、画像を自由に動かすことに成功。上記VBScriptのコードも、無理なく記述することが可能になっている。ほぼ、完成だろう。
次に取り組んだのが、文字の表示。これはSDL本体では実装されていないようで、別途SDL_ttfというライブラリを使う必要があるらしい。そこで、SDL.dll 以外の DLL も呼び出せるようにし、その機能を用いて文字を表示させたテストコードが次。
set SDL=CreateObject("sfcmini.oyagame") execute SDL.ConstVBS SDL.Init(SDL_INIT_EVERYTHING) set surface=SDL.SetVideoMode(200,100,32,SDL_RESIZABLE+SDL_HWSURFACE+SDL_DOUBLEBUF) call SDL.WM_SetCaption("Hello oyagame",0) set TTF=CreateObject("sfcmini.oyagame") call TTF.LoadLibrary("SDL_ttf.dll","TTF_") TTF.Init() font=TTF.OpenFont("c:\windows\fonts\msgothic.ttc",16) text=TTF.RenderText_Solid(font,"Hello oyagame!",&Hffffff) set text=SDL.CreateStructure("SDL_Surface",text) set ev=SDL.CreateStructure("SDL_Event") do call SDL.BlitSurface(text,0,surface,text.clip_rect) SDL.Flip(surface) SDL.WaitEvent(ev) loop until ev.type=SDL_QUIT WScript.Quit
実行結果:
TTF.RenderText_Solidの戻り値が整数なので、SDL.CreateStructureを用いて構造体オブジェクトに変換している。ここの仕様をどうしようか迷っているが、おそらくこのままにすると思う。SDL.dll 以外の機能を使う場合はこのような変換が必要と決めておくことで、仕様として統制が取れるからである。
まだ、SDL_ttf用の定数が使えないが、これは後のバージョンでサポートする予定。SDL_ttf, SDL_image, SDL_mixerの3つは良く使いそうなので、サポートすることになりそう。
次の予定としては、何か一つゲームをVBScriptかJScriptに移植して動作確認を取ること。これが済めば、正式版として公表かな。
あと、すぐにはやらないが、pygame互換のインターフェースが使えるようにもしたい。pygame入門のページをみていると、pygameのインターフェースは結構よさそうなので。
もう一つやりたいのは、ボタンやテキストボックスなどのコントロールを表示させること。SDL_EventStateでシステム固有のイベントをトラックするようにすれば、SDL_SysWMEvent構造体でmsgを取得可能のはず。ここで、msg が WM_CREATE のときに、CreateWindowすればよいのではないかと思う。ただ、ボタンをクリックしたときや、テキストボックスを変更したときなどのイベントをすべてフォローできるかどうか分からない(おそらく、すべては無理;wparamとlparamが受け渡されないようだ)。
<%media(20080508-oyagame_0030a.zip|oyagame0.0.3.0αはここからダウンロードできます。)%>
コメント
Kat (2008年5月11日 23:24:28)
SDL_SysWMEvent構造体のmsgは、SDL_SysWMmsg構造体へのポインタのようだ。SDL_SysWMmsgは、wparam, lparamを含んでいるので、すべてのイベントをトラックできるのではないだろうか。