前回作ったModelクラス内でテクスチャの読み込みをやりました。
この時テクスチャリソースを渡すようにしましたね。
Modelクラスは表示を楽にするので結構色々なところで使われます。
この時に問題になるのがテクスチャリソースをどうやって渡すかということです。
クラスをかませる度にテクスチャリソースを渡すのは嫌ですね。
そこで、テクスチャリソースなど色々なところで使うクラスは
なるべく他のクラスを経由しないようにしようというのが今回やってみることです。
テクスチャリソースをたらい回さないようにするためには
あらゆるところからアクセスできるところに置くのが楽です。
そこで、テクスチャリソースをどこかひとつのクラスに持たせて
staticメソッドでアクセスできればよさそうです。
なので、staticメソッドだけを持ったクラスを作ることにしましょう。
クラス名はAppとしてソースをまずは追加しましょう。
ソース名は”App.java”です。
ソースの中身はとりあえず必要最低限の物を書いておきます。
package com.hitman; // アプリケーションクラス public class App { }
このクラス内でstaticなテクスチャリソースを持てばいい!
JavaならそれでOKです。
しかし、今回はC++的なトラップも絡めつつ説明をすると面白いのであえて別の方法を使ってみます。
C++でstaticとしてクラスを持つと開放順序の制御ができません。
(全くできなわけではないがかなり面倒)
その結果、予期せぬ開放順序によりハングしたりします。
そこで、このクラスでstaticで持つものはこのクラスのインスタンスのみにし、
他のものは作成元で解放するようにして順番を制御します。
なお、開放順序を気にせず解放する方法にフェニックスシングルトンというものがあります。
興味がある人は調べてみてください。
では、早速実装して行きましょう。
このクラスでstaticで持つものはこのクラスのインスタンスなので
コンストラクタとメンバ変数を↓のように追加します。
// コンストラクタ private App() { super(); } private static App s_Instance = null;
次にインスタンスを取得できるようにします。
この時にインスタンスがnullなら作るようにします。
// インスタンス取得 private static App GetInstance() { if( s_Instance == null ) { s_Instance = new App(); } return s_Instance; }
では、テクスチャリソースにアクセスできるようにしましょう!
メソッドとメンバ変数を追加します。
// 取得 public static TextureResource GetTextureResource() { return GetInstance().m_TexRes; } : // コンストラクタ private App() { super(); m_TexRes = null; } : private TextureResource m_TexRes;
これででき……てませんね。。。
まだテクスチャリソースがnullのままです。
テクスチャリソースを設定できるようにしましょう!
// 設定 public static void SetTextureResource( TextureResource texRes ) { GetInstance().m_TexRes = texRes; }
これだけです。
しかし、このメソッドは少々問題があります。
このクラスにアクセスするクラスは取得さえあればいいわけです。
が、設定まで存在するとどこからか書き換えられてしますかもしれません。
これでは困るのでC++の場合はfriendというものを使って特定のクラスにのみ
privateメンバにアクセスする方法があります。
が、Javaには無いので諦めちゃいます。。。
早速このクラスを使ってみましょう!
MainActivityからテクスチャリソースを設定します。
// 作成 @Override public void onCreate( Bundle savedInstanceState ) { : m_TexRes = new TextureResource( m_AppRes, m_DrawDevice ); App.SetTextureResource( m_TexRes ); : }
テクスチャリソースを作った後に設定します。
簡単ですね。
では、ModelクラスもAppクラスを使うようにしてみましょう!
: // 背景作成 public void CreateBack( String imageName ) { _LoadImage( imageName, TextureResource.TEXTURE_TYPE.BACK ); _CreateDrawInfo( 0.0f, 0.0f, 0, 0, ( int )DrawDevice.DRAW_WIDTH, ( int )DrawDevice.DRAW_HEIGHT ); } // キャラ作成 public void CreateChara( String imageName ) { _LoadImage( imageName, TextureResource.TEXTURE_TYPE.CHARA ); final float width = m_Image.GetWidth(); final float height = m_Image.GetHeight(); _CreateDrawInfo( width * 0.5f, height, 0, 0, ( int )width, ( int )height ); } : // テクスチャ読み込み private void _LoadImage( String imageName, TextureResource.TEXTURE_TYPE texType ) { m_Image = App.GetTextureResource().Load( imageName, texType ); }
テクスチャリソースを渡す必要がなくなりました!
呼び出し側も適宜削除してください。
これで他にも全体からアクセスしたいものが出てきたときは
このクラスに追加すればよくなります。