今はこれが精一杯-2
前回の続きです。
1枚のテクスチャを使って表示されるオブジェクトが1つだけの場合
例えば、背景とか、レースゲームでユーザーが操作する車とか、そういう単純なパターンも割と多いです。
こういう場合は、前回のTextureDrawerとほぼ同じことをするだけで十分と思われます。
一応、C++で書きます。
template <typename T, typename C> class SimpleTextureObject { public: SimpleTextureObject(); virtual ~SimpleTextureObject(); virtual void Draw(GLuint); public: T x, y, width, height, u, v, tw, th; C r, g, b, a; protected: void Clear(); }; template <typename T, typename C> SimpleTextureObject<T, C>::SimpleTextureObject() { Clear(); } template <typename T, typename C> SimpleTextureObject<T, C>::~SimpleTextureObject() { } template <typename T, typename C> void SimpleTextureObject<T, C>::Draw(GLuint texture) { GLfloat vertices[] = { x - width / 2, y - height / 2, x + width / 2, y - height / 2, x - width / 2, y + height / 2, x + width / 2, y + height / 2, }; GLfloat texCoords[] = { u, v + th, u + tw, v + th, u, v, u + tw, v, }; glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture); glVertexPointer(2, GL_FLOAT, 0, vertices); glEnableClientState(GL_VERTEX_ARRAY); glColor4ub(r, g, b, a); glDisableClientState(GL_COLOR_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } template <typename T, typename C> void SimpleTextureObject<T, C>::Clear() { x = y = u = v = 0.0f; width = height = tw = th = 1.0f; r = g = b = a = 255; }
テンプレートを使っているのは、座標の型と色の型を汎用的に指定できるようにするためです。
結構面倒臭いソースになってしまいますが、使う側からすると、それほど面倒でもありません。
例えば、アプリの共通ヘッダで
typedef SimpleTextureObject<GLfloat, GLubyte> CpSimpleTextureObject;
こんな風にしてしまうことを想定しています。
使い方ですが、背景のように単純で動かないものに関しては、SimpleTextureObjectをそのまま使うようにします。
@interface ES1Renderer : NSObject<ESRenderer> { // ... Texture* _bgTexture; CpSimpleTextureObject _bg; } @end @implementation ES1Renderer -(id)init { // ... // 背景を初期化する _bgTexture = [[[Texture alloc] initWithImageName:@"hoge.png"] load]; _bg.width = _bg.height = 2.0f; // ... } -(void)renderMain { // 背景を描画する _bg.Draw(_bgTexture.raw); // ... } // ... @end
レースゲームの車のように、独自の座標管理などが必要なクラスは、SimpleTextureObjectから派生させることにします。
class CpCar : public CpSimpleTextureObject { typedef CpSimpleTextureObject inherited; public: CpCar(); void SetControlLeft(bool); void SetControlRight(bool); void SetControlAccel(bool); float GetPosX(); float GetPosY(); float GetAngle(); float GetSize(); void Move(); void Draw(GLuint texture) override; private: float _posX, _posY; // 座標 float _angle; // 向き float _size; // サイズ float _vx, _vy; // 慣性力 bool _controlLeft; // 左ハンドルON/OFF bool _controlRight; // 右ハンドルON/OFF bool _controlAccel; // アクセルON/OFF }; CpCar::CpCar() : inherited() { _posX = -0.5f; _posY = 0.0f; _angle = 0.0f; _size = 0.05f; _vx = _vy = 0.0f; _controlLeft = _controlRight = _controlAccel = false; } void CpCar::SetControlLeft(bool onoff) { _controlLeft = onoff; } void CpCar::SetControlRight(bool onoff) { _controlRight = onoff; } void CpCar::SetControlAccel(bool onoff) { _controlAccel = onoff; } float CpCar::GetPosX() { return _posX; } float CpCar::GetPosY() { return _posY; } float CpCar::GetAngle() { return _angle; } float CpCar::GetSize() { return _size; } void CpCar::Move() { // 左旋回 if (_controlLeft) { _angle += 3.0f; } // 右旋回 if (_controlRight) { _angle -= 3.0f; } // アクセル制御 if (_controlAccel) { float theta = _angle / 180 * M_PI; _vx += cos(theta) * 0.000125f; _vy += sin(theta) * 0.000125f; } // 慣性抵抗 _vx *= 0.98f; _vy *= 0.98f; // 移動 _posX += _vx; _posY += _vy; } void CpCar::Draw(GLuint texture) { inherited::Clear(); inherited::Draw(texture); }
@implementation ES1Renderer -(id)init { // ... // 車を初期化する _carTexture = [[[Texture alloc] initWithImageName:@"hoge.png"] load]; _car = new CpCar(); // ... } -(void)renderMain { // ... glPushMatrix(); glTranslatef(_car->GetPosX(), _car->GetPosY(), 0.0f); glRotatef(_car->GetAngle(), 0.0f, 0.0f, 1.0f); glScalef(_car->GetSize(), _car->GetSize(), 1.0f); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); car->Draw([_carTexture raw]); glDisable(GL_BLEND); glPopMatrix(); // ... } // ... @end
さて、ここまでは、ただ実装がC++になっただけで、以前の設計から内容的には進歩していません。
問題は、同一テクスチャで多数のオブジェクトを描画する場合です。