イベントを処理するための効率的な方法、Observer Patternのようなものである可能性があります。私は、このパターンのバリエーションを、私が作業しているプラットフォームのゲーム用のライブラリに使用しました。ここで、オブザーバーは特定のイベントを購読します。それは私のためにとてもうまく働いているので、私はそれを分かち合うことができると思った。
ここに私の基本クラスです:
1)BaxEventSubscriberが
interface BaxEventSubscriber {
function getNotified(baxEventKey:String):Void;
}
2)BaxEvent
class BaxEvent implements BaxEventSubscriber
{
public var id:String;
/** Event will be fired when all prequisite events are triggered.
* Once a prequisite is satisfied, it will be removed from this list.
* When the list is empty, the event will trigger */
public var prequisiteEvents:Array<String>;
/**
* If serialExecution is true, the prequisites must be executed in a serialised order (first to last)
* In other words, every prequisite will be satisfied only if it is first in the prequisited list
*
* If serial execution is false (default, the prequisites can be satisfied in any order)
*/
public var serialExecution : Bool = false;
public function new (id:String)
{
if (id == null) {
throw "any Event should have an id";
}
this.id = id;
prequisiteEvents = new Array<String>();
}
public function addPrequisite(key:String):Void {
if (key == null || key.length == 0) {
return;
}
var isUnique:Bool = true;
for (i in 0...prequisiteEvents.length) {
var ss:String = prequisiteEvents[i];
if (ss == key) {
isUnique = false;
}
}
if (isUnique) {
prequisiteEvents.push(key);
BaxEventManager.getManager().addSubscriberForEvent(this, key);
}
}
public function getNotified(baxEventKey:String):Void {
this.eventTriggered(baxEventKey);
}
public function eventTriggered(key:String):Void {
var isPrequisite :Bool = false ;
for (i in 0...prequisiteEvents.length) {
var ss:String = prequisiteEvents[i];
if (ss == key) {
isPrequisite = true;
}
}
if (isPrequisite) {
var ind:Int = prequisiteEvents.indexOf(key);
// If no serialExecution, checkout this event.
// Else, check it out only if it's the first on the prequisites list
if (! serialExecution || ind == 0 ) {
prequisiteEvents.splice(ind, 1);
}
}
// if all prequisites are satisfied, fite the Event
if (prequisiteEvents.length == 0) {
BaxEventManager.getManager().broadcastEvent(this.id);
}
}
}
3)BaxEventManager
class BaxEventManager
{
/** the names of registered Events */
public var events:Array<BaxEvent>;
/**
* Objects that need to be notified for a certain event
*
* structure:
* [key] = event name (as in events[])
* subscribers : Array<BaxEventSubscriber> : an array of subcribers for this Event
*/
public var eventSubscribers : StringMap<Array<BaxEventSubscriber>>;
private static var eventManager:BaxEventManager;
public static inline function getManager():BaxEventManager {
if (eventManager == null)
return eventManager = new BaxEventManager();
else
return eventManager;
}
private function new() {
trace(" BaxEventManager CONSTRUCT");
events = new Array<BaxEvent>();
eventSubscribers = new StringMap<Array<BaxEventSubscriber>>();
}
/**
* Registers an event's key, and an array with Subscribers for it. FailSafe, as it checks if event already exists
* @param key
*/
public function addEvent(key : String):Void {
//trace("check to add key :"+key);
var alreadyExists :Bool = false;
for (i in 0...events.length) {
var ss :String = events[i].id;
if (ss == key) {
//trace("key " + key + " exists");
alreadyExists = true;
break;
}
}
if (!alreadyExists) {
events.push(new BaxEvent(key));
var subscribers : Array<BaxEventSubscriber> = new Array<BaxEventSubscriber>();
eventSubscribers.set(key , subscribers);
}
}
public function addSubscriberForEvent(subscriber:BaxEventSubscriber, eventKey:String):Void {
this.addEvent(eventKey);
var subscribers :Array<BaxEventSubscriber> = eventSubscribers.get(eventKey);
subscribers.push(subscriber);
}
public function broadcastEvent(evt:String) : Void {
if (evt == null) {
return;
}
var subscribers :Array<BaxEventSubscriber> = eventSubscribers.get(evt);
if (subscribers != null && subscribers.length > 0) {
for (i in 0...subscribers.length) {
var sub:BaxEventSubscriber = subscribers[i];
sub.getNotified(evt);
}
}
}
/**
* Clears up the registered Events and their subscribers.
* Make sure to Call this when resseting a level, as the subscribers might be nullified
*/
public function clearEvents():Void {
ArrayUtils.emptyArray(events);
eventSubscribers = null;
eventSubscribers = new StringMap<Array<BaxEventSubscriber>>();
}
}
私の実際の実装では、ゲームセッションごとに一度登録(および起動)する必要があるかどうかを定義するさまざまな種類のイベントも使用しています。今私はそれについて考えているので、これをBaxEventクラスに含めるべきです。
とにかく、ポイントはこの設計
- であなたがトリガーされるイベントをよりよく制御することが、すでに
- を解雇されたイベントあなたは上の反復する必要はありません、それは追跡することが容易だということですすべてのイベントまたは購読者を介した更新機能
- 拡張可能で、レベルイベント(収集したすべてのコイン)、ウォークイベント、完了したダイアログ、スイッチおよびインタラクティブオブジェクトなど、さまざまな種類のイベントに使用できます。
イベント・マネージャはシングルトン・クラスですが、静的ユーティリティ・クラスとして設計することもできます。
BaxEventがEventサブスクライバを実装する唯一の理由は、複雑なイベントをサポートすることであり、その前提条件(他のイベント)が満たされると、イベントは発生します。しかし、これがあなたにとって過酷な場合は、この機能を削除してコードを単純化することができます。
役立つリンクがいくつかあります。次のイベントを持つhaxeflixel rpgベースコードプロジェクトがあります:https://github.com/kevinresol/flixel-rpgまた、私はhaxeflixelに束縛されていないイベントのためにmsignalを愛しています(したがって、ループの種類がなく、うまくいかないかもしれません)。https://github.com/massiveinteractive/msignal – 5Mixer
パフォーマンスのボトルネック?利用可能なイベントのチェック?フレーム更新機能?すべての部屋で何百ものイベントが開催されていない限り、これはパフォーマンスに何ら変わるものではないと思いますが、そうはいかないでしょう。一般に、パフォーマンスは、ゲームロジックではなく、画像のレンダリング、グラフィックス、オーディオ、アセットのロードおよびアンロードなどの影響を受けます。 –
私は、その後、私はそのアプローチに固執するよ、ありがとう! –