Zurück   Flashforum > Flash > ActionScript > Softwarearchitektur und Entwurfsmuster

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 11-05-2011, 17:56   #1 (permalink)
Neuer User
 
Registriert seit: Feb 2011
Beiträge: 32
Status verwalten/ändern

Hi,
ich bins mal wieder mit einer Design-Frage...

Stellen wir uns mal ein Adventure-Spiel vor. In dem Spiel gibt es eine verschlossene Tür. Wenn der Spieler drauf klickt wird eine Sprachfrequenz abgespielt, dass die Tür noch verschlossen ist. Erst wenn er einen geheimen Knopf gedrückt hat soll die Tür beim Klick aufschwingen.

Das war jetzt nur exemplarisch eine Situation, wo der Zustand eines Objekts (Tür offen/geschlossen) vom Zustand eines anderen Objekts abhängt (Geheimknopf nicht gedrückt/gedrückt). Wie würdet ihr den Code zur Verwaltung schreiben?

Meine Idee: Die Tür kennt den Geheimknopf nicht direkt sondern geht einen Umweg über einen Status-Manager. Der Statusmanager hört auf Events von allen Objekten. Wenn er dann mitbekommt dass der Geheimknopf gedrückt wurde informiert er die Tür darüber, die dann ihren Zustand von verschlossen auf geöffnet ändert.
Was haltet ihr davon?

Viele Grüße!
Paratron ist offline   Mit Zitat antworten
Alt 11-05-2011, 18:08   #2 (permalink)
Keine Panik
 
Registriert seit: Apr 2010
Ort: Düsseldorf (im ernst)
Beiträge: 2.799
Zitat:
Wie würdet ihr den Code zur Verwaltung schreiben?
im Grunde genauso wie du es beschrieben hast.

PHP-Code:
//im StatusManager
secretButton.addEventListener(MouseEvent.CLICKunockDoor);
function 
unlockDoor(e:MouseEvent):void
{
    
door.locked false;
// oder 
    
door.unlock();
// je nachdem was dir lieber ist.

__________________
greetz Thomas

plz RTFM & Coding Conventions
thomas_E ist offline   Mit Zitat antworten
Alt 11-05-2011, 20:05   #3 (permalink)
Neuer User
 
Registriert seit: Feb 2011
Beiträge: 32
okay, aber wie verwalte ich die einzelnen objekte? ich mcöhte sie ja nicht im statusmangaer instanziieren...

außerdem in einem größeren spiel wird die stateklasse ja riesig denke ich! hat jemand weitere ideen dazu?
Paratron ist offline   Mit Zitat antworten
Alt 11-05-2011, 20:26   #4 (permalink)
Flash-Designer
 
Benutzerbild von Martin Kraft
 
Registriert seit: May 2006
Ort: Wiesbaden
Beiträge: 7.306
Ich glaube Du denkst da viel zu kompliziert. Im Endeffekt geht es doch nur darum, dass eine Instanz ein Ereignis in einer anderen Instanz mitbekommt ohne, dass sich die beiden Instanzen kennen.

Man benötigt also einen Mittler zwischen beiden, der idealerweise auch keine festen Referenzen auf beide enthält, aber von überall aus ansprechbar ist. Und genau für diesen Zweck habe ich mir eine Art toten Briefkasten gebaut, der als Singleton (*wegduck*) global ansprechbar ist (*hinterDem SchrankVersteck*) und Ereignisse von Objekten weiterreicht, ohne das er sie oder sie sich kennen müssen:
PHP-Code:
package net.martinkraft.utils {
    
import flash.events.Event;
    
import flash.events.EventDispatcher;
    
    
/**
     * @author Martin Kraft
     */
    
    
public class StaticEventDispatcher extends EventDispatcher{
        
        
////
        
        
private static var _instance:StaticEventDispatcher;
        
        
///////////////////////////////////////////
        
        
public function StaticEventDispatchersi:SingleInstance ) {
            
super();
        }
        
        
///////////////////////////////////////////
        
        // Instance functions to static
        
        
static public function addEventListener(type:Stringlistener:Function, useCapture:Boolean falsepriority:int 0useWeakReference:Boolean true):void {
            
instance.addEventListener(typelisteneruseCapturepriorityuseWeakReference);
        }
        
        static public function 
dispatchEvent(event:Event):Boolean {
            return 
instance.dispatchEvent(event);
        }
        
        static public function 
hasEventListener(type:String):Boolean {
            return 
instance.hasEventListener(type);
        }
        
        static public function 
removeEventListener(type:Stringlistener:Function, useCapture:Boolean false):void {
            
instance.removeEventListener(typelisteneruseCapture);
        }
        
        static public function 
willTrigger(type:String):Boolean {
            return 
instance.willTrigger(type);
        }
        
        
////
        
        
static public function get instance():StaticEventDispatcher 
            if(!
_instance_instance = new StaticEventDispatcher( new SingleInstance() );
            return 
_instance;
        }
        
    }
}

