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

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 10-05-2006, 18:32   #1 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
Lecker Spaghetti

Ich suche ein Pattern für eine AS3 Physicsengine. Die Physicsengine unterstützt bislang zahlreiche Hindernisse und bewegliche Kreise. Alle Hindernisse haben eine Funktion, mit der ich eine dynamische Intersektion mit einem bewegten Kreis berechnen kann.

Jetzt möchte ich die Engine um weitere bewegliche Objekte (Partikel,Kreis,Poly,Flipper,etc.) erweitern. Dafür brauche ich weitere Methoden, um die dynamische Intersektion zu berechnen. Und zwar paarweise.

Eine Resolver Klasse, die zur Auflösung der Simulation vorhanden ist, speichert alle beweglichen und unbeweglichen Objekte in 2 Arrays (movables,statics).
Jetzt ist die Frage, wie ich innerhalb der beiden Loops auf die jeweiligen Methoden komme, welche die dynamische Intersektion berechnen. Das soll möglichst nachvollziehbar (OO), aber letztlich natürlich auch performant laufen.

#A:
Eine Möglichkeit wäre, den Methodennamen aus Strings zusammenzusetzen.
Dabei hätten alle Objekte einen UniqueString. Zum Beispiel: 'MovableParticle' und 'StaticCircle'. Innerhalb des Loops könnte ich dann den Methodennamen zusammenbauen: eval( StringA + StringB ). Ich weiss, dass eval nicht mehr existiert in AS3, aber mit der Array Syntax ('[]') könnte das gehen. Nachteil: Die Typisierung geht verloren.

#B:
Eine andere Idee ist, allen Objekten Bits zu vergeben. Im Loop verknüpfe ich die beiden Bits (performant) 'bitA | bitB' und mache eine switch Anweisung mit allen Cases, die möglich sind und rufe dann die entsprechende Methode auf. Nachteil: Ich kenne die Reihenfolge nicht. Entweder ich müsste immer beide Möglichkeiten in 2 Methoden implementiert haben oder ich tausche die beiden Objekte, wenn die Signatur eine andere Reihenfolge vorgibt.

#C:
Man arbeitet mit instanceof bzw. jetzt 'is'. Letztendlich ist das in etwa wie #B.

##:
Die Lösungen befriedigen mich nicht. Sie sind allesamt Hacks und erzeugen langen SpaghettiCode.


Am schicksten wäre zu Begin eine Anmeldung aller Objektpaare mit deren Methoden an einem MethodTable. Genau dafür bräuchte ich einen Hint.
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 10-05-2006, 19:22   #2 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
Hier eine lauffähige Dummyversion (FlexBeta3, nur Design - keine Physics).

In der Methode Simulation.nextFrame wird die Lösung gesucht.
Angehängte Dateien
Dateityp: zip Revive.zip (28,4 KB, 23x aufgerufen)
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com

Geändert von André Michelle (10-05-2006 um 19:24 Uhr)
André Michelle ist offline   Mit Zitat antworten
Alt 10-05-2006, 19:40   #3 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
So gefällt mir das sehr gut:

Code:
public function nextFrame(): void
{
	var objA: IDynamicIntersectionTestAble;
	var objB: IDynamicIntersectionTestAble;
	
	var intersection: DynamicIntersection;
	
	for each( objA in movables )
	{
		if( objA is MovableParticle )
		{
			for each( objB in statics )
			{
				intersection = objB.dIntersectMovableParticle( MovableParticle( objA ) );
			}
			for each( objB in movables )
			{
				if( objA == objB ) continue;

				intersection = objB.dIntersectMovableParticle( MovableParticle( objA ) );
			}
			continue;
		}
		
		if( objA is MovableCircle )
		{
			for each( objB in statics )
			{
				intersection = objB.dIntersectMovableCircle( MovableCircle( objA ) );
			}
			for each( objB in movables )
			{
				if( objA == objB ) continue;

				intersection = objB.dIntersectMovableCircle( MovableCircle( objA ) );
			}
			continue;
		}
		
		// [...]
	}
}
IDynamicIntersectionTestAble is ein Interface, welches für alle beweglichen Objekte eine Intersection-Methode bereitstellen muss. Daher gehen alle Anfragen auf. Die individuellen Methoden arbeiten mit den richtigen Objekten, daher muss ich sie downcasten.
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 10-05-2006, 20:31   #4 (permalink)
flachzange
 
