ゲーム開発7:スプライト処理

ba1523d5.gifグラフィックまわりをやる事にしました。

まずスプライト描画処理を修正しました。DrawSpriteBase()です。スプライトに拡大縮小回転と色味の引数を渡して、それを計算しています。

次にスプライトそのもののデータ管理ですが、スプライト管理構造体SPRITE_MANAGEMENTテクスチャ管理構造体TEXTURE_MANAGEMENTの2つに分けてみました。なぜかというと、1枚の画像(テクスチャ)から複数のスプライトを取り出すため、別々に扱った方がよさそうだからです。

まずテクスチャの生成CreateTexture()ですが、上に書いた通り1枚のテクスチャを複数のスプライトが参照するため、既に生成しているテクスチャなのかをTEXTURE_MANAGEMENTのファイル名で確認し、その参照している数をreferenceでカウントします。参照数のカウントは、テクスチャを破棄する際に、誰も参照していない事を確認するためです。誰かが参照してるのに破棄したら困るからね。

次にスプライトの生成CreateSprite()は、どのテクスチャを使うか、またテクスチャのどの領域から切り取って使うかをSPRITE_MANAGEMENTに格納します。

これで生成されたスプライトは、最低限スプライト番号spr_noと座標x,yだけで画面に表示できます。ちなみにDrawSprite()には引数がたくさんあるけど、spr_no,x,y以外はディフォルト引数にしているため、未入力でもOKです。

グラフィックに関しては、画面スクロールを実現するため、ワールド座標系ビューポート座標系の導入が必要になりますが、とりあえず置いといて、次回は入力まわりです。

//---------------------------------------------------------
// スプライト描画

void CGraphicsBase::DrawSpriteBase(int tex_no, RECT drawRect, float x, float y, float z, DWORD color, float angle, float scale_x, float scale_y)
{
 D3DXMATRIX mat, mat1, mat2, mat3;
 float  center_x, center_y;
 D3DXVECTOR3 Center;

 // マトリクス初期化
 D3DXMatrixIdentity(&mat1);
 D3DXMatrixIdentity(&mat2);
 D3DXMatrixIdentity(&mat3);

 // マトリクスで拡大縮小回転移動
 D3DXMatrixScaling(&mat1, scale_x, scale_y, 1);
 D3DXMatrixRotationZ(&mat2, D3DXToRadian(angle));
 D3DXMatrixTranslation(&mat3, x, y, z);
 mat=mat1*mat2*mat3;
 D3Sprite->SetTransform(&mat);

 // 画像の中心
 center_x=(float)(drawRect.right-drawRect.left)/2;
 center_y=(float)(drawRect.bottom-drawRect.top)/2;
 Center=D3DXVECTOR3(center_x, center_y, 0);

 // 描画
 D3Sprite->Draw(Texture[tex_no]->Tex, &drawRect, &Center, NULL, color);
}

//---------------------------------------------------------
// テクスチャ生成
int CGraphics::CreateTexture(char *filename)
{
 int  i, tex_no;

 // テクスチャが既に登録されていないか判断
 tex_no=-1;
 i=0;
 for (i=0; i<max_TEX; i++) {
  if (Texture[i]!=NULL) {
   if (strcmp(Texture[i]->filename, filename)==0) {
    tex_no=i;
   }
  }
 }
 if (tex_no!=-1) {
  Texture[tex_no]->reference++;
  return tex_no;
 }

 // 空いているテクスチャを探す
 tex_no=0;
 while (Texture[tex_no]!=NULL || tex_no>=MAX_TEX) {
  tex_no++;
 }
 if (tex_no>=MAX_TEX) {
  return -1;
 }

 // テクスチャ生成
 Texture[tex_no]= new TEXTURE_MANAGEMENT;
 Texture[tex_no]->filename= new char[strlen(filename)+1];
 Texture[tex_no]->reference=1;
 strcpy_s(Texture[tex_no]->filename, (strlen(filename)+1), filename);

 // テクスチャ読み込み
 CreateTextureBase(Texture[tex_no]->filename, &Texture[tex_no]->Tex);

 return tex_no;
}

//---------------------------------------------------------
// テクスチャ解放
void CGraphics::ReleaseTexture(int tex_no)
{
 // 解放済み?
 if (Texture[tex_no]==NULL) {
  return;
 }

 // どのオブジェクトからも参照されていなければ解放
 Texture[tex_no]->reference--;
 if (Texture[tex_no]->reference<=0) {
  delete[] Texture[tex_no]->filename;
  Texture[tex_no]->Tex->Release();
  delete Texture[tex_no];
  Texture[tex_no]=NULL;
 }
}

//---------------------------------------------------------
// スプライト生成
int CGraphics::CreateSprite(char *filename, RECT Range)
{
 int  i, tex_no, spr_no;

 // 空いているスプライトを探す
 spr_no=-1;
 for (i=0; i<max_SPR; i++) {
  if (Sprite[i]==NULL) {
   spr_no=i;
  }
 }
 if (spr_no==-1) {
  return -1;
 }

 // テクスチャ生成
 tex_no=CreateTexture(filename);

 // スプライト生成
 Sprite[spr_no]= new SPRITE_MANAGEMENT;
 Sprite[spr_no]->tex_no=tex_no;
 Sprite[spr_no]->Range=Range;

 return spr_no;
}

//---------------------------------------------------------
// スプライト解放
void CGraphics::ReleaseSprite(int spr_no)
{
 // 解放済み?
 if (Sprite[spr_no]==NULL) {
  return;
 }

 // テクスチャ解放
 ReleaseTexture(Sprite[spr_no]->tex_no);

 // 解放
 delete Sprite[spr_no];
 Sprite[spr_no]=NULL;
}

//---------------------------------------------------------
// スプライト描画
void CGraphics::DrawSprite(int spr_no, float x, float y, float z, DWORD color, float angle, float scale_x, float scale_y)
{
 DrawSpriteBase(Sprite[spr_no]->tex_no, Sprite[spr_no]->Range, x, y, z, color, angle, scale_x, scale_y);
}

コメントを残す

メールアドレスが公開されることはありません。