Virtuelle Sprites (03/2002, Dir 8)

In diesem Bereich befinden sich Artikel und Tutorials zum Thema Director.

Moderatoren: Bär, Admin

Antworten
Admin
Site Admin
Beiträge: 41344
Registriert: 07.02.2006, 2006 16:09
Wohnort: München
Kontaktdaten:

Virtuelle Sprites (03/2002, Dir 8)

Beitrag von Admin » 11.02.2006, 2006 17:46

Virtuelle Sprites

Normalerweise zieht man in das Drehbuch die Darsteller vom Cast per Drag & Drop hinein und erstellt somit ein neues Sprite. Nun das ist die eine Möglichkeit, Sprites in das Drehbuch zu bekommen, aber es gibt auch noch eine andere.

Es ist so, daß man des öfteren Sprites benötigt, aber im Vorhinein nicht genau weiß, wie viele davon genau gebraucht werden und welche Eigenschaften diese haben sollen. Denken wir z.B. an ein Spiel, in dem sich verschiedene Raumschiffe am Screen bewegen. Mit steigendem Level werden diese immer mehr und auch deren Eigenschaften verändern sich.

Man kann jetzt hergehen, eine Anzahl von Dummy Sprites anlegen und diese je nach Level aktivieren. Das ist vielleicht eine schnelle Lösung, aber allein von der Wartung her ein sehr unattraktiver Weg. Um im Drehbuch dynamisch zu bleiben gibt es die Technik der virtuellen Sprites.

Virtuelle Sprites haben genau die gleichen Eigenschaften wie echte Sprites: Sie können jeden Darstellertyp haben, natürlich sämtliche Eigenschaften ändern, wie z.B. Farbe, Breite, Höhe und auch Behaviors annehmen und wieder weglösen. Es können so viele Spritekanäle benutzt werden wie im Drehbuch eingestellt sind. Wenn man ein virtuelles Sprite einem nicht vorhanden Kanal zuweist hat das überraschenderweise keine Fehlermeldung zur Folge, es sei denn, das virtuelle Sprite wurde bereits mit einem Behavior erweitert.

Das Drehbuch ist nicht von vornherein ohne Informationen, sondern ist eigentlich schon mit Sprites belegt, nur haben diese eben noch keine Informationen über Darsteller, Farbe, Script und so weiter. Das können wir mit Hilfe des Nachrichtenfensters auch schön beweisen:

Code: Alles auswählen

put sprite(1).member
-- (member 0 of castLib 0)
  
put sprite(1).loc
-- point(0, 0)
  
put sprite(1).forecolor
-- 0
  
put sprite(1).rect
-- rect(0, 0, 0, 0)
  
put sprite(1).type
-- 0
  
put sprite(1).member.type
-- #empty

Generierung eines Würfels mit Imaging Lingo

Also sind im Drehbuch schon im vorhinein alle Sprites vorhanden, nur haben diese eben keine Informationen. Nun machen wir einen Test und erzeugen über das Nachrichenfenster einen virtuellen Sprite.
Das Einzige, das wir brauchen, ist erst mal ein Darsteller, den wir mit Imaging Lingo virtuell erzeugen:

Erst wird ein Image Objekt erstellt mit den Abmessungen von 200x200 und einer Farbtiefe von 8 Bit.

Code: Alles auswählen

bild = image(200,200,8)

Dann wird mit dem Befehl „fill“ der gesamte Würfel gefüllt

Code: Alles auswählen

bild.fill(bild.rect, rgb(255,0,0))

Nachdem jetzt das Image Objekt generiert haben und auch eine Farbe zugewiesen haben brauchen wir noch einen Darsteller:

Code: Alles auswählen

