探索機能をSpriteライブラリに追加する

座標で、そこに位置するSpriteオブジェクトを検索する。

例えば、 『移動しているSpriteの画像をマウスでクリックできたら、その移動を止める』 とか、 『スプライトがある位置に移動したら異なるアクションをする』 、またシューティングゲームなどに使うの衝突検出  などの処理で使える機能です。

画面に表示するSpriteは、SprateTreadオブジェクトのインスタンス変数 subSpriteのArrayListで管理されています。
subSpriteの定義位置はスーパークラスのSpriteクラスなので、そこに作るのがよいでしょう。 しかし、Spriteクラスは汎用のクラスなので、ある作品に特化した仕様で作るわけにはいきません。 将来の指針となるメソッドだけを作るべきクラスだからです。
そこで、任意検索に対応できるように 別途に探すデータとフィットしたか調べるメソッドのインターフェイスを作り、 それを利用した検索メソッドにします。
Spriteクラスに追加する予定の検索メソッド名は、getFitSpritesと決めます。
仕様としては、subSpriteの中から、「ある比較で適合」するオブジェクトを抽出して、 その配列を返すことにします。 そしてインターフェイスに、この「ある比較で適合」判定をfitWithメソッドの名前で 用意します。
このインターフェイスの名前は、単純にSpriteFitInterfaceとして、次のように作りました。
SpriteFitInterface.java

// Spriteの検索メソッドgetFitSprites用インターフェイス(SpriteFitInterface.java)
package sprite;
interface SpriteFitInterface {
	//objとargの情報で、objが探すものに適合したらtrue
    public boolean fitWith(Sprite obj, T arg);//objが適合したらtrue
}

次に、これを利用した次のgetFitSpritesメソッドを、Spriteクラスに追加します。
検索は単純な線形探索ですが、後方から適合したオブジェクトを探して、 戻る時に配列で返します。
なお、後方から探索する理由は、各オブジェクトの描画順が前からになっているので、 後の方が、より前面の画像となり、前面に見える画像のオブジェクトから探すためです。 Spriteクラスに追加するコードを以下に示します。
←チェックでGenericコードになります)最終的版はGenericを使っています。
Sprite.javaのSpriteクラスに追加する部分コード

	//subSpriteの可変長配列から、argの付随情報でobjと合致するSprite群を返す。
	public <T> Sprite [] getFitSprites(SpriteFitInterface<T> obj, T arg){
	    ArrayList <Sprite> lst = new ArrayList <Sprite>();//適合オブジェクト記憶用
	    for(int i = this.subSprite.size()-1; i >= 0; i--){
	        Sprite sprite = this.subSprite.get(i);
	        if( obj.fitWith( sprite , arg) ){//適合したら追加
	            lst.add( sprite );
	        }
	    }
	    Sprite []t = new Sprite[0];
	    return lst.toArray(t);//配列にして返す。
	}

次に、これを利用する「座標に位置するするSpriteオブジェクト」を探すメソッドを、 searchの名前で、SpriteBasicクラスに作ります。以下にそのコードを示します。
SpriteBasic.javaのSpriteBasicクラスに追加する部分コード

	public Sprite [] search(int x, int y){//subSprite内より、引数の座標(x,y)に位置するSprite群を返す。
		Point pt = new Point(x,y);
		SpriteFitInterface<Point> fitObj = new SpriteFitInterface <Point>() {
		    public boolean fitWith(Sprite obj, Point p){//インターフェイスの実装メソッド
		              
		            ImageObserver observer = null;
		            if(obj.parent instanceof SpriteThread){
		                observer = ((SpriteThread)obj.parent).targetComponent;
		            }
		            Dimension size = obj.getSize(observer);
		            Point pt = new Point((int)obj.x, (int)obj.y);
		            Rectangle rect = new Rectangle(pt, size);
		            return rect.contains(p);//座標が長方形エリア内ならtrue
		    }
		};//----SpriteFitInterfaceインターフェイスを継承した匿名クラスの定義範囲
		return getFitSprites(fitObj, pt);// fitObjに適合するsubSprite内オブジェクトを返す		
	}

当然ですが、SpriteFitInterfaceインターフェイスを実装したクラスを作らなければ使えません。 引数の座標(x,y)が探索対象のイメージサイズ内にあるかを判定する機能を、 SpriteFitInterfaceインターフェース実装クラスとしています。
上記では、その実装クラスを、匿名クラスとして作っています
しかしこの名前のないクラス(匿名クラス)は、コンストラクタで引数を持つことができません。 つまり、座標(x,y)の情報を引数で渡せません。 そこで使うのがfitWithメソッド第2引数のです。 内部的にはObject型なので、座標(x,y)でも任意情報も渡せます。

(上記のsearchは、SpriteFitInterfaceインターフェースの利用例とも言えるコードです。 インターフェイスを匿名クラスで実装し、それを引数にしてSpriteのgetFitSpritesメソッドを使っています。)