internal class SingleInstance {
    
/// protects Singleton
    
public function SingleInstance():void { }

Das einzige, was Du jetzt noch benötigst ist eine Eigene Event-Klasse mit String-Konstanten für alle Zuständen, die Du blind durch die Gegend schicken möchtest...

P.S.: Ich überleg mir gerade die Klasse wirklich in DeadLetterOffice umzubennen
__________________
Viele Grüße // Martin

Martin Kraft // Interaktionsdesign

Hilfreiche Websites:
// Hilfe zur Adobe Flash Plattform
// ActionScript 2 Referenz
// ActionScript 3 Referenz
// ActionScript 3 Arbeitshandbuch
// weitere Flash Ressourcen

Bitte keine Flashfragen per PM oder Profilnachricht! Dafür ist das Forum da!

Geändert von Martin Kraft (11-05-2011 um 20:28 Uhr)
Martin Kraft ist offline   Mit Zitat antworten
Alt 11-05-2011, 21:00   #5 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Bremen
Beiträge: 13.419
Verstehe ich nicht, es sind doch anscheinened immer 2 Instanzen, die miteinander assoziiert werden. Da braucht man keinen globalen EventDispatcher, da die Instanzen sich eh kennen.

Man bräuchte eigentlich nur zwei Interface
Code:
package fs.secrets
{
  public interface IAliBaba
  {
    function set sesame(value:ISesame):void;    
  }
}
Code:
package fs.secrets
{
  public interface ISesame
  {
    function set aliBaba(value:IAliBaba):void
  }
}
Und was nun wie genau miteinander interagiert, kann man aus der Entfernung hier eh nicht wirklich ausmachen. Alternativ könnte ein Schlüssel natürlich auch mehrere Locks lösen. Aber auch da können sich die Instanzen kennen.

Ich würde eine Form von IoC nutzen, da spart man sich viel Stress und der Singleton ist egal.
Omega Psi ist gerade online   Mit Zitat antworten
Alt 11-05-2011, 21:04   #6 (permalink)
Neuer User
 
Registriert seit: Feb 2011
Beiträge: 32
Achtung! Post bezieht sich auf Martins Antwort!

okay das stimmt eigentlich. könntest du noch mal kurz ein beispiel mit meiner knopf-tür-geschichte machen?

Ein toter Briefkasten ist es nicht wirklich oder, weil eigentlich nichts reingelegt wird?


Code:
secretButton.addEventListener(MouseEvent.CLICK, unockDoor);
function unlockDoor(e:MouseEvent):void
{
   StaticEventDispatcher.instance().dispatchEvent(StatusEvent.OPEN_DOOR);
}
Code:
door.addEventListener(StatusEvent.OPEN_DOOR, unlock);
Ist das korrekt so?

Geändert von Paratron (11-05-2011 um 21:08 Uhr)
Paratron ist offline   Mit Zitat antworten
Alt 11-05-2011, 21:08   #7 (permalink)
Keine Panik
 
Registriert seit: Apr 2010
Ort: Düsseldorf (im ernst)
Beiträge: 2.799
@Martin, und an der Stelle gehen die Meinungen scheinbar auseinander.

du löst das (zumindest hier) über eine schier endlose Anzahl an eigenen Events, die zentral über deinen DeadLetterOffice schickst.
Nachteil für mich: Wer ist dafür zuständig, die visuellen Elemente auf die Bühne zu packen, Events zu registrieren und wieder zu löschen?

ich würde pro Screen einen Controller anlegen, der seine Schäfchen kennt, Objekte instanziert, Events empfängt, Aktionen auslöst, und vor allen dingen Objekte und Events wieder sauber entfernt.
sprich alles verwaltet, was in diesem Bild/Raum/Fenster möglich ist, und dem Screenmanager mitteilt, wann es zeit ist, einen anderen Screen anzuzeigen.
klingt erstmal kompliziert, aber im Grunde ist das nicht mehr als ein Sprite, mit init und dispose-funktion, wo Events registriert und wieder gelöscht werden.
die Visuellen Teile kannst du hier sowohl programmieren, als auch in der Flash-IDE anlegen.
__________________
greetz Thomas

plz RTFM & Coding Conventions
thomas_E ist offline   Mit Zitat antworten
Alt 11-05-2011, 21:14   #8 (permalink)
Perverted Hermit
 
Benutzerbild von Omega Psi
 
Registriert seit: Mar 2004
Ort: Bremen
Beiträge: 13.419
Thomas beschreibt letzten Endes gar noch mehr als das Problem. Strukturell ist das aber die bessere Variante.
Omega Psi ist gerade online   Mit Zitat antworten
Alt 11-05-2011, 21:24   #9 (permalink)
Keine Panik
 
Registriert seit: Apr 2010
Ort: Düsseldorf (im ernst)
Beiträge: 2.799
Zitat:
Zitat von Paratron Beitrag anzeigen
Ist das korrekt so?
nicht ganz.
PHP-Code:
public class GameEvent        //weil StatusEvent gibbet bereits
{
    public static const 
OPEN_DOOR:String 'obenDoor1';
    public static const 
OPEN_DOOR_2:String 'obenDoor2';
    public static const 
OPEN_DOOR_3:String 'obenDoor3';
//...
    
public static const DO_SOMETHING_AT_LEVEL_42:String 'omfg';

PHP-Code:
secretButton.addEventListener(MouseEvent.CLICKunlockDoor);    //im Controller
//oder 
addEventListener(MouseEvent.CLICKunlockDoor);    //in secretButton

//dort wo die Zeile oben definiert wurde
function unlockDoor(e:MouseEvent):void
{
   
StaticEventDispatcher.dispatchEvent(new Event(GameEvent.OPEN_DOOR));

PHP-Code:
//in Door
StaticEventDispatcher.addEventListener(GameEvent.OPEN_DOORunlock);
function 
unlock(e:Event):void
{
    
trace('got unlocked');

und bei der zweiten Tür heisst es dann dispatchEvent(new Event(GameEvent.OPEN_DOOR_2));, OPEN_DOOR_3, etc.
weil wir wollen ja nicht, dass der erste Event direkt alle anderen Türen mit öffnet

@Paratron, und jetzt vergleich das mit dem Dreizeiler, den ich in meiner ersten antwort geschrieben habe


Zitat:
Zitat von Omega Psi Beitrag anzeigen
Thomas beschreibt letzten Endes gar noch mehr als das Problem.
was mach ich?
__________________
greetz Thomas

plz RTFM & Coding Conventions

Geändert von thomas_E (11-05-2011 um 21:29 Uhr)
thomas_E ist offline   Mit Zitat antworten
Alt 11-05-2011, 21:44   #10 (permalink)
Neuer User
 
Registriert seit: Feb 2011
Beiträge: 32
okay danke für die ausführen. aber das ist eurer meinung nach nicht die optimale lösung, höre ich raus es ist in der tat können sich sehr viele String-Konstanten in der Event-Klasse ansammeln, wenn das Projekt wächst.

Omega Psi's Idee kann ich leider nicht so ganz nachvollziehen. Es geht darum die beiden Objekte die miteinander zu interagieren miteinander bekannt zu machen, right? Also wenn ich den Geheimschalter instanziiere kann ich folgendes machen:
Code:
schalter:Sender= new Geheimschalter();
tuer:Empfänger = new Tuer();
schalter.setEmpfaenger(tuer);
Aber ne, das bringts ja auch nicht Bitte noch um kurze Erklärung!


Thomas Lösung ist ja eigentlich recht einfach. An der Stelle wo ich meine Sprites instanziiere füge ich auch direkt EventListener ein. Wer soll die init() und dispose() Funktionen anbieten und was bewerkstelligen die genau? Und was ist wenn der Geheimknopf im Keller ist und die Tür im ersten Stock aufgehen soll?

Sry fürs Nerven. Bin noch neu im OO-Design, will aber nichts vermurksen...
Paratron ist offline   Mit Zitat antworten
Alt 11-05-2011, 23:25   #11 (permalink)
JoH
Neuer User
 
Registriert seit: Dec 2005
Beiträge: 99
MVC?
Dein Geheimschalter(View) führt entsprechenden GeheimschalterController(Controller) aus der dann den state im Model (irgendwelche Türen wurden freigeschaltet oder verschlossen) setzt.
Verstehe das Problem nicht ganz.
__________________
http://blog.johannes-hodde.com
JoH ist offline   Mit Zitat antworten
Alt 12-05-2011, 07:29   #12 (permalink)
Neuer User
 
Registriert seit: Feb 2011
Beiträge: 32
Das Problem liegt daran, dass die Application bisher nicht nach ModelViewController aufgebaut ist. Ist das üblich bei Spielen?

Ich habe mich mehrere Wochen mit Entwurfsmustern beschäftigt, aber MVC nicht richtig verstanden. Ich verstehe nicht wie ich die Funktionalität meiner Objekte auf 3 verschiedene Klassen aufteilen soll? Bzw. wo instanziiere ich z.B. das Türobjekt (Model, View oder Controller?) und wie mache ich dann diese Instanz den beiden anderen Komponenten bekannt?
Paratron ist offline   Mit Zitat antworten
Alt 12-05-2011, 08:14   #13 (permalink)
Developer
 
Benutzerbild von malthoff
 
Registriert seit: Sep 2001
Ort: Stuttgart
Beiträge: 519
Mvc, ioc, dpi

Hallo.

Wenn Du neu bist in OOP hast Du mit Flash eine tolle Umgebung gefunden es zu lernen. Was Du Dir anlesen solltest ist ganz klar MVC(Model-View-Control), was Du wahrscheinlich an jeder Ecke schon gehört hast. Das trennt deine visuellen Anteile der Anwendung (VIEW) von den Teilen, die auf die Benutzerinteraktion hören und daraufhin entsprechende Anwendungslogiken starten (CONTROL(ler)) und dem Teil, der den Anwendungszustand speichert (MODEL).

Auf diesem "Meta" Pattern (weil es viele einzel OOP Design Pattern vereint, um GROSSES zu schaffen :-)) basieren andere DPI(Dependency Injection) Frameworks, die das Problem umgehen, was Du richtig mit "Bekanntmachung der Objekte" beschrieben hast. Dependency Injection bedeutet nicht mehr, als das einem Objekt seine Abhängigkeiten (andere Objekte) injeziert werden - und zwar automatisch und nicht mehr über "boilerplate code", also Code, der nur für das Zusammenfügen von Objekten anstelle von Anwendungslogik zuständig ist.

Eines dieser Frameworks ist Robotlegs. Dieses solltest Du Dir umbedingt mal anschauen, vielleicht das best-practises Dokument lesen, einfach um die Idee davon mit zu nehmen.

Auf dein Problem bezogen: Du schreibst Dir also eine Klasse für deine Szene (View) und einen dazugehörigen Controller (eigene Klasse), der die View Instanz kennt und sich bei dieser für eventuelle Events anmeldet. Wenn jetzt jemand auf den Secret Button klickt, hört der Controller auf das ClickEvent (oder ein eigenes Event, was noch andere Informationen enthält) und ändert daraufhin den Zustand im Model, dessen Instanz dem Controller ebenfalls bekannt ist. So hast Du den Controller als vermittelnde Instanz zwischen der View und dem Modell.

In deiner Szene (neue View), in der die Tür enthalten ist, die von dem Secret Button abhängt, holt sich zu Beginn der korrespondierende Controller (ebenfalls neuer Controller) den aktuellen Wert des Secret Button aus dem Model (wie gesagt, die Controller haben Zugriff aufs Model) und vergleicht bei Klick auf die Tür, diesen Wert. Natürlich kann der Controller auch erst bei dem Klick Event auf die Tür, auf welches er ja hört, den Secret Button Wert aus dem Model holen.

Diese Controller werden auch gerne Mediatoren genannt (z.B im Falle von Robotlegs), was dem Begriff Vermittler näher kommt.

Und ja, natürlich wird das Modell irgendwann riesig, wenn das Spiel wächst. Irgendwo muss der Zustand aber gespeichert werden. Bei steigender Komplexität kann man auch "das" Modell in mehrere kleinere und das Spiel in Module aufteilen. Bestimmte Zustände im Spiel sind ja auch nur für einen bestimmten Abschnitt relevant. Bei Robotlegs gibt es auch dafür eine Erweiterung.

Kurz noch, wie Robotlegs das Schreiben von "Bekanntmachungs-Code" umgeht: Zu Beginn der Anwendung registrierst Du entsprechende Klassen in einem Injektor. Dieser weiß ab dem Moment, falls irgendeine Klasse signalisiert, dass es z.B das Model benötigt, welche Klasse er instanzieren und injezieren muss. Dieses Signalisieren passiert tatsächlich darüber, dass du öffentlichen Variablen in deiner Klasse ein [INJECT] anfügst.
PHP-Code:
[INJECT]
public var 
model:MyModel 
Sobald also eine Instanz dieser Klasse erzeugt wird schaut Robotlegs nach, ob es dort eine Variable findet, die mit INJECT gekennzeichnet ist, schaut in seiner internen Map nach, ob dort eine entsprechende Klasse oder bereits Instanz dieser registriert ist und setzt diese Variable AUTOMATISCH.

Letztlich das gleiche, als wenn Du der Klasse dieses Objekt per Konstruktur beim Instanzieren übergeben hättest - nur ohne zusätzlichen Code.

Geändert von malthoff (12-05-2011 um 08:17 Uhr)
malthoff ist offline   Mit Zitat antworten
Alt 12-05-2011, 09:32   #14 (permalink)
Flash-Designer
 
Benutzerbild von Martin Kraft
 
Registriert seit: May 2006
Ort: Wiesbaden
Beiträge: 7.306
Dacht' ich's mir doch, dass ich für den StaticEventDispatcher mal wieder Prügel beziehe

Zitat:
Zitat von thomas_E Beitrag anzeigen
du löst das (zumindest hier) über eine schier endlose Anzahl an eigenen Events, die zentral über deinen DeadLetterOffice schickst.
Eigentlich benötigt man ja nur ein Event mit einer Anzahl an String-Konstanten, die auch nicht höher ist, als wenn ich die verschiedenen Ereignisse direkt übertrage.

Zitat:
Zitat von thomas_E Beitrag anzeigen
Nachteil für mich: Wer ist dafür zuständig, die visuellen Elemente auf die Bühne zu packen, Events zu registrieren und wieder zu löschen?
Natürlich wäre es schicker, wenn man das ganze Speiel hierachisch so aufbauen würde/könnte, dass es immer einen Controler gibt, der die Interaktion zweier Objekte organisiert.

Ich hatte Paratron jedoch so verstanden, dass es darum geht, ein bestehendes Szenario um eine Art Schmetterlingsflügeleffekt zu ergänzen?! D.h. es passiert an einer beliebigen Stelle irgendetwas, was an einem ganz anderen, logisch damit nicht verknüpften Ort (z.B. in einem anderen View) irgendeine Reaktion hervorruft.

Und wenn man von dieser Annahme ausgeht, ist es IMHO um ein vielfaches einfacher, das auf die beschreibene Weise zu implementieren, als die komplette Hierachie anzupassen um irgendwie eine Verbindung zwischen diesen beiden Orten hinzubekommen und damit Unmengen überflüssiger Bindungen zu produzieren.
__________________
Viele Grüße // Martin

Martin Kraft // Interaktionsdesign

Hilfreiche Websites:
// Hilfe zur Adobe Flash Plattform
// ActionScript 2 Referenz
// ActionScript 3 Referenz
// ActionScript 3 Arbeitshandbuch
// weitere Flash Ressourcen

Bitte keine Flashfragen per PM oder Profilnachricht! Dafür ist das Forum da!

Geändert von Martin Kraft (12-05-2011 um 09:34 Uhr)
Martin Kraft ist offline   Mit Zitat antworten
Alt 12-05-2011, 09:39   #15 (permalink)
Developer
 
Benutzerbild von malthoff
 
Registriert seit: Sep 2001
Ort: Stuttgart
Beiträge: 519
@Martin: Wieso nicht über ein ausgelagertes Modell auf welches sich beide Spielszenen beziehen?
malthoff ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Schaltflächen Status ändern SKVler ActionScript 2 2 13-03-2010 15:51
Verwalten mit XML D-Tox Flash Einsteiger 2 07-11-2006 14:28
Schaltflächen Status ändern pachita ActionScript 1 5 09-12-2004 01:23
bei mouseover status cursor ändern? Sascha_oba Flash 4 und Flash 5 2 10-05-2002 15:23
Ändern des Status eines Rolloverbildes mit Action Script Mattula ActionScript 1 1 27-07-2001 16:02


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:32 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2014 Marc Thiele