darsteller = new(#bitmap) 

Nun wird dem neuen Bitmap Darsteller das Image-Objekt „bild“ zugewiesen

Code: Alles auswählen

darsteller.image = bild

Fertig! Und jetzt vergeben wir noch einen Namen:

Code: Alles auswählen

darsteller.name = "Würfel"

Nun haben wir einen neuen Darsteller erzeugt und können ihn auch gleich in das Drehbuch befördern, jedoch nicht per Drag&Drop sondern via Lingo.


Der Würfel kommt virtuell auf die Bühne

Also erinnern wir uns noch einmal an die Drehbuchstruktur und prüfen den Darsteller von Sprite 1:

Code: Alles auswählen

put sprite(1).member
-- (member 0 of castLib 0)

Jetzt gebe ich den Darsteller, den wir zuvor erstellt habe, in Sprite 1:

Code: Alles auswählen

sprite(1).member = "Würfel"

Was ist passiert? Gar nichts? Gibt es nicht – also prüfen wir noch einmal das Sprite 1:

Code: Alles auswählen

put sprite(1).member
-- (member 1 of castLib 1)

Die Antwort, warum der Würfel nicht auf der Bühne sichtbar wird ist, daß der Film nicht läuft und die Bühne deshalb auch nicht aktualisiert wird. Deshalb machen wir das nun manuell mit dem Befehl:

Code: Alles auswählen

Updatestage

Wie durch Zauberei erscheint der Würfel auf der Bühne und im Drehbuch ist kein Sprite sichtbar.

Das soeben erzeugen Sprite kann man auch wieder löschen:

Code: Alles auswählen

sprite(1).member = VOID

oder man setzt einfach den Sprite-type auf 0:

Code: Alles auswählen

sprite(1).type = 0
Updatestage

Übrigens, wenn man einen Spritekanal wie zuvor mit einem Darsteller belegt und ihn danach mit einem anderen Darsteller belegen möchte, muß man nicht den Spritekanal wieder freigeben bzw. löschen sondern man kann ihn einfach auch überschreiben. Das heißt wenn man einen Spritekanal doppelt belegt, wird der bestehende gelöscht und der neuere Darsteller eingefügt.

Das soeben erstellte Sprite kann jetzt alle Eigenschaften eines „normalen“ Sprites annehmen. Probieren wir das mal aus:

Nachdem das Sprite die Position auf 0 hat, werden wir es jetzt in die Mitte stellen:

Code: Alles auswählen

sprite(1).loc = point(100,100)
updatestage

Oder z.B. die Farbe ändern:

Code: Alles auswählen

sprite(1).color = rgb(255,0,0)
updatestage

Und so weiter... Sie sehen, ein virtuelles Sprite kann alle Eintellungen eines „realen“ Sprites übernhemen und ist mit Lingo 100%ig steuerbar.


Behaviors an virtuelle Sprites hinzufügen

Nun, was ist aber ein Sprite ohne Interaktivität? Um das Sprite interessant zu machen, braucht es noch ein Behavior, das man virtuell anhängen kann. Jedes Sprite hat als Eigenschaft eine Scriptinstancelist. Prüfen wir das anhand des soeben erzeugten Würfels:

Code: Alles auswählen

put sprite(1).scriptinstancelist
 -- []

Wir haben eine Leere Liste, die mit Script-Objekten gefüllt werden kann – was wir auch gleich machen, doch zuvor gehört in den Frame-Script Kanal noch ein go to the frame Script, das den Abspielknopf auf der Position lässt, denn das Testen der scriptinstancelist macht nur zur Laufzeit Sinn. Nun ist es aber nicht möglich den Sprite 0 Kanal, der ja das go to the frame Script erhalten soll, mit der Scriptinstancelist zu erweitern, also muß eine andere Lösung her.

Zuerst erstelle ich das Script, das in den Frame soll:

Code: Alles auswählen

-- Script „Frame“
On exitframe(me)
  Go to the frame
End

Damit dieses Script in den Frame-Script Kanal kommt, werde ich auf die Score Recording Technik zurückgreifen. Das ist vielleicht etwas unschön weil es ja dann nicht mehr wirklich ein virtuelles Sprite ist, aber das ist die einzige Möglichkeit.
In das MovieScript schreibt man diese Zeilen und erwirkt dadurch beim Start des Filmes die Belegung des Scriptes „Frame“ im Sprite 0 Kanal:

Code: Alles auswählen

on startmovie
  beginrecording
    the framescript = member("Frame")
  endrecording
end

Der Film ist jetzt abspielbereit und bleibt auf Frame 1 im loop stehen. Doch bevor wir das ihn abspielen werde ich noch das Script schreiben, das den Würfel mit einer Funktion erweitern soll.s
Unser Würfel liegt etwa in der Mitte der Bühne und soll nun auf den Mausklick reagieren. Und zwar sollte er immer, wenn man ihn anklickt, die Farbe wechseln. Das ist eine leichte Aufgabe, und nun schreiben wir erst einmal das dazu nötige Script.

Code: Alles auswählen

-- Script Farbe
on mousewithin(me)
  sprite(me.spritenum).color = rgb(random(255),random(255),random(255))
end

Jetzt ist alles komplett:

- das Framescript das beim Start in den Framescript Kanal gelegt wird.
- der Würfeldarsteller
- das Script das den Würfel beim Mausklick die Farben wechseln lassen soll.

Film Start!

So, das vorher virtuell erstellte Sprite ist verschwunden, da Director die virtuell belegten Spritekanäle beim Start des Filmes löscht wenn sie zuvor „offline“ erstellt wurden. Macht nichts, wir erstellen einfach ein Neues, was nicht soviel arbeit bedeute, da der „Würfel“ Member ja noch da ist.

Falls man während der Laufzeit ein Sprite per Lingo steuern möchte, sollte man sich mit dem Befehl puppetsprite die volle Kontrolle über den Sprite sichern. Wenn der Sprite-Kanal ein Puppet ist, bleiben alle durch Lingo an den Eigenschaften des Sprite-Kanals vorgenommenen Änderungen weiterhin aktiv, nachdem der Abspielkopf das Sprite verlässt.

Also Nachrichtenfenster:

Code: Alles auswählen

puppetsprite 1, TRUE
sprite(1).member = „Würfel“

Jetzt ist der Würfel auf der Bühne sichtbar geworden. Damit er wieder in der Mitte ist, weden wir seine loc noch ändern:

Code: Alles auswählen

sprite(1).loc = point(100,100)

Nun bekommt das Sprite mit scriptinstancelist das Script zugewiesen. Und zwar auf folgene Weise:

Code: Alles auswählen

neu = script("Farbe").new()
sprite(1).scriptInstanceList.add(neu)

Das Script Objekt wird erzeugt und der Variable „neu“ zugewiesen. Anschließend bekommt die Scriptinstancelist von Sprite 1 die Scriptreferenz „neu“ zugewiesen.

Wenn man nun mit der Maus in den Bereich von Sprite 1 kommt, wird immer für jeden RGB Kanal eine Zufallsfarbe im Bereich von 0-255 ausgewählt.


Virtuelle Sprites mit Klassen optimal erzeugen

Nun sollten wir nach den Laborversuchen im Nachrichtenfenster eine gute kompakte Lösung finden, die leicht wartbar und veränderbar ist. Hier bieten sich Klassen an, oder Parent-Scripts, wie es in Director ja heißt.

Mit Parent Scripts arbeiten heißt, immer strukturiert programmieren, und das benötigt auch eine strukturierte Vorbereitung.

Welche Informationen benötigt das Parent-Script und was sollte es machen?

Zuerst klären wir einmal, was dieses für virtuelle Sprites zuständige Parent Script benötigt:

1. Spritekanalnummer
2. Darstellernamen
3. Position
4. Farbe
5. Script

Zur Übergabe dieser Daten empfiehlt sich eine Eigenschaftsliste, in der wir folgende Eigenschaften festelgen:

#psprite = Spritenummer
#pmember = Darstellername
#ploc = Position
#pscript = Script
#pcolor = Spritefarbe

Code: Alles auswählen

-- Parent  « Klasse »
property mysprite,mymember,myloc,myscript,mycolor
  
on new(me,props)
  mysprite = props.psprite
  mymember = props.pmember
  myloc = props.ploc
  myscript = props.pscript
  mycolor = props.pcolor
  erstellen
  return me
end

Bei der Erstellung des Objektes wird die Eigenschaftsliste übergeben, und die einzelnen Listenelemente werden in neue Variablen gespeichert. Anschließend wird gleich die „erstellen“ Methode aufgerufen. Wichtig ist noch, daß die Objekt-Refernz mit „return me“ zurückgegeben wird damit die aussenstehende Objektvariable auch auf die einzelnen Methoden Zugriff hat.

Nun muß noch die „erstellen“ Methode geschrieben werden:

Code: Alles auswählen

on erstellen(me)
  puppetsprite mysprite, TRUE
  sprite(mysprite).member = mymember
  sprite(mysprite).loc = myloc
  sprite(mysprite).color = mycolor
  pscript = script(myscript).new()
  sprite(mysprite).scriptinstancelist.add(pscript)
end

In dieser Methode wird zuerst mit puppetsprite die volle Kontrolle über den Spritekanal gegeben. Dann werden die einzelnen Eigenschaften dem Sprite zugewiesen. Die Variablen mysprite, mymembe, myloc, mycolor, myscript sind die Property-Variablen, die bei der Generierung des Sprites bereits übergeben wurden.

Nun wechseln wir in die Laufzeitumgebung von Director und schalten den Movie auf Play. Im Nachrichtenfenster werde ich jetzt die Eigenschaftsliste erstellen:

Code: Alles auswählen

liste = [:]
liste.addprop(#psprite,1)
liste.addprop(#pmember,"würfel")
liste.addprop(#ploc, point(100,100))
liste.addprop(#pscript, "Klick")
liste.addprop(#pcolor,rgb(0,255,0))
  
put liste
-- [#psprite: 1, #pmember: "würfel", #ploc: point(100, 100), #pscript: "Klick", #pcolor: rgb( 0, 255, 0 )]

Es sind also alle erforderlichen Eigenschaften definiert worden.
Nun übergeben wir die Liste dem Parent-Script das ja schon darauf wartet.

Code: Alles auswählen

Objekt  = script("Test").new(liste)

Das Parent-Script hat jetzt alle nötigen Informationen bekommen und wie von uns zuvor definiert damit ein virtuelles Sprite erzeugt. Dieses virtuelle Sprite hat jetzt Gültigkeit, so lange der Film läuft. Beim Stoppen des Filmes oder Abbruch ist es gelöscht und existiert nicht mehr länger. Ausserdem liegt das Sprite nicht nur in Frame 1 sondern erstreckt sich über die ganze Länge des Drehbuches. Wenn es in einem anderen Frame nicht mehr gewünscht wird, muß es zuvor gelöscht werden.

Code: Alles auswählen

Sprite(1).type = 0

Add Script / Remove Script

Aber was, wenn man eigentlich von den vielen Farben genug hat und lieber doch ein anderes Script als Behavior haben möchte? Um auch für dieses Vorhaben gerüstet zu sein, werden wir einfach das bestehende Parentscript um 2 Methoden erweitern.

Also zuerst ein paar Zeilen zum Entfernen eines Scriptes an dem Sprite:

Code: Alles auswählen

on removescript(me,num)
  sprite(mysprite).scriptinstancelist.deleteat(num)
end

Wenn diese Methode aufgerufen wird, wird die übergebene Listenposition gelöscht.

Und natürlich sollte man im Nachhinein auch Scripts anhängen können – das funktioniert so:

Code: Alles auswählen

on addscript(me,pscript)
  pscript = script(pscript).new()
  sprite(mysprite).scriptinstancelist.add(pscript)
end

Das Script wird in ein neues Objekt gespeichert und anschließend an die Sprite-Scriptinstancelist übergeben.

Um dies zu testen, brauchen wir noch ein neues Behavior-Script, das ich „Klick“ nenne werde:

Code: Alles auswählen

-- Script „Klick“
on mouseup()
  alert "MMUG-D Usertreffen in Frankfurt!"
end

Im Nachrichtenfenster werden wir die neuen Methoden gleich ausprobieren: Die Objekt Variable ist ja noch im Zwischenspeicher und wir verwenden diese auch gleich: Das beim Erstellen des Objekts übergebene Script hat in der Scriptinstancelist die Position 1 da es das einzige Script ist. Lingo fängt nicht wie andere Programmiersprachen bei den Listen-Positionen mit 0 zu zählen an sondern mit 1. Also hat das Script die Listenposition 1.

Code: Alles auswählen

Objekt.removescript(1)

Nun ist das Script gelöscht und der Würfel wechselt seine Farben nicht mehr, wenn man ihn anklickt. Nun bekommt er das neue Skript „Klick“ übergeben:

Code: Alles auswählen

Objekt.addscript("Klick")

Das waren grundlegend die Funktionsweisen von virtuellen Sprites und wie man sie erstellt. Natürlich ist dies nur eine Möglichkeit und es gibt vielleicht auch andere, für andere Zwecke optimalere Methoden, ein virtuelles Sprite zu erzeugen. Aber ich denke diese Beispiele haben schon ganz gut gezeigt, wie man mit virtuellen Sprites arbeiten kann.


Autor: Bernhard Standl

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste