Home | Lesson | Game | Tool | Link

A01.スプライト

画像を拡大縮小/回転/色変更させながら表示します。
2Dゲームの作成や、HUD(ヘッドアップディスプレイ)などの作成が簡単にできるようになります。

定義
画像を拡大縮小/回転/色変更をするために、わかりやすいようにグローバル変数を用意しておきます。
#ifndef PI
	#define PI 3.1415926536
#endif

float SCALE = 1.0f;	//拡大縮小率
int   TV    = 0;		//テクスチャ読み込み座標
int   RZ    = 0;		//回転
int   COL   = 0;		//カラーパターン

position2d mouse;

イベント処理
MyEventReceiverを作成してイベント処理を行います。
マウスで画像を操作できるように設定します。操作方法は以下の通りです。
左ボタン   :画像読み込み位置変更。
中央ボタン押し:カラーパターン変更。
右ボタン   :画像回転。
ホイール上回転:画像拡大。
ホイール左回転:画像縮小。
マウス移動  :カーソル位置に画像表示。
//イベント処理
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(const SEvent& event)
	{
		if(event.EventType == EET_MOUSE_INPUT_EVENT)
		{
			switch(event.MouseInput.Event)
			{
				case EMIE_LMOUSE_PRESSED_DOWN:
					if(TV < 3)
						TV++;
					else
						TV = 0;
					return true;
				case EMIE_MMOUSE_PRESSED_DOWN:
					COL++;
					if(COL == 8)
						COL = 0;
					return true;
				case EMIE_RMOUSE_PRESSED_DOWN:
					RZ+=30;
					if(RZ == 360)
						RZ = 0;
					return true;
				case EMIE_MOUSE_WHEEL:
					//上回転
					if(event.MouseInput.Wheel == 1)
					{
						if(SCALE < 10.0f)
							SCALE += 0.2f;
					}
					//下回転
					else if(event.MouseInput.Wheel == -1)
					{
						if(SCALE > 0.2f)
							SCALE -= 0.2f;
					}
					return true;
				case EMIE_MOUSE_MOVED:
					mouse.X = event.MouseInput.X;
					mouse.Y = event.MouseInput.Y;
					return true;
				default:
					return true;
			}
		}
		return false;
	}
};

スプライト描画
回転拡大/縮小/色変更などの機能をもったスプライトを表示します。
今回のlessonの肝です。描画に関してはこの関数だけで解決するようにしています。
自分のプログラムに移植する際は、namespace/PIの定義も忘れないようにしてください。
//スプライト描画
void sprite(IVideoDriver *driver, char* filename, 
			int x, int y, int w, int h, int u, int v, int r, 
			float sx, float sy, SColor color,
			bool bColorKey)
{
	matrix4 rotate, pos, Ortho, scale, world;
	SColor col = color;
	char *file = filename;

	dimension2d<s32> screen = driver->getScreenSize();

	//テクスチャ読み込み
	ITexture* Texture;
	Texture = driver->getTexture(file);
	//[注意]
	//黒色が存在する状態で、ほかの色を指定すると抜いても黒くなる
	//描画のたびにカラーキー指定すると遅くなる(描画とは別が望ましい)
	//アルファを指定する場合は0x80以上だけが有効、それ以外は透明
	if(bColorKey)
	{
		//カラーキー(色指定)
		driver->makeColorKeyTexture(Texture, 0x00000000);
		//カラーキー(座標指定)
		//driver->makeColorKeyTexture(Texture,position2d<s32>(0,0));
	}
	dimension2d<s32> tex = Texture->getOriginalSize();

	//マテリアル設定
	SMaterial Material;
	Material.Lighting     = false;
	if(bColorKey)
		Material.MaterialType = EMT_TRANSPARENT_ALPHA_CHANNEL;//画像アルファ
	else
		Material.MaterialType = EMT_TRANSPARENT_VERTEX_ALPHA;//頂点アルファ
	Material.TextureLayer[0].Texture  = Texture;

	//拡大縮小設定
	scale.setScale(vector3df(sx,sy,1));//Z軸での拡大縮小はダメ

	//位置設定(左上を基準に設定)
	float px = ((x)+w/2*sx)/((double)screen.Width/2) - 1.0;
	float py = 1.0 - ((y)+h/2*sy)/((double)screen.Height/2);
	pos.setTranslation(vector3df(px,py,0));//Z座標での位置指定はダメ

	//回転設定(中心で回転)
	float rad = (float)(PI/180);//1度を設定
	float rz = (r)%360 * rad;
	rotate.setRotationRadians(vector3df(0,0,rz));//XY座標での回転はダメ

	//ポリゴン作成
	u16 list[] = {0,1,2, 2,1,3};
	S3DVertex ver[4];
	float tx = w/2;
	float ty = h/2;
	float tw = (float)w/tex.Width;
	float th = (float)h/tex.Height;
	float tu = (float)(u)/(float)tex.Width;
	float tv = (float)(v)/(float)tex.Height;
	ver[0] = S3DVertex(-tx, ty, 0,  0,0,0, col, tu,   tv   );//左上
	ver[1] = S3DVertex( tx, ty, 0,  0,0,0, col, tu+tw,tv   );//右上
	ver[2] = S3DVertex(-tx,-ty, 0,  0,0,0, col, tu,   tv+th);//左下
	ver[3] = S3DVertex( tx,-ty, 0,  0,0,0, col, tu+tw,tv+th);//右下

	//スクリーン設定
	//初期値以外を書き換え(W,0,0,0,0,H,0,0,0,0,1,0,0,0,0,1)
	Ortho(0,0) = (double)2/(double)screen.Width;
	Ortho(1,1) = (double)2/(double)screen.Height;

	//ワールドに反映
	driver->setTransform(ETS_VIEW, world);
	driver->setTransform(ETS_PROJECTION, world);
	world = pos*Ortho*rotate*scale;
	driver->setTransform(ETS_WORLD, world);

	//描画
	driver->setMaterial(Material);
	driver->drawIndexedTriangleList(&ver[0], 4, &list[0], 2);
}

描画
カラーパターン変更用に配列を用意しておきます。
void makeScene(IVideoDriver *driver)
{
	SColor colors[8] = 
	{
		0xFFFFFFFF, 0xFF0000FF, 0xFF00FF00, 0xFFFF0000,
		0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00, 0xFF000000
	};
	sprite(driver,"icon.bmp",mouse.X,mouse.Y,32,32,TV*32,0,
		RZ,SCALE,SCALE,colors[COL],true);
}


スプライト
今までのlessonの応用で作成できるようになっています。
これで、2Dゲームであれば、難なく作れるようになるかと思います。

現段階のスプライトの問題点
draw2DImageではアルファの値を0x00〜0xFFで設定できるので、
徐々に消えていく/徐々に表示するということができたのですが、
ポリゴンを使用しているため、0x81以上のアルファ値しか使用できません。
0x80以下の値を指定したい場合は、draw2DImageを使用してください。
もし、解決方法がわかれば、随時更新していきます。
ポリゴンを使用していますが、3D空間内での表示はできないので注意してください。
XY平面での表示、Z軸での回転だけになります。

ダウンロード
今回作成したファイル一式です。

宿題
1.キーボードで画像を操作してみましょう。
2.カーソルキーの押したキーによって画像がかわるようにしてみましょう。