Benutzerbild von elias
 
Registriert seit: Jun 2003
Ort: berlin
Beiträge: 3.932
Rein von der Aufgabe her würde der Chain of Responsibility gut passen.
Allerdings bräuchtest du für einen direkte umsetzung für jede
Intersektionsmöglichkeit ein Objekt und bei 10 möglichkeiten könnten bis
zu 10 Aufrufe stattfinden bis der richtige Algorithmus gefunden ist. Dazu kommt
das die CoR nicht umbedingt super eingängig ist, dafür aber extrem Flexibel.

Also wie gehts? Du packst jeden Form<->Form Algorithmus in eine Klasse.
Diese Klassen werden geschachtelt. Mit 'intersect' wird das äußerste Objekt
getestet ob es FormXY auflösen kann, ist das nicht der Fall dann wird das
nächste getestet.


PHP-Code:
class Intersectable
{
    function 
isComplement(obj:Intersectable);
    function 
intersect(obj:Intersectable);
}

//für jedes form<->form paar gibt es einen algorithmus in einer klasse
class CircleAndLine implements Intersectable
{
    private 
type:Function;
    private 
successor:Intersectable;
    function 
Circle(suc:Intersectablet:Function)
    {
        
type t;
        
successor suc;
    }
    
    function 
isComplement(obj:Intersectable)
    {
        return 
obj instanceof type;
    }
    
    function 
intersect(obj:Intersectable)
    {
        if (!
isComplement(obj))
        {
            
//nicht auflösbar, also nächstes testen
            
successor.intersect(obj);
        }
        
//ok, berechnung und abbrechen
        
return doIntersection(obj);
    }
    
}

//weitere implementierungen unterscheiden sich nur in 'doIntersection'.
class CircleAndCircle implements Intersectable /* ... */}

class 
LineAndCircle implements Intersectable /* ... */}
class 
LineAndLine implements Intersectable /* ... */}

//leere implementierung die immer zuletzt angehängt wird
class Empty implements Intersectable /* ... */}

//die objekte werden ineinander geschachtelt. 'Empty' kommt nach innen,
//kommt die Kette dort an ist sie nicht auflösbar.
var line = new LineAndLine(new LineAndCircle(new Empty(), Circle), Line);
var 
circle = new CircleAndCircle(new CircleAndLine(new Empty(), Line), Circle);
// Circle und Line Klassen fehlen hier! 
Der riesen Vorteil bei der Sache ist das du deine Interfaces nicht für jeden
neuen Algo anpassen musst und dein Anwendungscode da auch relativ wenig
von mitbekommt. Du kannst das ganze sehr flexibel über das
Zusammenstecken der Objekte erweitern.
Du könntest das ganze auch ohne die Schachtelung (dekorierung) Lösen
indem du die Objekte in ein Array packst. siehe 7.6
__________________
elias ist offline   Mit Zitat antworten
Alt 10-05-2006, 22:30   #5 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
Das scheint mir eine AS2 Implemention zu sein. Aber dennoch. Ich werde meinen Ansatz weiterverfolgen. Es sieht ganz so aus, als wäre das eine schnellere Möglichkeit von allem, was ich wollte. Denn durch die Trennung von Movables und Statics habe ich schon eine Vorsortierung gemacht, die mir viele Abfragen erspart.

Letztendlich bleiben nur für die Movables Fallunterscheidungen nach dem Typ übrig, da Statics vs Statics keinen Sinn machen. Der Spaghetti Effekt bleibt in Grenzen, weil es nicht so viele unterschiedliche Movables geben wird und der auszuführende Code sich auf einen Methodenaufruf beschränkt.

Bleibt noch die Performance-Frage, ob ein 'is' schneller ist als ein Integer zu testen, welches als 'const' im Objekt liegt. Das werde ich sehen, wenn die Engine wieder funktioniert und ich mit vielen Objekten testen kann.

Vielen Dank auf jeden Fall.

[BASS]
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 10-05-2006, 22:51   #6 (permalink)
flachzange
 
Benutzerbild von elias
 
Registriert seit: Jun 2003
Ort: berlin
Beiträge: 3.932
Zitat:
Zitat von André Michelle
Das scheint mir eine AS2 Implemention zu sein.
AS3 Fans könnens auch Pseudocode nennen.

