試してみた。
というわけで、MiyakoのScreen::updateメソッドの一部をCにしてみました。
ベースは、MinGW+MSYS+SDL+RubySDL1.3で。
ソースコードは↓から。
#include "ruby.h" VALUE mSDL; VALUE mMiyako; VALUE mScreen; VALUE cWindow; VALUE cTextBox; VALUE cSprite; VALUE mvScreen; ID idGetList; ID idDrawWindow; ID idViewPort; ID idEach; ID idUpdateTick; ID idFlip; ID idVX; ID idVY; ID idVW; ID idVH; ID idX; ID idY; ID idW; ID idH; ID idOX; ID idOY; ID idOW; ID idOH; ID idBitmap; ID idFont; ID idVisible; ID idTextVisible; ID idText; ID idTextMagrinLeft; ID idTextMagrinRight; ID idTextMagrinTop; ID idTextMagrinBottom; ID idLocateX; ID idLocateY; ID idTextAreaW; ID idTextAreaH; ID idNowLocateX; ID idNowLocateY; ID idUpdate; ID idEffect; ID idEffecting; ID idAngle; ID idScaleX; ID idScaleY; ID idCenterX; ID idCenterY; ID idSetClipRect; ID idFillRect; ID idTransformBlit; ID idBlitSurface; static VALUE update2(VALUE self) { VALUE wlist = rb_funcall(cWindow, idGetList, 0, NULL); VALUE tlist = rb_funcall(cTextBox, idGetList, 0, NULL); VALUE slist = rb_funcall(cSprite, idGetList, 0, NULL); VALUE vw = rb_ivar_get(mScreen, idVW); VALUE vh = rb_ivar_get(mScreen, idVH); rb_funcall(mvScreen, idFillRect, 5, INT2NUM(0), INT2NUM(0), vw, vh, rb_ary_new3(3, INT2NUM(0), INT2NUM(0), INT2NUM(0))); int cnt = RARRAY(wlist)->len; int i; for(i=0; i<cnt; i++) { VALUE window = *(RARRAY(wlist)->ptr+i); if(!(NIL_P(window))) { rb_funcall(window, idDrawWindow, 0, NULL); } } cnt = RARRAY(tlist)->len; for(i=0; i<cnt; i++) { VALUE window = *(RARRAY(wlist)->ptr+i); if(!(NIL_P(window))) { rb_funcall(window, idDrawWindow, 0, NULL); } } int vx = FIX2INT(rb_ivar_get(mScreen, idVX)); int vy = FIX2INT(rb_ivar_get(mScreen, idVY)); cnt = RARRAY(slist)->len; for(i=0; i<cnt; i++) { VALUE spr = *(RARRAY(slist)->ptr+i); if(RTEST(rb_funcall(spr, idVisible, 0, NULL))) { VALUE vp = rb_funcall(spr, idViewPort, 0, NULL); int vpx = FIX2INT(rb_funcall(vp, idX, 0, NULL)); int vpy = FIX2INT(rb_funcall(vp, idY, 0, NULL)); VALUE bitmap = rb_funcall(spr, idBitmap, 0, NULL); rb_funcall(mvScreen, idSetClipRect, 4, INT2NUM(vpx+vx), INT2NUM(vpy+vy), rb_funcall(vp, idW, 0, NULL),rb_funcall(vp, idH, 0, NULL)); rb_funcall(spr, idUpdate, 0, NULL); if(!(NIL_P(bitmap))) { VALUE effect = rb_funcall(spr, idEffect, 0, NULL); VALUE va = rb_funcall(spr, idAngle, 0, NULL); VALUE vsx = rb_funcall(spr, idScaleX, 0, NULL); VALUE vsy = rb_funcall(spr, idScaleY, 0, NULL); VALUE vcx = rb_funcall(spr, idCenterX, 0, NULL); VALUE vcy = rb_funcall(spr, idCenterY, 0, NULL); VALUE vspx = rb_funcall(spr, idX, 0, NULL); VALUE vspy = rb_funcall(spr, idY, 0, NULL); double angle = NUM2DBL(va); int sx = (int)(NUM2DBL(vsx) * NUM2DBL(vcx)); int sy = (int)(NUM2DBL(vsy) * NUM2DBL(vcy)); int x = NUM2INT(vspx); int y = NUM2INT(vspy); if(!NIL_P(effect) && RTEST(rb_funcall(effect, idEffecting, 0, NULL))) { rb_funcall(effect, idUpdate, 1, mvScreen); } else if(sx != 1.0, sy != 1.0, angle != 0.0) { rb_funcall(mSDL, idTransformBlit, 10, bitmap, mvScreen, va, vsx, vsy, INT2NUM(sx), INT2NUM(sy), INT2NUM(x+vx+sx), INT2NUM(y+vy+sy), INT2NUM(0)); } else { VALUE vox = rb_funcall(spr, idOX, 0, NULL); VALUE voy = rb_funcall(spr, idOY, 0, NULL); VALUE vow = rb_funcall(spr, idOW, 0, NULL); VALUE voh = rb_funcall(spr, idOH, 0, NULL); rb_funcall(mSDL, idBlitSurface, 8, bitmap, vox, voy, vow, voh, mvScreen, INT2NUM(x+vx), INT2NUM(y+vy)); } } } } rb_funcall(mScreen, idUpdateTick, 0, NULL); rb_funcall(mvScreen, idFlip, 0, NULL); return self; } void Init_ext_update() { mSDL = rb_define_module("SDL"); mMiyako = rb_define_module("Miyako"); mScreen = rb_define_module_under(mMiyako, "Screen"); cWindow = rb_define_class_under(mMiyako, "Window", rb_cObject); cTextBox = rb_define_class_under(mMiyako, "TextBox", rb_cObject); cSprite = rb_define_class_under(mMiyako, "Sprite", rb_cObject); mvScreen = rb_funcall(mScreen, rb_intern("screen"), 0, NULL); idGetList = rb_intern("getList"); idDrawWindow = rb_intern("drawWindow"); idViewPort = rb_intern("viewPort"); idEach = rb_intern("each"); idUpdateTick = rb_intern("update_tick"); idFlip = rb_intern("flip"); idVX = rb_intern("@@x"); idVY = rb_intern("@@y"); idVW = rb_intern("@@width"); idVH = rb_intern("@@height"); idX = rb_intern("x"); idY = rb_intern("y"); idW = rb_intern("w"); idH = rb_intern("h"); idOX = rb_intern("ox"); idOY = rb_intern("oy"); idOW = rb_intern("ow"); idOH = rb_intern("oh"); idBitmap = rb_intern("bitmap"); idFont = rb_intern("font"); idVisible = rb_intern("visible"); idTextVisible = rb_intern("textVisible"); idText = rb_intern("text"); idTextMagrinLeft = rb_intern("textMarginLeft"); idTextMagrinRight = rb_intern("textMarginRight"); idTextMagrinTop = rb_intern("textMarginTop"); idTextMagrinBottom = rb_intern("textMarginBottom"); idLocateX = rb_intern("locateX"); idLocateY = rb_intern("locateY"); idTextAreaW = rb_intern("textAreaW"); idTextAreaH = rb_intern("textAreaH"); idNowLocateX = rb_intern("nowLocateX"); idNowLocateY = rb_intern("nowLocateY"); idUpdate = rb_intern("update"); idEffect = rb_intern("effect"); idEffecting = rb_intern("effecting?"); idAngle = rb_intern("angle"); idScaleX = rb_intern("scaleX"); idScaleY = rb_intern("scaleY"); idCenterX = rb_intern("centerX"); idCenterY = rb_intern("centerY"); idSetClipRect = rb_intern("setClipRect"); idFillRect = rb_intern("fillRect"); idTransformBlit = rb_intern("transformBlit"); idBlitSurface = rb_intern("blitSurface"); rb_define_module_function(mScreen, "update", update2, 0); }
extconf.rbはこんな感じ。
require 'mkmf' create_makefile('ext_update')
あと、このプログラムを弄るときは、
require 'miyako' require 'ext_update' Miyako::Screen.fpsView = true loop do Miyako::Input::update break if Miyako::Input.pushed_any?(:esc, :quit) Miyako::Screen::update end
とやれば動きますが・・・。
スピードあんま変わらんなぁ・・・。
これをもちっとオブジェクトを直接弄ることができれば高速化できるとおもうのですが・・・。
サテ、どうしようか・・・。