忍者ブログ
  • 2024.04
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 2024.06
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/05/03 03:25 】 |
テクスチャ描画関数
テクスチャ描画する関数の決定版(?)。

汎用的にするのが目標。
機能は多彩。でも使い方は簡単。そういう風に、私はなりたい。


というわけで、
関数としては1つだけ。

void drawTexture(SpriteData data);

これ以上ないくらい単純明快。


では解説していきます。

drawTextureができること(いずれ他にも出てくるかも)
・テクスチャを指定できる
・描画する座標を指定できる
・描画サイズを指定できる
・アンカーポイントを指定できる
・回転して描画できる
・uv座標の切り取りができる
・減色ができる


これらのことを全部やるには、指定すべき変数がかなり多くなります。
それをぜんぶ関数の引数に持たせるのは冗長。
オーバーロードするにも組み合わせが多いし、デフォルト引数で対応するのも難しい。
という訳で、引数としては構造体を一つ渡すだけにしました。
この構造体にすべての変数が入っています。


struct SpriteData {
public:
TextureHandle_t hTex; //テクスチャハンドル
point_t pos; //描画座標
size_t size; //描画サイズ
point_t anchorPos; //テクスチャ座標のどこを描画座標に置くか(0.0~1.0)
float rad; //回転させる. 回転中心はテクスチャ中心。anchorPosではない
rect_t uvRect; //テクスチャの切り取りUV座標
color_t color; //減色

SpriteData(TextureHandle_t ihTex)
: hTex(ihTex), pos(0.f, 0.f), size(0.f,0.f), anchorPos(0.f, 0.f), rad(0.f)
, uvRect(0.f, 0.f, 1.f, 1.f)
{}
SpriteData& Tex(TextureHandle_t ihTex){this->hTex = ihTex; setOriginalSize(); return *this;}
SpriteData& Pos(aoPoint2 pos){this->pos = pos; return *this;}
SpriteData& Pos(float x, float y){return Pos(aoPoint2(x,y));}
SpriteData& Size(size_t size){this->size = size; return *this;}
SpriteData& Size(float w, float h){return Size(aoSize2(w,h));}
SpriteData& Anchor(point_t pos){this->anchorPos = pos; return *this;}
SpriteData& Anchor(float x, float y){return Anchor(aoPoint2(x,y));}
SpriteData& Rect(rect_t rect){this->pos = rect.LT(); this->anchorPos = point_t(0.f,0.f); this->size = rect.Size(); return *this;}
SpriteData& AngleRad(float rad){this->rad = rad; return *this;}
SpriteData& AngleDeg(float deg){this->rad = deg / 180.f * 3.14159265359f; return *this;}
SpriteData& UVRect(rect_t rect){this->uvRect = rect; return *this;}
SpriteData& Color(color_t col){this->color = col; return *this;}
SpriteData& Color(float r, float g, float b, float a = 1.f){return Color(color_t(r,g,b,a));}
};


という訳で、見れば分かる通り、必要な変数がすべて入っている。

hTexはそのまま、テクスチャハンドル。
これが無いと始まらないので、コンストラクタにも引数で指定させています。
コンストラクタで指定した後に変えることも可。他の指定はそのままで、テクスチャだけどんどん変えていきたいなんてこともあるだろうからね。

posは描画する座標。
で、テクスチャのどの位置をこのposに置くか、というのを指定するのがanchorPos。
anchorPosはpoint2構造体で、xもyも0.0~1.0の範囲で指定します。
(0.0,0.0)の場合、アンカーポイントはテクスチャ左上。つまり、posで指定した座標にテクスチャの左上を合わせるように配置します。
anchorPosが(0.5,0.5)の場合、アンカーポイントはテクスチャ中心。(1.0,1.0)の場合、右下。(0.0,1.0)なら左下。
一応、0.0~1.0の範囲を超えても動作するけど、あまり意味は無いかな。
ついテクスチャサイズで指定してしまいそうだね。気をつけないと。
指定しない場合は、(0.0,0.0)になるので左上がアンカーポイント。

sizeは、描画するサイズ。
指定がない場合は、テクスチャ等倍で描画します。

(仮の仕様として、
Scale()関数で指定した場合、テクスチャの元のサイズの何倍で描画するか、という指定の仕方が可能。
もちろん、テクスチャハンドルが正しく指定されている状態でないと、元のサイズが分からないので正しく指定できません。
この場合だけ、テクスチャの元サイズが分かっている必要があり、テクスチャの元サイズを調べにいく処理が入るなどイレギュラーなので、今後外すかも。でもあるとすごく便利なんだよね。残すかどうかは出番が実際どれくらいあるかによる!)

また、Rect()関数を使うと、posとsizeをまとめて指定できます。

radは、テクスチャを回転したいときに使います。
単位はラジアンです。角度はいつものごとく間違えやすいので、AngleRad(),AngleDeg()関数を使って指定するのを推奨。
回転の中心は、テクスチャ中心です。アンカーポイント中心ではないので注意!

uvRectは、テクスチャを切り取って描画したいときに使います。
タイルマップ状のテクスチャのときなどに使うかと思います。
指定範囲は0.0~1.0。これもついテクスチャサイズで指定しまわないよう注意!

colorは、減色ができる。
指定しなければ、元の色のまま描画される。
色付きの長方形を描画する命令を出したときは(drawRectFull(rect,color))、内部では真っ白テクスチャをこのcolor指定で指定色に減色して描画している。


この構造体のインスタンスを作り、自分に必要な変数だけセットしてから、関数の引数として渡すようにします。

//テクスチャeTEXTURE_ID_SAMPLEを、座標(50.f,50.f)が中心になるよう描画
SpriteData data(eTEXTURE_ID_SAMPLE);
data.pos = point_t(50.f, 50.f);
data.anchorPos = point_t(0.5f, 0.5f);
drawTexture(data);

まあこういう感じで使っても良いんですが、setter系関数を用意してあります。
直接値を代入すると間違えやすかったり(radianとdegreeとか)、実は面倒だったり(Rect()関数ならposとsizeが一発指定!)するので、関数使う方がおすすめ。
さらに、どの関数も自身の参照を返すようにしてあるので、setterをどんどん繋げられるようにしてあります。
という訳で、推奨する使い方は以下の通り。

drawTexture(SpriteData(eTEXTURE_ID_SAMPLE).Pos(50.f, 50.f).Anchor(0.5f, 0.5f));

かなりスッキリしているんじゃなかろうか。


ところで、テクスチャとスプライトの区別を誰か分かりやすく教えて。
PR
【2011/03/20 00:43 】 | 自作エンジン | 有り難いご意見(0) | トラックバック()
<<新世界より | ホーム | Inputクラス・実装第2版>>
有り難いご意見
貴重なご意見の投稿














虎カムバック
トラックバックURL

<<前ページ | ホーム | 次ページ>>