Zitat:
Zitat von André Michelle
Aber dennoch. Ich werde meinen Ansatz weiterverfolgen. Es sieht ganz so aus, als wäre das eine schnellere Möglichkeit von allem, was ich wollte. Denn durch die Trennung von Movables und Statics habe ich schon eine Vorsortierung gemacht, die mir viele Abfragen erspart.
Naja soviel zu der "suche nach einem Pattern".
__________________
elias ist offline   Mit Zitat antworten
Alt 11-05-2006, 07:07   #7 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
Zitat:
Zitat von elias
Naja soviel zu der "suche nach einem Pattern".
Zitat:
Zitat von aM
Das soll möglichst nachvollziehbar (OO), aber letztlich natürlich auch performant laufen.
Du hast es auch nicht wirklich gut beworben
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 11-05-2006, 10:21   #8 (permalink)
flachzange
 
Benutzerbild von elias
 
Registriert seit: Jun 2003
Ort: berlin
Beiträge: 3.932
Das OO bischen mehr arbeit als Spaghetti macht sollte klar sein. Wenn du das
ganze mit SVN o.ä. pflegen würdest könnte ich ja mal versuchen eine Lauffähige
Version umbauen. Würde mich auf jeden Fall mal interessieren ob man das
nicht auch mit halbwegs ordentlichen OO performant hinbekommt.
__________________
elias ist offline   Mit Zitat antworten
Alt 11-05-2006, 13:27   #9 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.272
Es ist viel weniger Spaghetti als ich dachte.

Wenn du magst, schicke ich Dir den aktuellen Stand. Bis jetzt ist das noch halbwegs übersichtlich.
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 11-05-2006, 14:05   #10 (permalink)
flachzange
 
Benutzerbild von elias
 
Registriert seit: Jun 2003
Ort: berlin
Beiträge: 3.932
Naja wenn ich das jetzt umstricke und du Zeitgleich daran rumschraubst, wird
es wieder ein Akt das ganze wieder zusammen zu friemeln. Ich würde lieber mal
vorbeikommen, dann könnten wir das zusammen umsetzen.
__________________
elias ist offline   Mit Zitat antworten
Alt 13-05-2006, 13:48   #11 (permalink)
Neuer User for life!
 
Benutzerbild von Holger E.
 
Registriert seit: Sep 2001
Beiträge: 147
Zitat:
Zitat von André Michelle
Vielen Dank auf jeden Fall.

[BASS]
Hehe, BASS reprezents in da house, oder so.


Zum Thema habe ich aber nichts nennenswertes zu sagen, sorry.
Holger E. ist offline   Mit Zitat antworten
Alt 13-05-2006, 15:33   #12 (permalink)
Flashaholic
 
Benutzerbild von atothek
 
Registriert seit: Feb 2003
Ort: Berlin
Beiträge: 1.459
Moin würden dir in einem solchen fall nicht auch reflection sachen helfen ???
dies kann mann ja nun für anonyme objecte gut gebrauchen. Rein theoretisch. weil das if konstrukt das du dir da aufbaust wäre ja eher unschön.

mir fallen da zb. die methoden

string flash.utils.getQualifiedClassName( object )
object flash.utils.getDefinitionByName(name )

du könntest nen Array mit representative klassennamen als keys nutzen und dahinter dann eine Klassenreferenz. mal einfach nen theoretisches codebeispiel

PHP-Code:
public function nextFrame(): void
{
    var 
classesMap Object = {
        
MovableParticleMovableParticle,
        
MovableCircleMovableCircle
    
}
    
    var 
objAIDynamicIntersectionTestAble;
    var 
objBIDynamicIntersectionTestAble;
    
    var 
intersectionDynamicIntersection;
    
    for 
eachobjA in movables )
    {
        var 
className String flash.utils.getQualifiedClassNameobjA );
        var 
_class : Class = classesMapclassName ];
        
        for 
eachobjB in statics )
        {
            
intersection objB.dIntersectMovableParticle_classobjA ) );
        }
        for 
eachobjB in movables )
        {
            if( 
objA == objB ) continue;

            
intersection objB.dIntersectMovableParticle_classobjA ) );
        }
        continue;
    }

keine ahnung ob das geht aber in diese richtung sollte da doch was machbar sein

mfg
alex
__________________
TVNEXT Solutions
atothek 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



Alle Zeitangaben in WEZ +1. Es ist jetzt 21:57 Uhr.

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


Copyright ©1999 – 2014 Marc Thiele