サイログ。

~雑多な記事置き場~

試してみた。

というわけで、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

とやれば動きますが・・・。

スピードあんま変わらんなぁ・・・。

これをもちっとオブジェクトを直接弄ることができれば高速化できるとおもうのですが・・・。
サテ、どうしようか・・・。