Tutorial.18 拡大縮小(2)

拡大縮小

スプライトの拡大縮小機能は、以下のような手順で使用します。

  • 1.属性(Object Attribute Memory)に関する設定をする。
  • 2.拡大縮小パラメータをセットする。

拡大縮小パラメータは、OAMのattribute3を使います。
ただし、4つのスプライトのattribute3を1つのパラメータとして使うので誤解しないでください。
OAMのアクセスには、次のような構造体をマッピングをして指定できるようにします。

typedef struct {
	u16 dummy0[3];
	s16 pa;
	u16 dummy1[3];
	s16 pb;
	u16 dummy2[3];
	s16 pc;
	u16 dummy3[3];
	s16 pd;
} OBJAFFINE;

OBJAFFINE* rot = (OBJAFFINE*)OAM

以上のように指定すればrot[0].pa のようにアクセスすることができます。

RotData構造体は0-31の32個まで設定可能で、128個のスプライトで拡大縮小機能を使うものは、
0-31のどのパラメータを使うか指定する必要があります。
拡大縮小パラメータのフォーマットは16bitのデータで、これはBGで説明したときと同じです。

200%拡大してスプライトを表示する例

#include "lib/gba.h"
#include "res.h"

//---------------------------------------------------------------------------
void WaitForVsync(void)
{
	while (*(volatile u16*)0x4000006 >= 160) {};
	while (*(volatile u16*)0x4000006 <  160) {};
}
//---------------------------------------------------------------------------
/*
	SpriteSetRotateFlag
	スプライトの拡大縮小回転機能に関する設定
	no      ・・・ 使用するスプライトRotateパラメータの番号
	double_flag ・・・ 描画領域を2倍使用できるようにするか
	                     0なら通常の描画領域、SP_SIZE_DOUBLEなら2倍
*/
void SpriteSetRotateFlag(u32 num, u32 no, u32 double_flag)
{
	OBJATTR* sp = (OBJATTR*)OAM + num;

	sp->attr0 |= OBJ_ROT_SCALE_ON;

	sp->attr1 &= 0xC1ff;
	sp->attr1 |= OBJ_ROT_SCALE(no);
	sp->attr0 &= 0xfdff;
	sp->attr0 |= double_flag;
}
//---------------------------------------------------------------------------
void SpriteScale(u32 num, u32 xsc, u32 ysc)
{
	OBJAFFINE* rot = (OBJAFFINE*)OAM + num;

	rot->pa = 256 * 100 / xsc;
	rot->pb = 0;
	rot->pc = 0;
	rot->pd = 256 * 100 / ysc;
}
//---------------------------------------------------------------------------
void SpriteSetPalNo(u32 num, u32 palNo)
{
	OBJATTR* sp = (OBJATTR*)OAM + num;

	sp->attr2 &= 0x0fff;
	sp->attr2 |= (palNo << 12);
}
//---------------------------------------------------------------------------
void SpriteMove(u32 num, s32 x, s32 y)
{
	OBJATTR* sp = (OBJATTR*)OAM + num;

	if(x<0) x += 512;
	if(y<0) y += 256;

	sp->attr1 &= 0xfe00;
	sp->attr0 &= 0xff00;
	sp->attr1 |= (x & 0x01ff);
	sp->attr0 |= (y & 0x00ff);
}
//---------------------------------------------------------------------------
void SpriteSetSize(u32 num, u32 size, u32 form, u32 col)
{
	OBJATTR* sp = (OBJATTR*)OAM + num;

	sp->attr0 &= 0x1fff;
	sp->attr1 &= 0x3fff;
	sp->attr0 |= col  | form | (160);
	sp->attr1 |= size | (240);
}
//---------------------------------------------------------------------------
void SpriteSetChr(u32 num, u32 ch)
{
	OBJATTR* sp = (OBJATTR*)OAM + num;

	sp->attr2 &= 0xfc00;
	sp->attr2 |= ch;
}
//---------------------------------------------------------------------------
void SpriteInit(void)
{
	u32 i;
	for(i=0; i<128; i++)
	{
		SpriteMove(i, 240, 160);
	}
}
//---------------------------------------------------------------------------
int main(void)
{
	// モード設定
	SetMode(MODE_0 | OBJ_ENABLE | OBJ_1D_MAP);

	u16* oam = OBJ_BASE_ADR;	// スプライトデータ
	u16* pal = OBJ_COLORS;		// スプライトパレット
	u32 i;

	// データの格納
	for(i=0; i<sprTilesLen/2; i++)
	{
		oam[i] = sprTiles[i];
	}

	// パレットの格納
	for(i=0; i<16; i++)
	{
		pal[i] = sprPal[i];
	}


	SpriteInit();

	SpriteSetSize (0, OBJ_SIZE(1), OBJ_SQUARE, OBJ_16_COLOR);
	SpriteSetChr  (0, 0);
	SpriteMove    (0, 20, 20);
	SpriteSetPalNo(0, 0);

	SpriteSetRotateFlag(0, 0, OBJ_DOUBLE);
	SpriteScale(0, 200, 200);

	for(;;)
	{
		WaitForVsync();
	}
}

SpriteSetRotateFlag関数のdouble_flagは、ダブルサイズフラグと呼ばれるものです。
スプライトで拡大縮小回転表示を行う場合、元のスプライトのサイズ(この場合は16x16)を
超えた領域は描画が行われません。

拡大や回転を行って、画像がその領域を超えてしまう場合、
画像が欠けてしまうために不都合が起こる場合があります。

このような場合にダブルサイズフラグを設定すれば、描画領域が元の画像の下と右に広がり、
元の2倍の大きさまで描画するようになります。

ダブルサイズフラグを指定しても、2倍を超えた領域は描画されません。
ダブルサイズフラグを指定すると元の画像が2倍の大きさで描画されるということではありません。

 

ダブルサイズフラグを指定した場合、スプライトの中心位置が移動します。
スプライトのサイズの半分だけ、右下方向に移動します。
この場合は右方向に16/2=8、下方向に16/2=8移動することになります。
ダブルサイズフラグを指定する場合は、スプライトが表示される位置に注意してください。

動作画面

clip_1.png

履歴

  • 2015/10/07
  • 2007/09/08

添付ファイル: fileclip_1.png 200件 [詳細]

Last-modified: 2015-10-07 (水) 23:23:41 (2206d)