0

私は単純な 2D ゲーム エンジンをプログラミングしています。エンジンをどのように機能させるかを決めました。エンジンは、必要に応じてメインのゲーム ループがトリガーする「イベント」を含むオブジェクトで構成されます。

構造についてもう少し: すべてGameObjectにはupdateEventメソッドがあります。 objectList更新イベントを受け取るすべてのオブジェクトのリストです。このリストにあるオブジェクトだけが、ゲーム ループによって updateEvent メソッドが呼び出されます。

このメソッドを GameObject クラスに実装しようとしています (この仕様は、メソッドで達成したいものです) :

/**
* This method removes a GameObject from objectList.  The GameObject 
* should immediately stop executing code, that is, absolutely no more
* code inside update events will be executed for the removed game object.
* If necessary, control should transfer to the game loop.
* @param go The GameObject to be removed
*/
public void remove(GameObject go)

そのため、オブジェクトが更新イベント内で自身を削除しようとすると、制御がゲーム エンジンに戻されます。

public void updateEvent() {
    //object's update event
    remove(this);
    System.out.println("Should never reach here!");
}

これが私がこれまでに持っているものです。それは機能しますが、フロー制御に例外を使用することについて読めば読むほど気に入らなくなるので、代替手段があるかどうかを確認したいと思います。

メソッドの削除

public void remove(GameObject go) {
    //add to removedList
    //flag as removed
    //throw an exception if removing self from inside an updateEvent
}

ゲームループ

for(GameObject go : objectList) {
    try {
        if (!go.removed) {
            go.updateEvent();
        } else {
            //object is scheduled to be removed, do nothing
        }
    } catch(ObjectRemovedException e) {
        //control has been transferred back to the game loop
        //no need to do anything here
    }
}
// now remove the objects that are in removedList from objectList

2 つの質問:

  1. 上記の remove メソッドの stop-right-away 部分を実装する唯一の方法は、カスタム例外をスローしてゲーム ループでキャッチすることであると想定するのは正しいですか? (フロー制御に例外を使用するのは goto のようなものですが、これは悪いことです。自分がやりたいことを行う別の方法が思い浮かびません!)

  2. リスト自体からの削除では、1 つのオブジェクトがリストのさらに下にあるオブジェクトを削除することができます。現在、コードを実行する前に削除済みフラグをチェックしており、各パスの最後にオブジェクトを削除して同時変更を回避しています。これを行うためのより良い、できればインスタント/非ポーリングの方法はありますか?

[編集] あなたの回答を読んだ後、メソッドの仕様を変更すると思います。インスタント削除の動作は、私が別のエンジンでの作業に慣れているものですが、その通りです。Java の動作に実際には適合しません。ちょっと違う考え方を頭に入れてみよう!

4

4 に答える 4

2

仕様に従って remove メソッドを実装するには、例外アプローチが最適な方法であることに同意します。

ただし、仕様を再検討する必要があるかもしれません。updateEvent がいつ終了するかの決定は、実装者に任せます。remove() 呼び出しによる終了は紛らわしく、フロー制御のために例外を使用する必要があります。remove() の呼び出しは、フラグの状態のみを変更する必要があると思います。そして、すべてのオブジェクトをループして、それぞれの削除済みフラグをチェックしても問題はありません。

于 2010-06-16T21:07:30.330 に答える
1

単に戻ってみませんか、つまり、

public void updateEvent() { 
    //object's update event 
    remove(this); 
    return;   
    //obviously unreachable 
    System.out.println("Should never reach here!");     }
于 2010-06-16T20:54:20.690 に答える
1

次のことをしてみませんか。

  • ループを実行するオブジェクトで objectList を維持する
  • ゲームオブジェクトがリストにアクセスできないようにします (なぜアクセスする必要があるのでしょうか?)
  • updateEvent 関数がブール値を返すようにします。戻り値が false の場合、親オブジェクトはそのオブジェクトをイベントのリストから削除します。return ステートメントは、イベント関数の実行を終了する役割も果たします。
于 2010-06-16T20:55:59.453 に答える
1

@jballの答えは素晴らしいです-+1。

私が使用したもう 1 つの方法は、updateEvent() メソッドがブール値を返すようにすることです。updateEvent から True が返されるたびに、オブジェクトを remove() します。

これにより、イベント ループがループ自体の実行方法をより詳細に制御できるようになり、クラス間の不要なバインドが少し削除されます。

于 2010-06-16T21:02:56.707 に答える