ACHTUNG: WEGEN DER VERWENDETEN SHOCKWAVE-DATEIEN KANN DAS LADEN DIESER SEITE EINIGE MINUTEN DAUERN. BITTE UM ETWAS GEDULD
Einige Beispieldateien sind mit früheren Versionen von Director erstellt und müssen deshalb nach dem Herunterladen und Entpacken über den Menüpunkt Datei>Öffnen... geöffnet werden.

Wenn Sie kein Inhaltsverzeichnis sehen, dann klicken Sie bitte hier: .

Wenn Sie diese lecture note schon früher einmal angeschaut haben und sicher sein wollen, dass Sie die neueste Version haben, leeren Sie bitte den Browser Cache und laden Sie die Seite neu.
Wenn Sie auch andere Themen sehen wollen, hier klicken: .

Leider hat Adobe beschlossen, das Programm per 1.2.2017 nicht mehr zu verkaufen. Es bestht aber die Hoffnung, dass es, so wie Adobe es von Macromedia erworben hat, wieder von einer anderen Firma weiter geführt wird.

1. Basics

So wie in meinen anderen lecture notes habe ich auch hier versucht, dieses Dokument möglichst wenig zu unterteilen, also möglichst viel Inhalt auf einer einzigen Seite darzustellen. Das scheint auf den ersten Eindruck etwas unpraktisch, weil das Laden des gesamten Seitenumfangs mehr Zeit in Anspruch nimmt, hat aber den großen Vorteil, dass man mit einem Suchbefehl einen bestimmten Begriff im gesamten Umfang der Seite suchen kann. In diesem Sinne ist alles was Director betrifft auf dieser Seite zu finden, ausgenommen diejenigen Inhalte, die sich mit OOP (objektorientiertem Programmieren) befassen. Um in diesem Bereich zu suchen, muss man zu Kapitel 7 gehen, wodurch eine andere Datei in den sichtbaren Seitenauschnitt geladen wird. Je nach verwendetem Shockwaveplayer und Bandbreite der Verbindung können die Shockwavebeispiele einige Minuten in Anspruch nehmen, bevor sie zu laufen beginnen. Es scheint sich dabei um ein temporäres Problem zu handeln (4/2009), das jedoch bald behoben sein dürfte. Inzwischen bitte um etwas Geduld.

Hyperlinks werden auf dieser Seite in grün dargestellt, um sie besser1 von Programmcode unterscheiden zu können.

Es können an einigen Stellen der Notes Beispiele runtergeladen werden. Die Links sind an ihrer speziellen Schreibweise erkennbar, nämlich in der Form: (Download irgdeinBeispiel.sit). Dabei bedeutet die Endung .sit, dass das File mit Aladdin's Stuffit-Expander dekomprimiert werden muss (www.stuffit.com).

Für den Anfänger weniger wichtige Textteile sind in grauer Schrift gehalten. Er kann diese überspringen, ohne Gefahr zu laufen spätere Kernteile des Textes deshalb nicht zu verstehen.

Es empfiehlt sich die englischen Termini zu verwenden, wie z.B. Member statt Darsteller, weil man sich damit bereits an die entsprechenden Ausdrücke für das Programmieren in Lingo gewöhnt (dort heißt dann z. B. der in Kanal 12 verwendete Darsteller --sprite(12).member).

Zur Vereinfachung werden für manche oft gebrauchte Begriffe Abkürzungen verwendet (z.B. PI für den Property Inspector). Eine Liste der Abkürzungen findet sich am Ende.

Weite Teile des OOP-Abschnitts wurden der Quelle[5] nachempfunden.

Es ist nicht möglich, Quellcode direkt aus diesem File in ein Skriptfenster zu importieren, da sich das Skript dann abnormal verhält (vermutlich werden gelegentlich nbsp statt space übertragen).

Ab und zu passiert es, dass sich das Programm trotz syntaktisch richtiger Programmierung abartig verhält. Man sucht endlos nach dem Fehler und kann ihn nicht finden. Das kommt vor allem dann vor, wenn man mehrere Stunden ununterbrochen mit dem Programm arbeitet ohne es dazwischen einmal beendet zu haben. Es scheint dann gelegentlich vorzukommen, dass ein reproduzierbarer Fehler in der programmierten Datei auftritt, der aber sofort verschwunden ist, wenn man Director neu startet. Natürlich muss man auch daran denken, nach Änderungen in einem laufenden Programm dieses anzuhalten und wieder zu starten, da sonst veränderte Skripts nicht neu kompiliert werden.

------

Die diversen Werkzeugpaletten und Arbeitsfenster findet man unter dem Menüpunkt Window (Fenster):

Window-Menü

Der sehr wichtige PI befindet sich im Object Inspector und hat - so wie für das Cast-Fenster auch - zwei Darstellungsweisen, links die nicht-Listendarstellung, rechts die Listendarstellung, die bei manchen Objekten mehr Informationen als die erstere enthält!:

Director Property Inspector

Der PI ist Kontextsensitiv, d.h. er zeigt jeweils die Gruppe von Eigenschaften, die das angeklickte (ausgewählte) Objekt besitzt.

Sehr nützlich ist der New Window-Befehl, da er es erlaubt, zwei oder mehr Drehbuch- oder Skriptfenster offen zu haben, was zum Vergleichen oder Kopieren sehr praktisch sein kann.

In Director 10.1 (5/2007) funktionieren die Tastaturkürzel (z.B. für Kopieren, Einfügen, Aufruf der Fenster etc.) am Mac nicht, wenn in den Landeseinstellungen als Sprache Österreichisch gewählt wird. Man muss auf die Sprache Deutsch umstellen. Dieses Problem taucht bei Director 11 und MacOS 10.5 nicht mehr auf.

Neben dem Arbeiten mit den Werzeugfenstern, der Besetzung, dem Drehbuch und der Bühne gibt es eine Programmiersprache, Lingo. Sie gliedert sich in drei Typen, nämlich dem in Director eingebauten Core Lingo, weiters dem zur Integration von Shockwave-Filmen in die Internetumgebung verwendeten NetLingo und schließlich dem Xtra Lingo, das die Funktionalität von Lingo durch Xtras erweitert. Neben Lingo kann auch JavaScript verwendet werden. Die jeweiligen Befehle sehen recht ähnlich aus und haben die selbe Funktion. JavaScript wird sich vor allem für diejenigen anbieten, die diese Sprache schon in einem anderen Zusammenhang gelernt und verwendet haben und sich in ihr wohl fühlen.


1.1 Movie Terminologie und Setup

Als Filme bezeichnet man Director-Dateien, die abspielbar sind und in der Form des Projektors stand-alone Programme sind. Die weiteren drei grundlegenden Metaphern (die auch jeweils in einem eigenen Fenster dargestellt werden) sind: die Bühne (Stage) auf der der sichtbare Teil des Films abläuft, die Besetzung (Cast) und das Drehbuch (Score).

Beim Start des Programms, aber nicht beim Öffnen einer bereits vorhandenen Datei, kann es vorkommen, dass man wartet und wartet und es tut sich nichts. Das passiert eventuell dann, wenn ein Schutzprogramm wie z.B. Kaspersky installiert ist. Director legt nämlich eine exekutierbare Datei an und das lässt nicht jedes Sicherheitsprogramm zu. In diesem Fall muss man es kurzzeitig deaktivieren. Ist die Datei einmal erstellt, kann man diese öffnen ohne das Schutzprogramm neuerlich lahm legen zu müssen.

Die Einrichtung eines neu zu erstellenden Filmes geschieht über den Property Inspector. Dieser zeigt so wie beim Film auch bei anderen Objekten deren jeweilige Eigenschaften wenn diese gerade angewählt sind. Hat man mehrere Objekte ausgewählt werden nur die gemeinsamen Eigenschaften gezeigt.

Soll das Produkt einmal im Web wiedergegeben werden, so ist bei Verwendung von 8-bit Farbe eine web-sichere 216-Farbenpalette vorzuziehen. Das Movie wird für diesen Zweck als Shockwave (siehe Kapitel Shockwave und Flash) gesichert. Das hier eingefügte Shockwavebeispiel ist ein Test. Um es zu sehen, muss man den geeigneten Player für den jeweiligen Browser installiert haben.

 

-- wenn hier nach einer gewissen Ladezeit kein bewegtes Bild erscheint, fehlt der richtige Shockwaveplayer. Download bei Adobe.

1.2 Members (Darsteller) und Sprites

Members sind Objekte unterschiedlicher Natur (Text, Bild, Film, Ton etc.), die in der cast library, oder Deutsch Besetzung zusammengefasst sind. Näheres zu den Besetzungen findet man in Kap. 1.4. Die Darsteller (members) einer Besetzung (eines Casts) werden als Acteure im Film benötigt . Aber so wie man in dem Filmklassiker Casablanca nicht den Darsteller Humphrey Bogart selbst sieht, sondern nur seine Abbildung, so sieht man im Director-Film nicht die Members selbst, sondern ihre, als Sprites bezeichneten, Abbildungen. (In der Terminologie objektorientierten Programmierens ist das Member die Klasse, der Sprite eine Instanz der Klasse - siehe Kap. 6). Members können im Cast Fenster auf zwei verschiedene Arten dargestellt werden - als Liste und als Thumbnails. Zusätzlich erlaubt ein ctrl-klick (Windows: Rechte Maustaste) auf einen Darsteller in der Thumbnail-Ansicht weitere Eigenschaften zu sehen, insb. wo sich ein Sprite des Darstellers im Drehbuch befindet. Zeigt ein Darsteller dabei keinen Sprite an, so darf er trotzdem nicht ohne zu Überlegen gelöscht werden, denn es könnte ja eine programmierte Erzeugung einer Instanz vorliegen (siehe OOP). Ebenso kann man diejenigen Members finden, die nicht im Score referiert sind über Edit>Find>Cast Member…>usage. Aber auch hier bedarf es der oben erwähnte Achtsamkeit bei OOP.

In Lingo kann die Existenz eines Members mit einem bestimmten Namen festgestellt werden. Existiert das Member mit beispielsweise dem Namen "Note" nicht, so erhält man folgende Resultate:
put member("Note").number --  -1
put member("Note").type --   #empty

Man kann Members außer durch Erzeugen in einem der zuständigen Werkzeugfenster von Director auch importieren. Dabei gibt es verschiedene Optionen:

Standard Import speichert die files im movie. Danach gibt es keine Verbindung zu den Originaldaten mehr (Ausnahme: digitale Video files, sie bleiben immer gelinkt).

Link to External File erzeugt ein link zu dem entsprechenden file und importiert die Daten zur Laufzeit jedesmal neu. Das funktioniert auch, wenn man von einer URL via Internet importiert (Ausnahme: Text und RTF).

Beachte: .avi and QuickTime files werden immer gelinkt, auch wenn man Standard Import wählt.

Beachte: Text and RTF files haben immer einen Standard Import), auch wenn man Link to External File wählt.

Include Original Data for Editing In diesem Falle speichert Director zusätzlich eine Kopie der originalen Daten des cast member, die dann verwendet werden, wenn ein externer Editor (z.B. PS) aufgerufen wird.

Import PICT File as PICT verhindert, dass PICT files in bitmaps umgewandelt werden.

Importiert man ein PICS oder Scrapbook file, gibt es zusätzliche Optionen.

Hat man ein bitmap mit einer bestimmten Farbtiefe oder Palette importiert, die sich von der des aktuellen Films unterscheidet, so erscheint die Image Options dialog box.

1.2.1 Arten von Members

Es gibt mehrere Arten von Members, die jeweils in einem zugehörigen Fenster bearbeitet werden können. In diesem Fenster kann oben ein Name für das Member eingegeben werden, das Feld daneben dient dazu, um es auf die Bühne zu ziehen.

1.2.1.1 Paintdarsteller (Bitmaps)

Doppelklick auf die Pixelbreitenangabe am linken Fensterrand gibt die Paint-Window Preferences,

Ein Doppelklick auf das unterhalb der Linienbreiteneinstellung befindliche Farb-bit-Tiefe-Kästchen gibt Transformiermöglichkeiten. (Wichtig: nicht mehr Farben (bits) für ein Member verwenden als nötig, um schnelleres Laden zu ermöglichen). Am unteren Rand des Paint-Fensters, neben dem Rollbalken, ist die Ink-Einstellung für Gradienten, Durchsichtigkeit etc.

Farbverläufe können durch klicken zwischen die zwei gewählten Farben näher spezifiziert werden:

Die Arten von Inks die (am unteren Fensterrand) wählbar sind, hängen vom gewählten Zeichenwerkzeug ab. Aus Geschwindigkeitsgründen empfiehlt es sich, soweit möglich Inkeffekte am Darsteller im Paint window und nicht erst am Sprite anzuwenden. Ein spezieller Effekt ist Reveal. Durch ihn kann man Objekte ganz oder teilweise im Paintfenster sichtbar machen, wobei nur diejenigen Teile der Zeichnung erscheinen, die mit dem Darsteller im vorangehenden cast member slot überlappen.

Onion Skinning ist ein wichtiger Effekt für Trickanimation. Man öffnet das Werkzeugfenster mit Ansicht>Zwiebelschichteneffekt. Klickt mandaraufhin im linkesten Feld der erschienen Werkzeugpalette, so wird das Werkzeug aktiv. Der Hintergrund einstellen-button erlaubt, das aktuelle Bitmap Cast Member als Hintergrund festzusetzen. Sichtbar wird das erst, wenn auch der Button rechts davon, nämlich Hintergrund einblenden gedrückt wird. Hintergrund verfolgen erlaubt für jedes neu zu zeichnende Member einen neuen Background zu verwenden. Die Hintergrundbilder müssen als zusammenhängende Serie von Darstellern gespeichert sein. Bespiel in {[1] S. 78ff}

Zum Zwecke der Platzersparnis, resp. des schnelleren Ladens ist es zweckmäßig, die Bit-tiefe eines Members so niedrig wie möglich zu halten. Da ein Runtertransformieren nicht rückgängig gemacht werden kann, sollte man aber zuerst an einem Duplikat des Darstellers experimentieren. Das Ändern der Bit-tiefe geschieht nach dem Doppelklicken auf das entsprechende Feld an der linken Werkzeugleiste des Paintfensters. In diesem Transformierfenster kann auch die Pixelbreite und-höhe des Darstellers skaliert werden. Ganz wichtig ist es, die Bittiefe eines schwarz-weiß Darstellers auf 1 Bit zu begrenzen. Sollte das verwendete Bild dabei einen nicht rein weißen Hintergrund haben (z.B. beim Import von Notenbeispielen aus Finale):

so ist es ungünstig zuerst auf 32-bit Farbtiefe zu importieren und dann erst auf 1 Bit zu reduzieren, da es dabei zu einem Qualitätsverlust in der Zeichnung kommt:

Sinnvoller ist es, das Malfenster zuerst auf 1 Bit zu stellen und dann erst zu importieren:

 

Paletten sind heutzutage weniger ein Thema, da im Allgemeinen schon mehr als 8-bit Farben verwendet werden. (NB: Man kann in Photoshop eine angepasste Palette exportieren, die in Director wieder importiert werden kann, wenn man im Photoshop auf indizierte Farben umwandelt (Bild>Modus>Indizierte Farben) und dann die Farbtabelle (Bild>Modus>Farbtabelle…) sichert.)

Eine spezielle Form des Paintdarstellers ist der Cursordarsteller.

Importiert man ein Bitmap, so ergibt sich das Problem der Randfarbe. Antialiast man auf einem weißen Hintergrund und bringt das Objekt auf einen dunklen, so hat man bei der ink "transparent" immer weiße Randflecken. Deshalb sollte man gegen einen dunklen Hintergrund (dunkelgrau) antialiasen, bei statischen Objekten (die sich also immer über dem selben Hintergrund befinden) am besten gegen den zukünftigen Hintergrund selbst. Will man Alphakanäle mit exportieren, sollte man ein Format wählen, das dieses bewerkstelligt, wie z.B. .png. Außerdem muss man beim Import des Bitmaps die Farbtiefe auf Image (32 bits) eingestellt haben, und Trim white space muss abgewählt sein.

1.2.1.2 Vector shapes

Man muss darauf achten, nicht versehentlich mit den Werkzeugen der Tool-Palette auf der Bühne zu zeichnen, sonst erhält man keinen vector shape, sondern einen internal shape (eine Auswahl aus 4 Grundformen - siehe property inspector>shape), der zwar noch weniger Speicherplatz braucht, aber auch nicht anti-aliasen kann.

In vector cast members can man mit dem Feder-Werkzeug Bézier-Kurven zeichnen. Erzeugt man mehrere Pfade in einem Fenster, so haben sie alle die gleichen Eigenschaften

Wählt man einen Gradienten, so kann man diverse Parameter oben im Fenster auswählen (eventuell ist es nötig das Fenster zu vergrößern um bis zum y-Offset zu sehen.)

Eine ganz nützliche Anwendung für vector shapes ist die Erstellung von weißen Hintergründen. Versucht man ein weißes Bitmap zu machen, so gelingt das nicht, weil es sich nicht vom Hintergrund abgrenzen lässt. Ein shape mit der Füll- und Linienfarbe weiß ist hingegen definierbar.

Vektorgraphiken kann man aus Flash im SWF-Format importieren.

1.2.1.3 Textdarsteller

Man kann im Textfenster die Breite des Feldes nicht dadurch einstellen, dass man das kleine Dreieck rechts im Lineal nach rechts zieht, denn es ist nur für den rechten Absatzrand innerhalb des Feldes zuständig. Will man das Feld nach rechts erweitern, muss man die rechte Randlinie ziehen:

Die meisten Einstellungen zur Schrift findet man in Modifizieren>Schrift.

Obwohl der registration point von Textdarstellern nicht offensichtlich ist, so haben sie doch die Eigenschaft member("some name").regpoint. Diese Eigenschaft braucht man, wenn man z.B. alternativ einen Bitmap- oder einen Textdarsteller an denselben Punkt positionieren will. Der Bitmapdarsteller wird nämlich by default immer zentriert positioniert erscheinen, der Textdarsteller aber mit dem linken oberen Eck am gegebenen Punkt. Dann ist es nötig, für ihn ein Offset zu machen (am besten im message window, da der Vorgang ja nur einmal stattfinden muss).

Alternativ kann man einen Textdarsteller in einem Scrollfeld, wo er ja auch zentriert positioniert wird, mittels

member("MemberNummerOderName").scrollTop = 0

So einstellen, dass der Scrollhandler im vertikalen Balken oben steht. Setzt man statt 0 einen laufenden Wert (etwa mittels repeat), so kann man z.B. einen selbst scrollenden Abspann erzeugen oder ähnliches.

Textdarsteller sind RTF und eröffnen die weitesten Möglichkeiten der Textdarstellung. Ihre Darstellung ist anti-aliased.

Die Einheiten auf dem Lineal können durch opt-klick auf das Lineal umgestellt werden.

Um direkt auf die Bühne zu schreiben, öffnet man die Tool-Palette mit Window>Tool Palette

Verwendet man Fonts, die nicht Systemstandard sind, so sollte man sie (oder wenigstens die von ihnen verwendeten Zeichen) in den Directorfilm einschließen (embedding fonts). Insert>Media Element>Font. Unter Original Font wählt man den im eigenen System vorhandenen speziellen Font, unter New Font Name einen passenden für den intern verwendeten Font, der dann durch ein am Ende angehängtes *-Zeichen gekennzeichnet ist. Achtung! Bereits geschriebene Darsteller nehmen nicht den internen Font an. Sie müssen neu erzeugt werden! Also zuerst das Font-Embedding machen, dann Textdarsteller erzeugen.

Importiert man Text von einem HTML-Dokument werden die meisten Tags erkannt. Import aus dem Internet geschieht über File>Import und den Internet button.

Zugriff auf den Text in Lingo erfolgt mit member("Textdarsteller").text

Fonteigenschaften (wie .fontstyle oder .fontstyle[1]) liefern bei Textdarstellern Properties, (bei Felddarstellern Strings).

Bei Textdarstellern gibt es auch eine spezielle Eigenschaft .ref, anhand derer sich ein Textausschnitt referenzieren läßt. z.B.:
myRef=member (1).line[1..10].ref
put myref
-- <Prop Ref 2 1120e48>
put myref.text.length
-- 87
put myref.font
-- "Geneva"

1.2.1.4 Felddarsteller

Sie dienen der Aufnahme von character strings und chunk expressions, die zur Laufzeit auch nach Belieben editierbar sind, wenn man die Eigenschaft im PI enabled hat. Abgesehen von der unterschiedlichen Funktionalität brauchen Felddarsteller weniger Platz als Textdarsteller, haben aber kein Anti-alias. Beispiel für die Verwendung von Feldern:

on enterframe
member ("IchBinEinFelddarsteller").text="Hallo Welt"
end

Zur Erzeugung eines Felddarstellers kann man nicht einfach auf das Textsymbol in der Textsymbolleiste klicken, sondern muss aus dem Menü Fenster>Feld auswählen.

Wählt man bei einem Felddarsteller im PI Rahmen und/oder Schatten, so kann man sein Sprite nicht mehr auf matt oder durchsichtig setzen.

Zugriff auf den Text in Lingo erfolgt mit member("Felddarsteller").text

Fonteigenschaften (wie .fontstyle oder .fontstyle.char[1]) liefern bei Felddarstellern Strings (bei Textdarstellern Properties).

Man kann in Felddarstellern enthaltene Ziffern, die ja vom Typ Character, respektive String sind in Zahlen umwandeln.

1.2.1.5 Text als Bitmap

Beim Schreiben eines Textes verwendet man einen bestimmten Zeichensatz in einem bestimmten Stil. Das gibt so lange kein Problem, als der Anwender des Programms den selben Zeichensatz mit dem vom Verfasser vcerwendeten Stil geladen hat. Ist dies nicht der Fall, so kann es zu Problemen kommen, da am Rechner des Endusers der nicht vorhandene Font durch einen anderen ersetzt wird. Dabei kann es dan passieren, dass wegen unterschiedlicher Zeichenbreiten sich Zeilenumbrüche ändern, dass dadurch eventuell auch letzte Zeilen eines Textfeldes aus dem sichtbaren Bereich verschwinden oder dass gar manche Zeichen (wie z.B. Umlaute oder ß) gar nicht dargestellt werden können. Um für solche Eventualitäten Vorsorge zu treffen sollte man aus dem (editierbaren) Textfeld ein (nicht editierbares) Bild machen. Das allerdings erst dann, wenn man sicher sein kann, dass der Text nicht mehr verändert werden soll. Sowohl RTF-Text als auch Textfelder können in Bitmaps umgewandelt werden durch: Modify>Convert to Bitmap (Dabei keine unnötig größe Farbtiefe im entstandenen Bitmapdarsteller verwenden!). Alternativ dazu kann man auch den verwendeten Font in den Film einbetten.

1.2.1.6 Filmschleifen

Eine Filmschleife ist ein Darsteller, der aus einem oder mehreren Sprites besteht. Der Nutzen einer Filmschleife besteht in einer größeren Übersichtlichkeit und kompakteren Handhabung, insbesondere von repetitiven Sequenzen. Man wählt eine Anzahl von Sprites in einem Kanal über einen gewissen Framebereich, dann Insert>Film Loop, gibt dem Darsteller einen Namen und kann nun diesen Filmdarsteller in einem Kanal einsetzen. Wenn man will, kann man alle in ihm enthaltenen einzelnen Sprites im Score löschen (nicht aber die Darsteller!). Einzelne Darsteller dieser Loop darf man nicht mehr für andere Sprites verwenden, da sich sonst insbesondere beim Skripten Probleme ergeben.

Will man einen Ink-Effekt, so muss man den schon an den Ausgangssprites anwenden. Filmschleifen werden nicht gezeigt, wenn man den Frame Pointer händisch bewegt. Erst beim Abspielen über den Controller werden sie aktiv. Dabei ist die Ablaufgeschwindigkeit der einzelnen Sprites durch die momentane Geschwindigkeit des Tempokanals gegeben und kann dort auch nachträglich verändert werden. (Download Filmschleife.sit)


Will man in der Filmschleife allerdings mehr Eigenschaften festlegen, als es bei der oben angeführten Methode möglich ist (z.B. Mouseaktionen), so kann man einen eigenen Director-Film mit allem Drum und Dran erzeugen und dann diesen importieren. Dabei werden alle Darsteller (auch Verhalten etc.) in die Besetzungsliste einzeln importiert. Allerdings wird auch in diesem Fall das Tempo durch den übergeordneten Film bestimmt, ebenso der Bezug auf the frame etc. Zu beachten ist, dass man jeweils auf der Registerkarte eines Directorfilmdarstellers die entsprechenden Eigenschaften festsetzt. Soll also der importierte Film kleiner sein, so muss das vor dem Import festgelegt worden sein.

1.2.1.7 Media-Darsteller (Insert>Media Element>…)

Ein wichtiger Mediadarsteller ist der Typ "Font". Mit ihm kann man im Director-Film verwendete Fonts einbetten.

Siehe auch das Kapitel Flashkomponenten.

1.2.1.8 Ton

Tondarsteller werden in einen der acht Soundkanäle importiert und werden dort time-based abgespielt. D.h. sie haben ihren eigenen zeitlichen Ablauf und hängen nicht mit dem Abspielkopf zusammen. Deshalb beginnt in den beiden Drehbuchbasierten Tonkanälen 1 und 2 auch ein Sound zu spielen, wenn der Abspielkopf das entsprechende Frame errreicht, hört aber sofort wieder auf, wenn der Kopf das Frame verlässt, sofern sich der Tonsprite nicht auch auf das nächste Frame erstreckt. Will man die Steuerung des Abspielkopfes vom Tonabspielen abhängig machen, muss man im Tempokanal Cuepoints verwenden oder mit Lingo arbeiten (siehe Kap 3). Die Tonkanäle 3 bis 8 sind nur über Skripting in Lingo ansprechbar.

Auch .mp3 kann direkt importiert werden (zumindest unter OSX am Mac).

Seit Director 11 gibts es einen eigenen Darsteller, den Mixer. Näheres darüber findet sich in Kap. 3.7

1.2.1.9 Digitales Video

Der prinzipielle Unterschied zwischen Director und Quicktime oder .avi Movies besteht darin, dass letztere time-based sind, d.h. sie haben ihre eigene, interne Ablaufsteuerung. Außerdem hat intern der Tonkanal Priorität. D.h. die DV- Filme droppen mehr oder weniger Bildframes, wenn es nötig ist um einen kontinuierlichen Ablauf des Tons zu gewährleisten.

Es gibt grundsätzlich 3 Typen von DV, nämlich Quicktime, .avi und QuicktimeVR

DV kann über FILE>IMPORT importiert werden. Die Verwendung von Insert>Media Element>Quicktime bringt nur ein leeres Darstellerfenster vom Typ QT. Am Mac verwendet man nur Quicktime-.mov Dateien. Nötigenfalls kodiert man andere DV-Formate vorher um, wobei ein als Quicktime-.dv kodiertes Video nicht importierbar ist, sondern erst über den Quicktime Player in ein .mov verwandelt werden muss.

Unter Windows wählt man dann aus dem Files of Type - Pop-up Menü entweder QuickTime, .avi, oder RealMedia. Im Media pop-up Menü braucht man keine Auswahl zu treffen, da der Import immer gelinkt ist. Das impliziert auch, dass die Quelldatei immer mit dem Directorfilm mitgeliefert werden muss. Importiert man ein .avi File, so kann man zwischen QuickTime und .avi als Importformat wählen. wählt man QuickTime, so importiert Director das Video als QuickTime Asset Xtra, das zusätzliche Abspieloptionen ermöglicht, wie man durch anklicken des QT oder .avi-Reiters im PI erkennen kann. Außerdem unterstützt das "QuickTime Asset Xtra" QuickTime-Medien direkt. Der User muss keinen QT-Player haben um die Filme innerhalb von DirectorMovies anschauen zu können. Allerdings muss man darauf achten, dass auch das entsprechende Xtra mit dem Projektor mitgeliefert wird.(Checken unter Modifizieren>Film>Xtras)

Wenn der Abspielkopf das Frame mit dem DV erreicht, beginnt dieses - sofern PauseAtStart false und controller »false« (siehe später) eingestellt ist - zu spielen und spielt, da Film so wie Ton sound-basiert ist so lange weiter, bis der Kopf das Frame verlässt. Will man, dass der Kopf das Frame erst verlässt, wenn der Film aus ist, so setzt man im Tempokanal einen cue point. Weitere Steuerungen sind über cue points im sound track des DV möglich.

Mittels des PI kann man wichtige Eigenschaften des Films voreinstellen. Der PI sollte auf Listendarstellung stehen um alle Optionen zu sehen. Dabei unterscheidet der PI zwischen QT, .avi und RealMedia. Im folgenden die Einstellungen für QT und .avi (RealMedia ist sehr eingeschränkt):

Hat das DV einen weißen Rand, so setzt man die ink auf Background Transparent. Allerdings funktionieren inks dann nicht, wenn Direct to Stage true ist. Die inkform Matte funktioniert nie.
Ist der Spritefenster kleiner oder größer als das eigentliche DV, so gibt es zwei Möglichkeiten, nämlich crop true oder false. Ist crop true, wird das DV in das Spritefenster eingepasst, also verzerrt. Ist crop false, so wird - wenn center false ist -das linke obere Eck des DV an das linke obere Eck des Spritefensters gebracht, oder - wenn center true ist - die Mitte des DV mit der Mitte des Spritefensters übereingestimmt.
Mit sound oder video true oder false kann man bestimmen welche Tracks eines DV gespielt werden sollen.
PausedatStart verhindert dass das DV sofort loslegt, wenn der Director-Film an die entsprechende Stelle kommt.
Loop lässt den Film jedes Mal wenn er am Ende ist wieder von vorne beginnen.
Ist DTS true, so kontrolliert der QT- oder .avi-Treiber des Computers das Abspielen. Damit erreicht man zwar die beste Performance, hat aber zwei Einschränkungen, nämlich dass die inks nicht funktionieren und dass das Videosprite immer über allen anderen Sprites liegt, unabhängig davon in welchem Kanal es steht. Allerdings kann man dann mit mask eine Maske über das Video legen.
Außerdem kann man bei DTS true die framerate festlegen. Dabei bedeutet o eine Synchronisation des Films zum Ton, Framerate -1 spielt jedes frame mit der im DV-Film festgesetzten Rate; -2 spielt den Film in maximal möglicher Geschwindigkeit. Positive Werte bedeuten einen der Zahl entsprechenden Tempofaktor. Der Ton bleibt nur bei 0 und -1 erhalten. Die Geschwindigkeit und Richtung ist aber viel sinnvoller durch .movierate zu gestalten.
Controls true (QuickTime only) zeigt eine Steuerleiste am unteren Rand des Fensters, wenn DTS true ist.
Preload (.avi only) ladet das cast member wenn das Director-Movie beginnt.
Streaming (QuickTime only) Der bereits geladene teil des DV beginnt schon zu spielen während noch der Rest geladen wird.

QT-Videos haben zum Unterschied von anderen Darstellern im PI einen Dateinamen in welchem der ganze Pfad angegeben ist. Das führt bei abhängigen .dxr Filmen dazu, dass am Mac erstellte Filme, wenn man sie für Windows veröffentlicht den Pfad nicht korrekt updaten, sodass die QTs nicht gefunden werden. Will man QT auf Windows verwenden ist es daher nötig, alle Filme in eine Datei zu packen.

Über QTVR siehe später.

1.2.1.10 Skripts

Eine weitere Art von Darstellern sind die Skript-Darsteller. Jeder Programmiertext, mit dem bestimmte Verhalten ausgelöst werden können (siehe Abschnitt 4), werden ebenfalls als Darsteller in der Besetzung abgelegt. Bei den Skripten unterscheidet man dann zwischen drei verschiedenen Typen: Den Verhalten, den Filmskripts und den Parentscripts.

1.2.2 Sprites

Sind Instanzen der Members. Wenn - in Analogie - Humphrey Bogart der Darsteller (member) eines Spielfilms ist, dann ist der Sprite die Abbildung von ihm auf einem Frame des Filmstreifens.

Man kann abfragen welches Member einem Sprite zugeordnet ist mit put sprite(kanalnummer).member. Entsprechend kann man einem Sprite auch ein neues Member zuordnen.

Mit einer Property-Variablen kann man einen Sprite auch mit einem bedeutungsvolleren Namen referenzieren. Hat man z.B. einen Sprite, dessen Member ein Ball ist, so kann man den Ort des Balls (.loc-Eigenschaft) so referenzieren, wenn man folgendes Skript auf den Ballsprite zieht:

property ball

on beginsprite me
    ball=sprite(me.spriteNum)
end

on mouseup
    put ball.loc
end

wobei spriteNum ein reserviertes Wort ist und die Kanalnummer des betroffenen Sprites wiedergibt.

Sehr oft arbeitet man in Director mit Platzhaltern. Das bedeutet, dass man den Aufbau im Scorefenster erstellt, bevor noch die endgültigen Bilder oder Filme vorliegen. Man verwendet sozusagen zunächst einmal Statisten statt der teuren Stars. Hat man nun bereits einen Sprite auf der Bühne platziert, eventuell sogar ein Behavior angehängt und will aber dann den Darsteller austauschen, so muss man, um alle Eigenschaften des Sprites, wie z. B. die Position auf der Bühne zu erhalten, den Sprite im Score anwählen, dann im Cast den Darsteller und schließlich Edit>Exchange Cast Memebers anwählen. (Alternativ kann man dasselbe im msg-Fenster bewirken, indem man sprite(n).member = member(m) und anschließend auf die Bühne klickt oder im msg-fenster updatestage eingibt.). Dabei ist es wichtig zu beachten, dass man im Lingo keine Referenz zur absoluten Position des Darstellers im Castfenster gemacht hat, da sich der nunmehr verwendete Darsteller wahrscheinlich auf einer anderen Position befinden wird als der Platzhalter. Letzteren könnte man auch einfach löschen und den eigentlich zu verwendenden Darsteller an seine Position im Castfenster setzen. Dabei verliert man jedoch alle Bezüge zum Drehbuch und der neue Darsteller besitzt nicht mehr die am alten angehängten Skripts.

Ab Version MX 2004 ist es auch möglich Spritekanälen (durch Doppleklicken im Scorefenster) und Sprites (durch Eintrag im PI und Darstellung durch Einstellen des Menüpunkts Namen im Popup-Menü des Scorefensters) Namen zuzuordnen.

Das hat denVorteil dass man sich bei Lingoreferenzierungen auf den Namen des Spritekanals beziehen kann und es dadurch nichts ausmacht, wenn man den Sprite während der Entwicklung in einen anderen Kanal zieht, sofern man diesen umbenennt. Allerdings kann man nicht einfach schreiben:

sprite("Nord").visible=True --geht nicht

sondern

channel("Nord").sprite.visible=0

zur Vereinfachung könnte man etwa so vorgehen:

SprN=channel("Nord").sprite
SprN.visible=0

Darstellungsoptionen unter Director>Preferences>Sprite (unter Windows: File>Preferences>Sprite). Display sprite frame (Spritebilder anzeigen) erzeugt als Default bei der Neuerstellung eines Sprites im Drehbuch ein kleines Kästchen in jedem Frame, sodass leicht eine einzelne Zelle angewählt werden kann. Ist diese Option abgewählt, muss man zu diesem Zweck den Sprite an der geeigneten Stelle opt-klicken. Durch normalen Klick wird ansonsten das ganze Sprite gewählt.

Manchmal ist es von Vorteil die einzelnen Zellen breiter zu machen um mehr Inhalt lesen zu können. Man kann dies durch Eingabe der Breite am rechten Rand des Drehbuchfensters machen:

Um das Drehbuch übersichtlicher zu gestalten, kann man besetzten Zellen bestimmte Farben zuordnen. Die Auswahl der möglichen Farben ist am unteren Rand der Kanalnummernliste zu treffen

Auschnitt Drehbuchfenster

Die Arten von Inks sind über den PI wählbar.

Wenn ein Sprite im Drehbuch einen Kreis hat, so bedeutet das, dass sich dort Keyframe befindet und somit seine Eigenschaften an dieser Stelle verändert werden können. Keyframes erzeugt man z.B. durch Insert>Keyframe, gelöscht werden sie durch Insert>Remove Keyframe. Fügt man ein Keyframe in ein gegebenes Sprite ein, so erzeugt Director mittels Tweening In-betweens vom vorigen bis zu diesem Keyframe, sofern diese Option im Menü Modify>Sprite>Tweening eingestellt ist. Das geht mit Bewegung (durch Verschieben des Sprites auf der Bühne), Rotation (aus der Eigenschaftsfestlegung im PI des Sprites), Farben usw. (Download RotationsTweening.sit).

Ein komplexeres Beispiel mit Tweening ist das folgende, bei dem der ins Tor fliegende Ball nicht nur rotiert, sondern, um die Entfernung zu simulieren, auch kleiner wird. Dabei ist es sinnvoller ein großes Sprite zu verkleinern und nicht vom einem kleinen Sprite auszugehen, das man vergrößert, weil man im letzteren Fall eine deutliche Verschlechterung der Auflösung erleidet. (Beachte im Beispiel die Sichtbarkeiten durch entsprechende Kanalbelegungen). (Download Goal.sit 04MB).

Zur einfacheren Platzierung von Sprites gibt es im PI des Films ein Gitter (grid) und Hilfslinien (guides). Die Hilfslinien werden mit Klick and Drag vom PI auf die Bühne gezogen. Das Anbinden von Sprites an die entsprechendenan Hilfslinien hängt davon ab, wo man den Sprite anfasst. Es zeigt sich dann an einer Stelle des Sprite ein großes Plus-Zeichen das die "magnetische" Stelle angibt.

Sprites, die man nicht mehr verändern will, kann man im Sprite Toolbar im PI locken (sperren). Allerdings muss man dabei aufpassen, dass kein Laufzeitfehler in Bezug auf die Bitmap-Erstellung des gesperrten Sprites passiert!

Einem Sprite kann auch ein sogenanntes Behavior angehängt werden. Es handelt sich dabei um eine Art von Lingo-Skript, das dadurch mit dem Sprite verbunden wird, dass man es aus dem Cast-Fenster über das auf der Bühne befindliche Sprite drüberzieht. Man kann den Skriptdarsteller aber auch über den Sprite in der entsprechenden Zelle des Scores ziehen. Sollten wider Erwarten Hindernisse auftauchen, so liegt es meist daran, dass das verwedete Skript vom Typ Film statt vom Typ Verhalten ist. Das lässt sich im PI berichtigen. Anstatt selbst solche Lingodarsteller zu erzeugen, kann man auch fertige Darsteller aus einer Bibliothek wählen und sie über den Sprite ziehen, dem man das entsprechende Verhalten zuweisen will. Mittels Fenster>Bibliothekspalette das entsprechende Skript auswählen und dann über den Sprite ziehen.

über Spriteeigenschaften betreffend die Koordinaten siehe später

Setzt man den Registrierungspunkt des Darstellers außerhalb seines sichtbaren Bereichs, kann man erstaunliche Effekte beim Rotieren des Sprites erreichen.


Und noch eine Bemerkung dazu auf was alles sich der Begriff sprite beziehen kann. Nehmen wir folgendes Beispiel:

on beginsprite me
   Kutsche=sprite(me.spritenum)
   x=member("Kutsche").sprite
   put Kutsche.spritenum,"x: ",x
end

wobei der Darsteller "Kutsche" der 2. Darsteller der Besetzung ist, sein Sprite aber in Kanal 4 des Drehbuchs liegt. Die Prozedur liefert das Resultat

-- 4 "x: " (sprite 2)

Das heißt also, dass die Zuordnung der Spriteeigenschaften auf der Bühne, wie z.B. das .loc nicht als member("Kutsche").sprite.loc erfolgen dürfen, da der Darsteller selbst sich ja nicht auf der Bühne befindet und folglich den Wert point(0,0) liefert, sondern als Verhaltensskript des Sprites sprite(me.spritenum).loc wobei spritenum die Nummer des Spritekanals bedeutet.


1.2.2.1 Übersicht über Spriteigenschaften

sprite(1).blend gibt den Grad der Transparenz zwischen 0 (voll transparent) bis 100 (total deckend). Durch erhöhen des Werts kann man einen Sprite aus dem Nichts auftauchen lassen. (Updatestage nicht vergessen). Will man aber während der Änderung des Wertes eingreifen (z.B. Schimmern Bergkristalle, ein Mausklick soll aber zu einem anderen Frame führen, so ist es sinnvoller, die .blend-Änderung über verschiedene Frames ablaufen zu lassen, so dass immer ein exitframe zwischen den Änderungen auftritt. Dazu muss man nicht unbedingt eine lange Framereihe bemühen, sondern kann zwischen zwei Frames hin und her pendeln und über einen Counter die Eigenschaft steuern.

sprite(1).visible kann die Werte true oder false haben.

 

1.3 Das Drehbuch (Score)

es enthält Channels, Kanäle, die man ein- und ausschalten kann, sowie Frames, entsprechend den einzelnen Bildern eines Kinofilms. Auf dem Schnittpunkt der beiden liegt eine einzelne Zelle. Rechts oben am Fenster gibt es eine Stelle an der man die Spezialeffektkanäle sichtbar oder unsichtbar machen kann. (Darunter ein Zoom für die Framebreite).

Wählt man einen Framebereich dadurch aus, dass man eine Zelle in einem Kanal anklickt und dann eine weitere Zelle mittels shift-klick, so kann man mit CONTROL>SELECTED FRAMES ONLY den Abspielbereich auf diese Auswahl beschränken. Der ausgewählte Bereich wird im Scorefenster grün angezeigt. Um die Auswahl aufzuheben, entfernt man das check mark im Menü.

Klickt man links auf die Kanalnummer, so werden solche Kanäle, die noch keinen Sprite enthalten schwarz eingefärbt. Das ist nützlich, wenn man noch vollkommen leere Kanäle sucht.

1.3.1 Die nummerierten Spritekanäle

Sprites eines Darstellers befinden sich in Kanälen. Diese sind nummeriert oder können ab DW MX 2004 auch mit Namen bezeichnet werden, was für die Programmierung in Lingo gewisse Vorteile bringt. Die Kanäle sind auch zuständig für die Sichtbarkeiten. je niedrige die Kanalzahl ist, desto weiter hinten auf der Bühne befindet sich der Sprite. Deshalb sollten Bühnenhintergründe immer in den Spritekanal 1 gelegt werden. Allenfalls kann man allerdings auch nachträglich über Lingo die Schichtungen verändern.

Um eine einzelne Zelle eines Sprites auszuwählen muss man sie alt-klicken. Über das Insert-Menü kann man Zellen einfügen oder entfernen. Die Marker werden mitverschoben.

Um einen Sprite zu zersägen wählt man Modify>Split Sprite

1.3.2 Die Spezialkanäle

Im Tempokanal gibt es nach doppelklicken auf eine Zelle verschiedene Optionen. Zunächste einmal kann man hier die Framerate vorgeben. Je schneller der Film läuft, desto glatter werden Animationen, weil man bei doppeltem Tempo doppelt so viele Frames für eine Animation einer gegebenen Dauer verwenden kann. Auch die Reaktion auf messages und Befehle erfolgt prompter. Allerdings kostet schnellers Tempo auch höhere Leistung der CPU. Aber achtung bug: Hat man im Fenster Steuerpult eine Geschwindigkeit vorgegeben und versucht später im Tempokanal eine andere Geschwindigkeit einzuprogrammieren, kann es zum Absturz des Programms kommen  (so geschehen mit Director 11.5 mit MacOS 10.2.6). Bei der Option "wait for Mouse Click or Key Press" muss das stage window aktiv sein, damit Key Press auch im Authormodus funktioniert. Ist das Stage window nicht das vorderste, funktioniert zwar Mausklick, aber nicht Key Press.

Eine für Musiker wichtige Option ist WAIT FOR CUE POINT. Damit kann man das Weiterrücken des Abspielkopfes von Markern abhängig machen, die man an beliebigen Stellen einer Audiodatei setzen kann. Dieses Setzen erfolgt zum Beispiel mit dem Programm Peak (für Mac) oder Soundforge 5.0 (für Win).

Die Framerate kann außerdem auch per Lingo programmiert werden. Mit Hilfe des Befehls

_movie.puppetTempo(n)

kann man die Ablaufgeschwindigkeit variabel in Abhängigkeit von anderen Parametern gestalten. n muss eine Integer sein und gibt den Wert in fps an. Natürlich ist diese nach oben hin durch die Leistungsstärke des Rechners begrenzt.

Palettenkanal: Das Einfügen von 8-bit Paletten wird für CD-ROMs zusehends unwichtiger, da die üblichen Farbtiefen bereits bei 16-bit liegen, hat allerdings Bedeutung für das Netz. Will man eine zum Bild passende Palette haben, so muss man in einem Programm sichern, das indexed colors unterstützt (z.B. Photoshop BILD>MODUS>INDIZIERTE FARBEN, beim sichern Farbprofil einbetten). Dabei erzeugt man eine Palette, die - wenn sie kompatibel ist - anschließend als eigener Darstellerbeim Import des Bildes mit importiert werden kann.

(Zum schwierig zu gebrauchenden Effekt des Color Cycling siehe [3, S. 91ff]. Dabei werden die gewählten Farben der Palette im Radl verschoben. Die Auswirkung besteht auf alle Objekte, die diese Farben enthalten, weshalb man dabei darauf achten muss, dass "farbstabile" Teile des Schirms keine dieser Farben enthalten dürfen. )

Transitions im Drehbuch müssen in dem Frame stehen in das gewechselt wird, passieren also beim Eingang in ein neues Frame. Wenn sie in Lingo programmiert sind, muss das Skript(z.B. im exitframe handler) des zu verlassenden Frame stehen! (Download (Puppet)Transitions.sit)

Ein spezielles Problem stellen Frames dar, bei denen eine Schleife in Form von on exitframe - go to the frame im Score Behavior steht. Auf ihnen darf keine Transition stehen, da jede Veränderung in dem Frame (z.B. Austausch eines Members) wiederum mit der Transition passiert und damit zu langsam wird. Das bedeutet, dass Sounds hacken, Videos stottern usw. In so einem Fall macht man die Transition in ein Frame ohne Loop, das sofort in ein gelooptes Frame mit den selben Darstellern weitergeht.

Fehler Es gibt verschiedene nützliche Übergänge von Drittherstellern, insbesondere den Crossfade-Übergang DMFade xtra. Man kann solche Übergänge als Puppet schreiben, z.B.

_movie.puppetTransition member("fadeTrans",tempTime,1,false)

wobei tempTime die Anzahl von Sekunden für den Übergang angibt. Jedoch kann man diese Vorgangsweise nur für systemeigene Übergänge wählen. Bei Übergängen von Drittherstellern muss man für jedes Übergangstempo einen eigenen Darsteller mit entsprechenden expliziten Zeitangaben wählen, also

_movie.puppetTransition member("fadeTrans_1sek")
_movie.puppetTransition member("fadeTrans_8sek")

etc.

Man sollte Pixel dissolve-Transitions vermeiden, da sie beim Abspielen auf einer anderen Plattform als auf der sie programmiert wurden erheblich langsamer sein können.

Ab Director 8 gibt es neben den Frame-transitions auch Sprite-transitions, die nur ein einzelnes Sprite betreffen und über eine Reihe von Frames passieren. Sie benutzen Imaging Lingo und man findet sie in der Behavior library unter ANIMATION>SPRITE TRANSITION. Man zieht das Behavior auf das entsprechende Sprite und gibt in der sich öffnenden Dialogbox die Parameter ein. Um eine Transition zu löschen, muss man ins behavior pop-up menu des Scores

Imaging Lingo erlaubt sogar das Manipulieren eines einzelnen Pixels eines Sprites, ist aber sehr komplex.

Statt Sounds und Transitions im Drehbuch zu steuern kann man sie auch puppetieren. Auch Sprites können zu Puppets gemacht werden. Mehr davon später.

1.4 Der Cast (Besetzung)

Alle Darsteller werden entweder in einen Cast importiert oder scheinen nach Erzeugung in einem der Werkzeugfenster zur Castherstellung dort auf. A priori gibt es eine Besetzung mit der Bezeichnung internal. Man kann in File>New>Cast eine neue Besetzungsliste (castlib) anlegen. Wenn sie external ist, so stellt sie ein eigenes File dar, das immer mit dem Projektor mitgeliefert werden muss. Der Vorteil einer externen Besetzungsliste liegt darin, dass sie mit mehreren Projekten verbunden werden kann, wenn diese immer eine solche Besetzung verwenden. Sowohl interne als auch externe Besetzungen können über Modifizieren>Film>Besetzungen>Verknüpfen in das Projekt eingebracht und auf dem selben Weg auch wieder entfernt werden. Der Name einer aktiven Castlib kann im PI geändert werden.

Eine Besetzung z.B. mit dem Namen Skripts kann man durch Group Scripts With>New Panel Group gruppieren.


Beim Öffnen eines Filmes mit externen Besetzungen kann es vorkommen, dass nach dem Öffnen nur die interne Besetzung zu sehen ist.  Die anderen Besetzungen tauchen aber dann wieder als Tabs auf, wenn man auf den Button "Besetzung auswählen" im linken oberen Eck des Besetzungsfensters klickt und die nicht als Tab sichtbaren Besetzungen im Pull-Down Menü aufruft.

Um die Pfadangabe eines Casts zu verändern bedient man sich des PIs

Will man eine vorhandene Besetzung zeitweilig unsichtbar machen, so führt man einen ctrl-Klick auf ihren Tab aus und wählt aus dem Pop-up schließen.

Es besteht auch die wichtige Möglichkeit eine Besetzung mittels eines Lingobefehls auszutauschen. So kann man z.B. der Besetzung it dem Namen "Buttons" die auf der Platte gespeicherte Besetzung "MeineTasten.cst" zuordnen.

castLib("Buttons").fileName = _movie.path & "MeineTasten.cst"
Näheres zu externen Casts in Kap. 8.2

2. Animation

Eine ganz einfache Art der Animation haben wir schon bei den Spriteeffekten kennen gelernt. Eine weitere interessante Art der Animation bietet das Xtra AutoDistort. Mit seiner Hilfe kann man Paint-Darsteller folgendermaßen animieren: Man wählt den Darsteller aus und transformiert ihn dann mittels des Rotations- oder Verzerrungswerkzeugs oder durch Resizing. Anschließend wählt man das Xtra AutoDistort und gibt im sich öffnenden Dialogfeld die Anzahl der zu erzeugenden Darsteller ein. Der Darsteller darf noch keinen Sprite auf der Bühne haben. Dann wählt man im cast window die von AutoDistort erzeugten neuen Darsteller aus und geht unter MODIFY>CAST TO TIME um einen Sprite der gewählten Darsteller zu erzeugen, das sich über genau dieselbe Anzahl von frames erstreckt wie die Anzahl der cast members war. Will man die Bewegung nun zyklisch gestalten, so kopiert man den Sprite, setzt es neben das bereits existierende und wählt - solange es noch angewählt ist - MODIFY>REVERSE SEQUENCE. Dadurch wird der zeitliche Verlauf umgekehrt und die Bewegung geht wieder rückwärts. (Das erste Spriteframe muss man löschen, da es sonst zweimal gespielt wird und der Film dann ruckelt) [4], {[1] S. 64ff}. (Download AutoDistort.sit).

2.1 Keyframes

Wird durch INSERT>KEYFRAME erzeugt. Ändert man dann die Position dieses Sprites, so werden In-Betweens vom Beginn bis zu diesem Keyframe erzeugt. Ändert man die Mittelpunkts-handle des Sprites, so wird das letzte Frame des Sprites verändert und es werden ebenfalls In-betweens erzeugt.

Auch durch Ändern eines Punktes auf dem Pfad wird ein Keyframe erzeugt. Dazu muss der Scorepointer natürlich im betreffenden Frame auf dem betreffenden Sprite stehen.

Pfade von Sprites kann man ändern durch: Modify>Sprite>Tweening. Man kann nicht nur Pfade von Sprites tweenen, sondern auch Eigenschaften (im PI) (z.B. Copy von 100% auf 20% über eine Anzahl von Sprites oder sukzessive Änderung des Winkels)

2.2 Realtime und steptime recording

Real-Time recording: den Sprite auswählen und Control>Real-Time Recording. Sprite herumziehen und dann auslassen. Eine andere Möglichkeit ist Control>Step Recording. Der zu klickende Step-button erscheint im Score am Kanalbeginn. Unter OS 10.2.4 und Director MX bewegt er aber den Abspielkopf nicht weiter. Verwendet man hingegen den Step-Befehl im Control Panel, so funktioniert es. Man kann auch einen eingeschränkten Bereich von Zellen wählen und im Control Menü auf Selected Frames Only klicken.

2.3 geschlossene Animationsverläufe

Hat man in einem Sprite einen Verlauf über mehrere Frames, so kann man das selbe Sprite an das ursprüngliche anhängen und seine Zeitlinie umkehren mit MODIFY>REVERSE SEQUENCE.

2.4 cast to time

Einige members im Cast window auswählen und MODIFY>Cast to time. Dadurch entsteht ein neuer Sprite mit einer Framelänge entsprechend der Anzahl der verwendeten Casts. Für den Sprite gibt es keinen Darsteller!

2.5 space to time

Einige Sprites auswählen und MODIFY>Space to time. Die Sprites dürfen aber nur über 1 Frame gehen.Diese Sprites werden als Keyframes genommen und dazwischen kann beim umwandeln noch eine Anzahl weiterer Punkte interpoliert werden. Auch ein nachträgliches Verändern ist über den Pfadvektor möglich.

2.6 Animation durch Filtereffekte

Man kann Filtereffekte, z.B. in Photoshop mehrfach auf ein und denselben Bereich eines Bitmaps anwenden. Speichert man nach jeder Stufe ein Bild ab, so erhält man eine animierte Filterwirkung (download AnimFilter.Sit)

2.7 Ordnung auf der Bühne

Das Ausrichten mehrere Sprites geschieht so, dass man sie aktiviert und dann mit Modify>Align ausrichtet. Auch die magnetischen Hilfslinien und Raster im movie-PI dienen der Ausrichtung.

2.8 Behaviors und Filmskripts

Skripts vom Typ Behavior kann man in den Skriptkanal des Drehbuchs setzen, oder an einen Darsteller oder einen Sprite anhängen . In letzterem Fall können sie an ein ganzes Sprite angehängt werden oder an nur ein Frame des Sprites. Eine Methode besteht darin, die Skripts mit Hilfe der Sprache LINGO selbst zu schreiben. Dadurch kann man jede Art von Skript erzeugen mit jedweder Art von Funktion.

Eine andere Methode besteht darin nachzusehen, ob die gesuchte Funktionalität bereits in einem vorgefertigten Skript enthalten ist. Man findet diese Skripts im Object Inspector unter Code Library. Man braucht das Skript von dort nur mehr zum Beispiel auf den Sprite auf der Bühne zu ziehen und in manchen Fällen dann noch in einem Dialog Parameter zu setzen. Um z.B. eine URL an einen Sprite zu hängen: WINDOW>LIBRARY PALETTE, aus dem Castbutton links oben NAVIGATION auswählen und go to URL auf den Sprite ziehen. Insgesamt hat diese Methode den Nachteil, dass es nur eine begrenzte Anzahl von Behaviors gibt und dass es auch für mäßig Fortgeschrittene meist unmöglich ist, diese Skripts, wenngleich auch ihr Code als Darsteller in der Besetzung nachlesbar ist, zu verstehen geschweige denn zu debuggen wenn irgend ein Fehler auftaucht.

Filmskripts sind Skripts, die an keinem Ort (frame, sprite, member) festgemacht sind. Sämtliche Prozeduren, die einen selbst definierten Handlernamen haben (on MeineEigeneProzedur) sollten von diesem Typ sein.

2.9 Quicktimefilme

Wie schon an anderer Stelle erwähnt lassen sich QT-movies in das Drehbuch einfügen. Wenn man jedoch eine Animation aus einer Reihe von Bildern erstellen will, ist es immer sinnvoller, die Bilder einzeln einzusetzen oder eine Filmschleife zu bauen, denn wenn man aus mehreren Bildern ein QT macht und dieses dann einsetzt, ergeben sich oft im QT veränderte Farben durch die bei der Erstellung des Videos erfolgte Kompression.

2.10 Welleneffekte

Wellen kann man auf verschiedene Arten herstellen. Die besten Methoden sind entweder das Verwenden eines 3rd-Party Tools wie dem Welleneffekt von DM-Tools oder aber auch das Verwenden zweier Bilder, die man aus einem Ausgangsbild mit Hilfe des PS-Filters Verzerrungsfilter>Kräuseln… erzeugt hat ( in diesem Filter z.B. mit den Werten von -50 und +20). Die beiden Bilder werden übereinander gelegt und die Transparenz des oberen Bildes (höhere Kanalnummer im Drehbuch) wird periodisch zwischen 0 und 100% kontinuierlich gewechselt.

3. Sound

Sound kann in den letzten Versionen des Programms nicht nur in Stereo, sondern sogar in 5.1 Surround verarbeitet werden.

Sounddateien (.mp3, .waf, .aiff,…) können genauso wie Bild- oder Textdateien importiert werden. Bei größeren Projekten empfiehlt es sich, für jeden Dateityp einen eigenen Cast anzulegen. Sind die Sounddateien sehr umfangreich, wird man sie nicht in das Projekt importieren, sondern extern mit einer Verknüpfung anlegen. Natürlich müssen verknüpfte Dateien jeweils mit einem Projektor mitgegeben werden, am sinnvollsten in einem Ordner eine Ebene unter dem Projektor. Hat man mehrere verknüpfte externe Dateien und importiert mehrere Sounds gleichzeitig, so passiert es, dass die Sounddateien in die letzte der externen Dateien landen. Man muss sie dann nötigenfalls von dort mit KlickenUndZiehen in den richtigen Dateiordner verschieben.

Das Austauschen von Sounddarstellern die bereits in einem Soundkanal im Drehbuch vorhanden sind geschieht am besten folgendermaßen (danke Knut Müller für den Tipp):
Den neuen Sound in die Sound.cst irgendwo am Ende importieren - Umbenennen in den Namen, den der Sound hat, den man ersetzen will - Dann den neuen, umbenannten Sound via Apfel+X ausschneiden - Den alten, zu ersetzenden Sound auswählen und dann Apfel+V einsetzen. Auf den neuen Darsteller (mit dem alten Namen) beziehen sich jetzt alle Sprites oder Aufrufe, wenn er A) an der selben Stelle im cast ist und B) den selben Namen hat.

In Director 11.5 gab es einen schwerwiegenden Programmfehler: Dateien, die mit einer älteren Directorversion (11.0) erstellt wurden, hatten nach dem Veröffentlichen den Soundlevel 0, egal wie er in Wirklichkeit eingestellt war. D.h. man hörte keinen Ton. Um dem abzuhelfen musste man entweder bei den Veröffentlichungseinstellungen beim Reiter Projektor statt Standard die Angabe Shockwave machen (wodurch Dateien komprimiert werden), auch wenn man gar nicht für das Netz veröffentlichen wollte. Dieses Phänomen tritt nur bei der veröffentlichten Datei auf, nicht in der Authoringumgebung!. Eine andere Möglichkeit bestand darin, eine neue Directordatei zu erstellen und alle Daten aus der alten mittels copy/paste zu übertragen. Mittlerweilen ist die Version 12 die aktuelle und das Aufarbeiten von Director 11-Dateien ist wohl nicht mehr so relevant.

Zunächst möchte ich auf ein paar typische Soundfallen eingehen: Oft beginnt ein Sound zu spät an zu spielen. In solch einem Fall muss man ihn mit queue vorausladen. Aber auch das hilft mitunter nichts, wenn man nicht genügend Zeit zwischen dem queue und dem play-Befehl einbaut. Umgekehrt schert sich das Programm nicht darum ob ein Sound noch weiter läuft oder schon vorbei ist. Will man also, dass das Programm wartet bis der Sound aus ist, so muss man anschließend an den play-Befehl abfragen ob der Sound noch spielt. Etwa so, wenn in Kanal 3 schon ein Sound in der queue liegt:

sound(3).play()
repeat while soundbusy(3)
end repeat

Es kann aber auch vorkommen, dass Soundbefehle dazu führen, dass Director in seinem restlichen Gebaren irritiert wird und dann z.B. sagt er könne einen bestimmten Bitmapdarsteller nicht korrekt aufbauen.

Man muss weiters bedenken, dass Sounds mitunter recht große Darsteller sein können. Man wird also da, wo es geht versuchen mit Loops auszukommen. Das gilt vor allem dann, wenn der Sond nicht den Mittelpunkt des Interesses einnimmt, sondern es sich etwa nur um eine Geräuschkulisse handelt. Damit man aber auch dort, besonders bei kurzen Schleifen, nicht so leicht erkennt, dass es sich um Loops handelt, verwendet man am besten zwei Loops von etwas unterschiedlicher Länge, sodass sich durch die Phasenverschiebung eine größere Vielfalt ergibt.

Die Lautstärke des Rechners lässt sich mittels

_sound.soundLevel = i mit i=0,...7

einstellen. Das ist insofern wichtig, da ja das Verwenden von Sounds in einem Film nur dann einen Sinn hat, wenn die Tonwiedergabe des Rechners nicht ausgeschaltet ist. Außerdem fungiert diese Methode als Mastersound Regler wenn man mehrere Kanäle mit separater Lautstärkensteuerung hat. Allerdings wird auch bei relativ geringer Lautstärke der Level 0 angezeigt, da sich der Bereich mit diesem Wert von Lautlosigkeit bis zu einer geringen Lautstärke erstreckt.

Sound abspielen ist eine recht CPU-intensive Tätigkeit. Daher unterbricht jede andere intensive Aktion den Sound kurzfristig. Will man z.B. während des Ablaufs eines Sounds etwa eine Sichtbarkeit verändern ("flackerndes" Licht bei Donner, wobei flackerndes Licht über die Sichtbarkeit von 2 oder mehr Darstellern gesteuert wird) und verwendet dazu Angaben wie warteTicks(20) mit

on warteTicks(seksDurch60)
  endZeit=the ticks+seksDurch60
  repeat while endZeit>the ticks
   nothing
  end repeat
end

so wird der Donnersound nicht mehr glatt ablaufen. Es ist dann sinnvoller in einem frameloop the timer (siehe Kap. 4.3.6) zu verwenden.

3.1 Sounddarsteller

Immer gut verwendbar ist das .aiff oder .aif-Format (audio interchange file format). Solche Dateien können aus den verschiedensten Quellen erstellt werden, so z.B. auch aus Notensatzprogrammen wie Sibelius oder Finale (Über das Erzeugen von Audiofiles aus Sibelius siehe sibelius lecture notes, Kap 13, aus Finale siehe finale lecture notes, Kap. 15).

.aif Soundfiles können auch mit Markierungen versehen werden. (auf dem Mac z.B. mittels Sound Studio oder Bias Peak , unter Windows mit SoundForge), mit deren Hilfe der Framepointer über den Tempokanal gesteuert werden kann. Bei .mp3-Dateien können keine Marker exportiert werden. Man muss sie also nach dem Einlesen und Bearbeiten als .aif sichern.

Mit Hilfe der verschiedenen cuepoint-Befehle kann man über Lingo den Ablauf des Framepointers steuern indem man im obersten Effektkanal des Drehbuchs auf das Erreichen eines Markers wartet. Z.B:

Hier wartet der Framepointer auf das Auftreten des Markers C2 in der in Kanal 1 abspielenden Datei Purcell_Funeral. Zu beachten ist allerdings, dass während die Musaik spielt, der Cursor nicht bewegt werden kann. Dieses Problem kann man dadurch lösen, dass man zu Beginn des Musikstücks eine Stoppuhr startet (starttimer) und dann on exitframe die abgelaufene Zeit abfragt und je nachdem weitergeht.

Auch Sounds im Quicktimeformat können mit Markern versehen werden. Das kann z.B. in iMovie geschehen, wo man Kapitelmarkierungen setzen kann (Normale Markierungen scheinen nicht als Marker auf). Dabei muss dann der Film für CD-ROM gesendet werden (das ergibt nämlich das richtige Kompressionsformat) und das QT-movie darf in Director nicht als streaming angegeben sein (im PI zu setzen). Man kann natürlich eine iMovie-Datei auch nur als .aiff exportieren und die Marker dann in Sound Studio oder SoundForge setzen.

Man kann die Arbeit mit Markierungen völlig umgehen, indem man den Ton in ein QT verpackt (QT-movies können ja auch ohne Videotrack nur mit einem Soundtrack ausgestattet sein). Ein QT erstellen kann man am einfachsten indem man z.B. ein .mp3 im QuickTime Player öffnet und dann einfach unter sichern… als .mov exportiert. Die wichtigen Eigenschaften des QT-Movies sind zum Einen #currentTime, die die abgelaufene Zeit des Movies abfragt oder setzt. Diese Eigenschaft gibt also den Punkt der Zeitachse des Movies an, an dem es sich gerade befindet. Setzt man z.B.

sprite(9).currentTime = 0

so hat man das Movie zurückgespult. diecurrentTimewird in msek gemessen (nicht wie fälschlich in der Hilfe angegeben inTicks). So kann man bestimmen, dass etwas passiert, wenn die currentTime  eines QT-Sprites einen gewissen Wert überschritten hat.

Zum Anderen kann man mit der Eigenschaft #duration die Gesamtlänge eines Movies abfragen, wobei diese Eigenschaft eine des Members - nicht des Sprites ist.

put member("King Kong").duration

Ein Beispiel für einen Film unter Zuhilfenahme der oben angeführten Methoden in welchem Noten parallel zu einem abgespielten Sound weiterrücken findet man in dieser Datei: d/l NotenundSound.sit .

Will man einen QT-Film stoppen (damit er z.B. nicht weitergespielt wird, wenn auf der selben Seite ein anderes QT angeklickt wird), so kann man seine Abspielgeschwindigkeit auf null setzen:

sprite(1).movieRate=0

Eine weitere wichtige Fragestellung betrifft die, ob ein QT fertig abgespielt ist. Will man, dass der Framepointer erst nach dem Abspielen eines in Kanal 26 befindlichen QT-movies weitergeht, so verwendet man #trackNextSampleTime.

on exitFrame me
   if (sprite(26).trackNextSampleTime(1)=0) then go to the frame+1
   go to the frame
end

denn der Wert des nächsten Samples am Ende des Abspielens ist 0. Man erhält damit eine ähnliche Funktion wie soundbusy.

Man kann Sounddarsteller durch Anklicken des entsprechenden Reiters im Informationsfenster anhören. Da dieses Abspielen immer im Soundkanal 1 stattfindet. ist zu beachten, ob sound(1).volume auch tatsächlich >0 ist, sonst hört man nichts.

3.2 Sound im Scorefenster

Prinzipiell kan man, unabhängig von allen anderen Sound-Einstellungen angeben ob  Sounds zu hören sein sollen oder stumm bleiben. Man verwendet dazu die Boole'sche Variable _sound.soundEnabled.

Im Score gibt es 2 Spezialkanäle, in die Sound als .aif oder .mp3 importiert werden kann. Darüber hinaus kann man auch weitere sechs normale Kanäle mit Soundfiles belegen (siehe hier), wobei der Sound in einem passenden Format, wie z.B. als Quicktime vorliegen muss.

Sounds können auch geloopt werden (PI) (in dem Fall bleibt der Framepointer bei wait for cuepoint dann, wenn der Sound gar keine Cuepoint Angabe hat, auf dem Frame stehen wo der Sound ist).

Laut der Hilfedatei von Director 11 unterbindet unter Windows ein Sound, der bereits in einem der Soundkanäle abgespielt wird, die Wiedergabe des Filmtons eines QuickTime- oder .avi-Videos oder eines Flash-Inhalts. Der Videosound kann auch nach Beendigung der Soundwiedergabe auf dem Soundkanal nicht abgespielt werden. Andererseits verhindert eine laufende Wiedergabe des Sounds eines Digitalvideos, dass die Wiedergabe eines Sounds auf beiden Soundkanälen gestartet wird.
Wenn man QuickTime-Audiospuren mit internen Director-Sounds mischen möchten, muss man die Systemeigenschaft soundDevice auf "QT3Mix" einstellen oder den Microsoft DirectSound-Audiotreiber ab Version 5.0 installieren (erhältlich unter www.microsoft.com). Die Eigenschaft soundDevice muss auf "DirectSound" eingestellt werden. Weitere Informationen finden. Im Director Support Center findet man neueste Informationen zu diesem Problem. Unter Windows kann Director standardmäßig acht Sounds mischen. Man kann die Anzahl der mischbaren Sounds verringern, indem man den Wert für MixMaxChannels in der Datei "Director.ini" im Ordner "Director" ändert.

3.3 Soundkanäle

Obwohl es Im Scorefenster nur 2 Soundkanäle gibt, kann man 8, seit Version 11.5 des Programms 16 Kanäle in Lingo verwenden, als sound(i), i=1,..,16. Eine höhere Kanalnummer führt zu einer Fehlermeldung. Sound im Soundkanal beginnt zu spielen in dem Moment, wo der Abspielkopf den Frame erreicht oder nach einem updatestage Befehl. Natürlich darf der Befehl nicht als FrameScript mit einer Loop formuliert sein, weil sonst bei jedem Neueintritt der Sound neu zu spielen beginnt und man im Endeffekt nichts hört. In so einem Fall ist es sinnvoll, den Befehl in ein beginSprite-Script oder on mouseup zu setzen.

Organisatorisch ist es geschickt, Loopsounds und solche, die nicht geloopt sind zu unterscheiden, etwa durch Groß- und Kleinschreibung. Auch die Festlegung der Lautstärke eines Hintergrungsounds in einem größeren Projekt sollte über eine globale Variable geschene, damit sie im Bedarfsfall rasch und einfach geändert werden kann. Eine weitere Möglichkeit sich die Arbeit zu vereinfachen besteht dain, einen eigenen Handler zu schreiben wie zum Beispiel:

on playChosenSample(Kanal,Beispiel,Lautstaerke,Richtung,Endeabwarten)
--
bei 'Beispiel' ist, wenn man einen bestimmten Sounddarstellern SoundXY angibt, die Formulierung member("SoundXY"), also nicht nur den Name des Sounddarstellers einzugeben!


if Beispiel=void then _player.alert ("Beispiel in PlayChosenSample ist leer")
--Soundkanaleinstellungen werden in dieser Routine bei Abwarten des Endes des Sounds abgespeichert, damit beim Verlassen des Handlers der Status ante wiederhergestellt wird:

soundvorher=sound(Kanal).volume
richtungvorher=sound(Kanal).pan
sound(Kanal).volume=Lautstaerke
sound(Kanal).pan=Richtung
sound(Kanal).play(Beispiel)
if Endeabwarten then
repeat while soundbusy(Kanal)
nothing
end repeat

--das Folgende darf nicht laufen, wenn das Ende eines abspielenden Sounds nicht abgewartet wird, sonst überschreibt man momentane Lautstärke und Richtung

sound(Kanal).volume=soundvorher
sound(Kanal).pan=richtungvorher
end if
end

Abschalten eines Sounds erfolgt mit sound(Kanalnummer).stop(). Damit wird der Sound gestoppt. Sein .volume bleibt unverändert. und soundbusy(Kanalnummer) wird auf false gesetzt.

Es gibt einige Befehle, um Sound nicht nur abzuspielen, sondern auch zu gestalten. Da wäre zunächst einmal ein fade-in und fade-out mittels

sound(whichChannel).fadeIn(milliseconds) und sound(whichChannel).fadeOut(milliseconds).

Mit sound(whichChannel).fadeTo(volume,milliseconds) mit 0 ≤ volume ≤ 255, kann man die Lautstärke in der gegebenen Zeit auf den Wert "volume" ansteigen resp. absinken lassen, um zum Beispiel einen gesprochenen Text über der Musik deutlich hörbar zu machen (ducking). Bewegt man sich allerdings aus dem fame heraus bevor die gewünschte Lautstärke rreicht wurde, so bleibt der Kanal auf dem zuletzt erreichten Volume eingestellt.

Sound hat verschiedene weitere Eigenschaften: Um festzustellen wie lange (in msek) der Sound z.B. im Kanal 4 schon abgespielt wurde, gibt es die Eigenschaft sound(4).elapsedTime. Die Lautstärke des Soundkanals stellt man unter sound(whichChannel).volume ein, wobei Werte von 0 bis 255 möglich sind. Sound(2).pan=i gibt die Stereoeinstellung wieder, wobei -100≤i≤100 ist. -100 bedeutet, dass nur der linke Kanal gespielt wird, resp. bei einer Monoaufnahme diese nur im linken Lautsprecher zu hören ist, +100 bedeutet ausschließlich rechter Kanal. 0 ist Mitte.

Stoppen des Abspielens eines Sounds geschieht mit sound(1).stop() . Hat man in dem Kanal allerdings eine queue (siehe 3.4), so wird beim nächsten Soundaufruf von der gestoppten Stelle bis zum Ende der gesamten Queue weitergespielt bevor der nächste aufgerufene Sound oder die nächste queue daran anschließt. Dem kann man abhelfen, wenn man die Queue dadurch leert, dass man vor dem Abspielen der neuen Queue einen kurzen Sound z.B. 1ms Stille abspielt:

on AlteQueueloeschen
   sound(gSoundkanal).play(member("Stille1ms"))
end AlteQueueloeschen

Eine weitere Voraussetzung, dass gequeuete Sounds ordnungsgemäß abspielt ist, dass man nicht während des Abspielens dreinpfuscht. Also ist es sinnvoll nach dem Beginn des Abspiels etwas einzusetzen wie

on Fertigspielen
  repeat while (gSoundkanal)
   nothing
  end repeat
end Fertigspielen

Zur Tonhöhe siehe nächstes Kapitel.

Wichtig ist auch die Abfrage ob ein Sound noch läuft . Dazu verwendet man soundbusy(gSoundkanal).

Ein Problem ergibt sich beim Abspielen eines Sounds nach einem mouseup, wenn man während des Abspielens nochmals auf das sounderzeugende Sprite klickt. Wenn man das Ende des Sounds abwartet (soundbusy) und dann einen Befehl wie go to setzt, so hat sich das System den Mausklick trotzdem gemerkt und der Sound wird noch einmal abgespielt. Um das zu vermeiden muss man im mousedown-Befehl ein exit geben, falls der Sound noch spielt, damit der zweite und weitere Mausklicks ignoriert werden:

on mousedown
  if Soundbusy(3) then exit
  MusikSpielen
end

Eine Übersicht über alle unterstützte Soundelemente in Director 11.5 findet man hier in der Directorhilfe.

3.4 Mehrere Sounds

(siehe auch Kap. 3.7 Mixer).
Man kann mehrere Sounds in eine Queue einreihen, hat dann allerdings das Problem, dass eine Soundbusy-Abfrage nach dem Ende des ersten Sounds auf False geht. Solch ein Abspielen gestaltet man am besten so, dass man das Abspielen in ein beginsprite (notfalls eines Dummy-Sprites) setzt und im Frame mit der Exitframe-Loop ein Wait-Statement mit der Dauer der gesamten Queue gibt. Die Idee eine leere Schleife laufen zu lassen um die Zeit vergehen zu lassen ist schlecht, weils sie zu CPU-intensiv ist und den Sound unterbräche.

Wenn man befürchten muss, dass ein Sounddarsteller nicht gleich zu spielen beginnt, weil sein Laden zu lange dauert, so kann man ihn mit

sound(1).queue(member("MeinLied"))
sound(1).play()

zuerst ins RAM laden und dann abspielen. Man kann durch mehrfache Anwendung der .queue-Eigenschaft auch mehrere Darsteller hintereinander in einen Soundkanal laden. Im Folgenden kann j eine Variable der Art j=member("EinTonDarsteller") sein, wobei hintereinander verschiedene Darsteller in j abgelegt und in der Queue aneinander gereiht werden:

sound(3).queue([member: j, #rateshift: -3, #endTime: 1250])

Will man im queue-Befehl zusätzliche Argumente angeben, wie #startTime, #endTime, #loopcount usw., muss eine Eigenschaftsliste folgender Gestalt angelegt werden:

sound(1).queue([member: member("MeinLied"), #startTime:2000, #loopcount:2])

#startTime gibt dabei an, ab welchem Zeitpunkt im Soundfile mit der Wiedergabe begonnen werden soll. Im obigen Beispiel wird also die Wiedergabe erst ab der 3. Sekunde im Soundfile gestartet. Was vorher drin ist, kann man nicht hören. #endTime gibt an zu welchem Zeitpunkt im Sound mit der Wiedergabe aufgehört werden soll.

Eine interessante Möglichkeit bietet die in Director 11 nicht mehr dokumentierte, aber unterstützte Eigenschaft #rateshift. Mit positiven Ganzzahlwerten erhöht man um je einen Halbton, mit negativen erniedrigt man. Der folgende Befehl transponiert um eine kleine Terz hinunter:

sound(1).queue([member: member("MeinLied"), #rateshift:-3])

bug Theoretisch ist es möglich, über setPlaylist() Abspiellisten zu erstellen, wobei die in der Liste aufgeführten members in Darstellerverzeichnis vorhanden sein muessen. Die Ergebnisse sind aber nicht reproduzierbar und es ist unklar ob und wie dieser Befehl tatsächlich funktioniert.

Ein sehr guter Beispielsfilm für die Beeinflussung aller möglichen Soundeigenschaften in Version 10 - allerdings für Fortgeschrittene - findet sich im Directorordner Learning als Datei sound control.dir.

3.5 Externe Sounddatei abspielen

Speziell wenn es sich um eine große Datei handelt kann es von Vorteil sein sie von der Platte zu streamen, wobei nicht alle Soundformate funktionieren. AIFF geht, mp3 nicht. Das Streamen geschieht in der jetzigen Version des Programms durch

sound(4).playfile(_movie.path & "Toene:xy.wav")

Dabei bedeutet die Zahl 4 hier, dass der abzuspielende Sound in Kanal 4 liegt, _movie.path gibt den Ort des momentan laufenden Films an, und im konkreten Beispielwird angenommen, dass sich auf diesem Level ein Ordner namens "Toene" befindet, in dem wiederum eine Tondatei "xy.wav" liegt. Näheres über Pfadangaben findet man hier.

3.6 Surroundsound

Seit Director 11.5 besteht die Möglichkeit Surroundsoundformat 5.1 zu verwenden. Dazu gibt es den sogenannten Mixer. Eine Einführung zu seiner Verwendung findet man http://www.adobedirectoronline.com/tutorials/tutorial_115audio_creatingmixer.php. Die Ausgabe von 5.1-Sound aus einem MacBookPro geschieht übrigens ganz einfach, wenn man an den Kopfhöreranschluss statt eines Klinkensteckers einen passenden TOS-Link Stecker gibt. Für den Standard TOS-Link Stecker gibt es dazu Übergänge, die in die Mini-Klinkenbuchse passen.

3.7 Mixer

Der Mixer wurde bereits vorher an anderen Stellen erwähnt. Der Mixer eignet sich besonders dann, wenn man Quellen mit unterschiedlichen Abspielraten, Bittiefen oder dergl. gleichzeitig abspielen will. Der Mixer bereitet alles Nötige vor und entlastet somit die CPU. Der Mixer ist ein Container und wird als Member erzeugt über Fenster>Audiomixer und dann im Mixerbrowserteil des Fensters + Neuer Mixer. Über + sound hinzufügen kann man jetzt Sounds aus dem Bestand der Castmember hinzufügen,

4. Interaktion

Um Interaktion herstellen zu können, bedarf es der Programmierung in Lingo,(Download einfacheInteraktivitaet.sit) oder JavaScript. Da beide Sprachen austauschbar verwendet werden können, beschränke ich mich hier auf die Angabe der Befehle in Lingo.

Ein kommentiertes Beispiel für Interaktion inklusive Menüsteuerung zum Download: (Download komplexeInteraktivitaet.sit)

Ein wichtiger Aspekt bei der Interaktion besteht darin, dass der Benutzer immer weiß ob ein Objekt klickbar ist oder nicht. Dazu sollte beim Rollover eine Änderung der Cursorform eintreten. Dafür gibt es vorgefertigte Behaviors (Rollover Cursor Change) in der Library unter ANIMATION>INTERAKTIVE

Ein spezieller Trick besteht darin, auf einfachste Weise Hotspots zu erzeugen. Das geschieht so, dass man einen schwarzen Paint Darsteller, der sich im 1-bit-Farbmodus (also schwarz/weiß) befinden muss, auf die Bühne bringt und ihm dann (sinnigerweise) die Ink nicht transparent zuordnet. Auf diese Weise wird der schwarze Darsteller durchsichtig(!), kann aber geklickt werden.

4.1 Messages und Handler

Events lösen Messages (Nachrichten) aus. Events sind Ereignissmeldungen, die während des Filmablaufs von der Zeitleiste des Scores, von einem Inputdevice oder vom Netzwerk ausgesandt werden, z.B.

startMovie
exitFrame
MouseEnter
beginsprite

Die dabei verwendete Skriptsprache, Lingo, ist eine Skriptsprache, die an eine Entwicklungsumgebung, ein Framework (in diesem Fall Director), gebunden ist. Das Framework schickt die Nachrichten, die vom Skript verarbeitet werden. Ein Framework ersetzt das in anderen Sprachen (z.B. Fortran) gebräuchliche "Hauptprogramm", das in diesen Sprachen dann die Unterprogramme oder Subroutinen aufruft und Parameter übergibt, oder Werte zurück übernimmt.

Das Framework besitzt systemeigene Variable wie z.B. the stilldown oder the Clickon, die nach neuerer Schreibweise (Director 11) als Eigenschaften der Maus in der Form _mouse.stilldown oder _mouse.clickon geschrieben werden. Variable des Systems beginnen dabei immer mit einem Unterstrich. Darüberhinaus kann man selbst Variable einführen, die aber deklariert werden müssen.

Ein Handler (auch (Ereignis)Prozedur genannt) ist ein Programm-Modul, das auf eine Message reagiert. Der Handler fängt ein Event ab und reagiert in der programmierten Art und Weise. Im Folgenden z.B. ein Skript, das verhindert, dass der Film auf das nächste Frame weitergeht:

on exitframe
  go to the frame
end exitframe

Eine einzelne Zeile in einem Handler nennt man ein Statement. (Im gegebenen Beispiel also die Zeile go to the frame).

Ein Handler weiß nicht von wo er aufgerufen wird. Obwohl also z.B. prepareMovie vom anlaufenden Film gesandt werden, kann man den Befehl ebenso z. B. aus einem Frameskript schicken (ein startMovie- handler wird allerdings als not defined bezeichnet, wenn man ihn in ein Verhaltensskript schreibt) .

Behavior (Verhalten) ist die Summe aller Handler, die in einem Skript (z.B. ein MouseUp-Skript) programmiert und einem bestimmten Sprite oder einem Frame zugeordnet sind. Es können aber einem Sprite mehrere Behaviors zugeordnet werden. Dabei können auch zwei oder mehrere Behaviors den gleichen Eventtyp haben. Ein Behavior ist als eigener Darsteller in der Darstellerliste eingetragen, befindet sich aber nicht explizit auf der Bühne, sondern als Frameskript im Skriptkanal des Drehbuchs oder man zieht das Verhaltensskript auf einen Sprite im Scorefenster oder direkt auf den auf der Bühne (was weniger Verwechslungsgefahr in sich birgt, als wenn man das Skript auf einen Sprite im Score zieht). Z.B. können die zwei folgenden Skripts auf einen Sprite gezogen werden:

Skript 1:

property ball

on beginsprite (me)
ball=me.spritenum
end beginsprite

und Skript 2:

property ball

on Mouseup (me)
_player.alert(String(ball))
end Mouseup

Das erste Skript setzt den Wert der Eigenschaft spritenum des Sprites in eine Variable, das zweite Skript liest diese Variable beim Anklicken des Sprites in einem Alert-Fenster aus.

Ein anderer Typ von Skript ist das sogenannte Filmskript. Es lässt sich nicht auf einen Sprite ziehen oder in den Skriptkanals des Scores bringen, sondern enthält Prozeduren, die unabhängig von der Position des framepointers oder der Maus reagieren, wenn eine entsprechenden Message geschickt wird. So wir z.B. ein mouseup-Handler in einem Skripttyp Movie immer reagieren, ganz gleich in welchem frame wir uns gerade befinden oder welche sprites in diesem frame gerade vorhanden oder nicht vorhanden sind (- es sei denn es gibt auch ein weiters mouseup-Skript als Score- oder Spriteskript, das den Befehl abfängt und nicht weitergibt.). Der Skripttyp Movie ist zu Programmbeginn als default eingestellt, Man kann ihn über den PI unter SCRIPT>TYPE verändern.

Statt das Behavior-Skript im Skriptfenster zu schreiben, kann man es auch im Behavior Inspector zusammensetzen (jeweils die + Kästchen anklicken und zuerst den Skriptnamen, dann das Event und dann die gewünschten actions aus dem Popup-Menü wählen, wodurch ein fertiges Skript im Skriptfenster angelegt wird) oder man kann ein fertiges Behavior aus der Library auswählen.

Vorgefertigte Skripten findet man in der Library unter WINDOW>LIBRARY PALETTE oder im PI  CODE>LIBRARY

Obwohl es eigentlich zu Kapitel 6 gehört hier schon ein kleiner Hinweis auf das wichtige Wort me. Das Gegenstück zu me ist in C++ der Ausdruck This und beide bezeichnen die Instanz auf die sich der Handler gerade bezogen hat. Am besten betrachten wir das an einem Beispiel: Im folgenden Bühnenfenster gibt es zwei Sprites, die sich im Drehbuch in den Kanälen 1 und 2 befinden und beide das selbe Skript mit der Darstellernummer 4 haben:

Dieses Skript lautet wie folgt:

on mouseup me
put me.spritenum
end

Klickt man nun auf das grüne Oval , so erhält man als Antwort die Zahl 1, klickt man auf das rote Dreieck so erhält man 2

4.2 Events und deren Hierarchie

Events sind Meldungen, die das System ausschickt, sei es aus Eigeninitiative (wie z.B. StartMovie), sei es als Reaktion auf einen Benutzervorgang (wie z.B. MouseDown).

4.2.1 Eventtypen:

Movie-Events sind unabhängig vom Score. z.B. startMovie oder preparemovie. Mit einem zugehörigen Handler on startmovie könnte man z.B. globale Variable initialisieren. Frame-Events werden vom im Score mit einem Frame wechselwirkenden Abspielkopf verursacht. z.B. enterFrame. Betrifft ein Event ein bestimmtes Sprite in einem Frame, so nennt man es ein Sprite-Event, z.B. MouseEnter. MIAW-Events (Movie in a Window-Events) sind solche, die sich auf ein von Director aufgemachtes Fenster beziehen, wie etwa ActivateWindow. Darüberhinaus gibt es noch ein paar Sonstige Events, die in bestimmten Fällen auftreten, die keiner der vorigen Gruppe zuordenbar sind.

Nachrichten werden - auch wenn sie von ganz oben, also vom Movie Event, kommen zunächst nach ganz unten, also auf die Sprite Ebene hinuntergereicht und von dort aus wird aufsteigend nachgesehen, ob das Event von einem Handler gebraucht wird.

Die Nachrichtenkette geht an (von der höchstenPriorität der Abarbeitung angefangen): Primary Event Handler => Sprite Skripts => Darsteller Skripts => Frame Skripts => Film Skripts. Im Gegensatz dazu ist die Priorität der Nachrichtensendung in umgekehrter Reihenfolge, was aber das Programmieren nicht wesentlich betrifft. Wichtig ist, dass ein Event, das von einem Handler, sagen wir im Sprite Skript abgefangen wird, nicht mehr von einem Film Skript Handler des gleichen Eventtyps wahrgenommen wird.

Primary Event Handler. Es gibt vier, nämlich the keydownscript, the keyupscript,the mousedownscript   und the mouseupscript. Diese sind zunächst leere Eigenschaftsvariablen, denen ein Skript zugewiesen werden kann. Das geschieht etwa folgendermaßen:
Man definiert z.B.

on preparemovie
   the keydownScript="BeiTastendruck"
end

on Tastendruck
   if _key.key = "s" then machwas
end

In Kombination kann man dazu noch Zusatztasten abfragen

if _key.controldown then...

Sprite scripts: sind Skripts, die nur mit einem bestimmten Sprite assoziiert sind. Das geschieht, indem man einen Behavior-Darsteller (achtung: der Skripttyp darf nicht "Filmskript" oder "Parentskript" sein) über ein auf der Bühne befindliches Sprite zieht. Es können mehr als ein Behavior am gleichen Sprite hängen. Wenn mehrere Skripts mit dem gleichen Handler am selben Sprite hängen, wird die message an alle weitergegeben. (Siehe Beispielfilm GleicheHaendler.dir)

Cast member scripts: sind Behaviors, die im Erzeugungsfenster des betreffenden Members geschrieben werden. Also beim Paint-Fenster indem man rechts oben das Skriptsymbol anklickt und sein Skript einträgt.

Frame scripts: sind Behaviors, die im Skriptkanal des Scores stehen und mit dem Ablauf des Abspielkopfes zusammenhängen.

Film scripts, sind Skripts, die unabhängig vom Abspielkopf, einem member oder einem sprite existieren.

Event-Typ Movie-Ebene Frame-Ebene Sprite-Ebene
Movie Event      
prepareMovie
x
   
startMovie
x
   
stopMovie
x
   
idle
x
x
 
keyDown, keyUp
x
x
x
mouseDown, mouseUp
x
x
x
Frame Event      
prepareFrame
x
x
x
enterFrame
x
x
x
exitFrame
x
x
x
Sprite Event      

New

   
x
BeginSprite    
x
EndSprite    
x
MouseEnter    
x
MouseWithin    
x
MouseLeave    
x
MouseUpOutside    
x
(RightMouseDown, -up)    
(x)
MIAW Event      
OpenWindow
x
   
CloseWindow
x
   
ActivateWindow
x
   
DeactivateWindow
x
   
MoveWindow
x
   
ResizeWindow
x
   
ZoomWindow
x
   
Sonstige Events      
StepFrame
x
   
TimeOut
x
x
 
StreamStatus
x
   
CuePassed
x
   
AlertHook
x
   

Prinzipiell kann man Nachrichten mit pass weiterreichen, sodass eine im Sprite abgearbeitete msg z.B. an den Darsteller weitergereicht wird (Download passMouseUp.sit). Mit stopEvent wird die Weiterreichung unterbunden, was nur bei primary event handlers nötig ist z.B.:

on startMovie
set the keydownscript to "myKey"
end

on myKey
put the keycode
if the keycode >17 and the keycode <30 then
_player.alert ("Bitte keine Ziffer eingeben")
stopEvent
end if

end

oder, wenn mehrere Skripts eines Sprites dieselbe msg handeln, z.B.

Skriptmember 6

on beginsprite
beep
stopEvent
--in diesem Fall wird der Cursor unverändert bleiben, weil die Nachricht nicht an das nächste Skript weitergegeben wird.
end

und in einem weiteren Skript, member 7

on beginsprite
cursor -1
end

Wenn 2 oder mehr Skripts mit dem gleichen Handler an einem Sprite hängen, wird dasjenige zuerst abgearbeitet, dessen Darstellernummer am niedrigsten ist (Download 2gleicheHandleramselbenSprite.sit).

Wenn sich kein entsprechendes Skript im Darsteller befindet, so wird das keydown-Skript im folgenden Filmskript abgearbeitet, ohne dass in einem Felddarsteller eine Zahl eingetragen wird. Ohne StopEvent wird die Zahl zwar moniert, aber danach eingetragen (Download BeispielStopEvent.sit).

on startMovie
set the keydownscript to "myKey"
end

on myKey
put the keyCode
if the keyCode > 17 and the keyCode < 30 then
_player.alert("Ziffer")
stopEvent
end if
end

Film scripts,Mitunter ist es sinnvoll, wenn man vom Benutzer durchgeführte Aktionen, insbesondere Mouseclicks ignorieren kann. Wenn er zum Beispiel während des Abspielens einerwichtigen Anweisung wegklickt, so kann man solche Eingaben mit _player.flushInputEvents() ungeschehen machen.

4.2.2 Übersicht über einige Eventtypen

Groß- und Kleinschreibung bei Handlern ist unwichtig

preparemovie tritt ein bevor das erste frame gezeichnet wird. Zu diesem Zeitpunkt gibt es noch keine Sprites! Gut für objekt-unabhängige Initialisierungen und Deklaration von Globals.
prepareframe der erste Event dieser Art tritt nach preparemovie und vor startmovie ein. tritt jedesmal auf, wenn man in den frame geht, also auch in einer loop. Gut für Initialisierungen, die nur den Frame betreffen.
startmovie
tritt ein nachdem der erste Frame vorbereitet wurde, aber bevor der Abspielkopf in ihn eintritt. Gut für Initialsierungen und Erzeugung allgemeiner Objekte (z.B. aus parent Scripts, deren Referenz in einer Global gespeichert wird).
stopmovie Gut für Speicherfreigabeaktionen und ähnliche Aufräumarbeiten.
idle
wird immer dann gesendet, wenn sonst nichts zu tun ist. (Siehe the idleHandlerPeriod in der lingo-help)
keydown; keyup Tastaturevent, das als Movie- oder Frame-event nur dann auftritt, wenn die Bühne das aktive Fenster ist. Als Sprite-event ist es nur im Zusammenhang mit einem Text- oder Felddarsteller funktionell und nur sofern dieser editierbar ist.
Mousedown; Mouseup Üblicherweise sollte man Ereignisse auf Sprite-Ebene als MouseUp-Events schreiben, falls der User nach MouseDown es sich noch einmal überlegt. Er kann dann mit gedrückter Maustaste aus dem Sprite herausfahren und es passiert beim MouseUp nichts.
enterframe kommt gleich nach prepareframe, wenn der Abspielkopf den frame betritt. Gut für Spritepositionierungen.
exitframe tritt auf, wenn ein frame verlassen wird. Wichtig für loops.
beginsprite tritt auf, wenn ein Sprite zur Darstellung vorbereitet wird, bevor es noch auf der Bühne ist. Erstreckt sich der Sprite über mehrere Frames, so wird es nur bei einem Keyframe generiert.
         In beginsprite ist es nicht möglich ein go, play oder updatestage auszuführen (alsoz.B. kein _movie.go(_movie.frame+3)
endsprite gut für Aufräumarbeiten - Gegenstück zu beginsprite
beginsprite
und endsprite eignen sich gut zum unsichtbar/sichtbar-machen eines Sprites, oder zur Voreinstellung anderer Eigenschaften eines Sprites, die nicht erneuert werden müssen während es in einem Frame loopt.
mouseEnter tritt auf, wenn der Mauszeiger in den Sprite eintritt. Gut z.B. für roll-over-Effekte. Der Zeitpunkt des Eintretens von mouseenter hängt auch von der gewählten ink ab.
mousewithin wird bei jedem Framedurchlauf ein Mal erzeugt, wenn sich die Maus über dem Sprite befindet (auch hier spielt die ink-Wahl eine gewisse Rolle)
mouseleave Gegenteil zu mouseenter
mouseupoutside tritt auf wenn mousedown über dem sprite war, aber mouseup außerhalb.
rightmousedown; rightmouseup wie mousedown und mouseup, aber für die rechte Maustaste.
new ist ein sprite-event, das generiert wird, resp. die on new-Funktion wird aufgerufen, wenn eine Instanz eines Parentscripts erzeugt wird.
openwindow tritt auf, wenn ein weiteres Director-movie in einem bestehenden Fenster geöffnet wird.
closewindow Umkehrung zu openwindow
activatewindow tritt ein, wenn das MIAW-Fenster aktiviert wird.
deactivatewindow Umkehrung zu activatewindow
movewindow wenn das MIAW bewegt wird.
resizewindow tritt auf, wenn die MIAW-Fenstergröße manuell verändert wird
zoomwindow wenn die MIAW-Fenstergröße durch einen der Buttons am oberen Fensterbalken verändert wird.
stepframe wird nach dem exitframe event für alle Objekte der actorlist generiert. Gut um Nachrichten an Objekte zu schicken, die kein Sprite auf der Bühne haben.
timeout tritt auf, wenn die in der globalen Systemeigenschaft the timeOutLength festgesetzte Zeit abgelaufen und kein Event aufgetreten ist.
streamstatus tritt auf bei Netzwerkoperationen, gut zum Überprüfen des Fortschritts.
cuepassed wird gesendet, wenn ein cue-point in einem Sound-Darsteller passiert wird.
alerthook wird gesendet, wenn ein Director-Fehler auftritt. In der Global Property the alertHook kann ein Skript angegeben werden, das den entsprechenden Event-Handler besitzt, um auf den Fehler zu reagieren.

4.3 Anwendungsbeispiele:

4.3.1 Interaktive Standbilder, Diashow

Um einen Film stehen zu lassen bedient man sich der on exitframe - _movie.go (_movie.frame)  loop. (Früher: on exitframe - go to the frame). Allerdings ist dabei zu beachten, dass Ereignisse, die nur einmal im Frame gesetzt werden müssen (z.B. die Zuweisung eines nicht veränderlichen Wertes zu einer Variablen) in der Schleife wiederholt werden, wenn sie in einem enterframe oder exitframe-handler stehen. Man kann nun entweder ein zusätzliche Frame ohne Loop vor das geloopte setzen, oder ein Dummysprite zeichnen lassen, das sich durchaus außerhalb der Bühne befinden kann und dann das einmalige Ereignis in ein on beginsprite des Dummysprites setzen. Dabei kann dasselbe Sprite mehrmals verwendet werden, wenn es nicht in den frames n und n+1 steht (denn dann würde es nicht neu gezeichnet!). (Download onbeginspritebeispiel.sit)

Entsprechend ist es ein grober Fehler eine Transition entweder im Transitionkanal oder als Skript in ein loopendes Frame zu setzen, da bei jedem enterframe der Schleife der Übergang neu gezeichnet werden muss. Das kann dann die Geschwindigkeit auf null herabsetzen und außerdem wegen der CPU-Belastung nahezu verhindern, dass man noch eine Aktion setzen kann (z. B. einen Mausklick).

Um zu anderen Frames - eventuell auch in anderen Filmen - zu gelangen kann man in einem loopenden Frame einen Button platzieren, der ein Skript der Art

on mouseup
 _movie.go("Credits","Abspannfilm")
end

Dabei ist Credits der Markername des anzusteuernden Frames und Abspannfilm der Name des Filmes, in dem sich das Frame Credits befindet. Lässt man die Filmbezeichnung weg, so bezieht sich die Angabe auf den derzeit offenen Film. Statt der Markerangabe kann auch die Framenummer stehen:

_movie.go (324)

4.3.2 DV-Filmsteuerung

Steuerung der Abspielgeschwindigkeit und -richtung:

sprite(Kanalnummer).movieRate

1: normal vorwärts
-1: rückwärts
  0: stop
ein Wert kleiner 1, größer 0 bedeutet ein langsameres Abspielen als normal, ein Wert >1 ein schnelleres, wobei allerdings DV-frames verloren gehen können. Der Ton wird nach Möglichkeit behalten, die Tonhöhe ändert sich aber entsprechend. (Unabhängig von DTS)

Die Performance wird - wie bei anderen Darstellern auch - schlechter, wenn der Sprite gestreckt wurde.

4.3.3 Buttons

Ein einzelner Button kann entweder Ein durchaus üblicher Vorgang ist auch der, dass ein Button bei einem Rollover sein Aussehen verändert. Die einfachste Methode besteht darin, zwei Members zu erzeugen und über den Sprite, der dann dargestellt wird, wenn die Maus sich nicht über ihm befindet, das Verhalten Fenster>Bibliothekspaltette>Verhalten>Animation>Interaktiv>Rollover Darstelleränderung drüber zu ziehen, wobei im dabei auftauchenden Dialogfenster das Member des alternativen Bildes angegeben wird.

Wer sich nicht auf fremde Skripts verlassen will, oder komplexere Operationen bei einem Rollover ausführen will, steuert die Zuordnung eines Members zu einem Sprite mit sprite(n).member = member(m) [n=Kanalzahl, m= Nummer des Members] in Abhängigkeit der Events MouseEnter und MouseLeave. Im Beispiel RolloverSpriteXChange.zip sind beide Versionen realisiert.

Mehrere zusammengehörige Buttons (Auswahlfelder) erstellt man, indem man zunächst unter Einfügen>Steuerung>Auswahlfeld mehrere Felder erstellt. Damit diese Felder das typische Verhalten zeigen, müssen diejenigen Buttons, die zusammengehören einen gemeinsamen Gruppennamen bekommen. Dies geschieht dadurch, dass man unter Fenster>Bibliothekspalette>Steuerungen>Auswahlfeldgruppe ein Verhalten auf jeden dieser Buttons zieht, wobei immer der gleiche Name in der Gruppenbezeichnung aufscheinen muss. Das Ausgewähltsein eines Buttons ist seine .hilite-Eigenschaft. Die .hilite-Eigenschaft ist eine des Members, nicht des Sprites. Also

member("Ton").hilite

4.3.4 Cursorformen

Will man, dass der Cursor, z. B. nach einem exitframe nicht mehr sichtbar sein soll, so verwendet man den entsprechenden Zahlenparameter  (nämlich:cursor 200)

on beginsprite
cursor 200
end

(Eine Übersicht über sämtliche verfügbaren Parameter findet man hier in der Lingo-Hilfe). Um die Cursorform zu ändern siehe das Beispiel (Download TestCursorformabfrage.sit)

Man kann auch einen eigenen Cursor zeichnen. Im einfachsten Fall nimmt man dazu ein Schwarzweißbild (1-bit Farbe !!) mit 16x16px und dazu einen Maskendarsteller, der die Fläche hinterlegt, auf der das Bild zu sehen sein soll. (Wenn man den weglässt, so ist der Cursor nicht in der Farbe definiert. Das folgende Beispiel zeigt je nach rollover drei verschiedene Cursorformen, wobei die Cursoren in der Shockwavedatei nicht sehr prompt reagieren. Sinvoller ist es, die Datei runterzuladen:


(download CustomCursor.zip)

Eine andere Möglichkeit seinen eigenen 1-bit Cursor zu verwenden besteht darin, dass man aus der Bibliothekspalette Verhalten>Animation>Interaktiv>Rollover-Cursoränderung auswählt. Hat man nämlich eigene Darsteller, die sich als Cursor eignen, so erhält man erweiterte Möglichkeiten beim Optionenfenster:

Verwendet man einen Cursor aus der Bibliothekspalette, so gibt es ein Problem, wenn man den Sprite, an dem dieser Cursor hängt, mit einem anderen Sprite abdeckt. denn der Cursor "schlägt durch". Das bedeutet: auch wenn der überdeckende Sprite einen größeren z-Wert hat (also in einem Kanal mit einer höheren Nummer liegt) als der Sprite an dem des Cursorverhalten aus der Bibliothek hängt, so verändert sich der Cursor beim Überrollen des tieferliegenden Sprites trotzdem. Will man das verhindern, so muss man 1) die Cursorform selbst wählen mit Hilfe der Methode

_player.cursor(nn) wobei nn eine Ganzzahl ist, die die Cursorform determiniert

2) muss man on mouseenter des überdeckenden Sprites die gewünschte Cursorform für diese Situation aufrufen. (Download CursorZ-Werte.zip)

4.3.4 Internetfunktionen

Oft sind in der Programmierung Pfadangaben nötig, um anzugeben wo sich ein externes einzulesendes Dokument befindet. Dabei kann es sich etwa um ein weiteres Directorfile, oder eine verknüpfte Mediendatei für ein Ton, Film oder ähnliches handeln, aber auch um Internetseiten.

Um aus einem Directorfilm eine Internetseite aufzurufen, kann zunächst mittels des Lingostatements browserName pathName der Pfad zu einem Browser (Netscape Navigator, Internet Explorer, Opera…) angegeben werden, danach kann man mit gotoNetPage eine Seite aufrufen. Mit browserName(#enabled, trueOrFalse) gibt man an, ob der spezifizierte Browser automatisch gestartet werden soll, wenn der goToNetPage - Befehl aufgerufen wird. ist der Pfadname zum Browser unbekannt, so kann man ihn mit Hilfe des displayOpen() Befehls aus FileIO angeben. (Download HyperlinkGrafik.sit)
z.B.:

on mouseup
  browserName"Festplatte:Programme:Internet:
Opera 5.0"
  gotoNetPage "http://www.moz.ac.at/user/rwolff"
end

Bei der Angabe des Browsernamens und -pfades muss man allerdings aufpassen, dass man die korrekte Schreibweise und die richtige Zielangabe verwendet, ansonsten reagiert gotoNetPage einfach überhaupt nicht. Da ist es oft zweckmäßiger, das BrowserName-statement überhaupt wegzulassen, da gotoNetPage dann versucht von selbst einen Browser ausfindig zu machen.

Analog kann man auch Textstellen mit einer Netzadresse verbinden, indem man eine Zeichenfolge auswählt und dann im PI des Textmembers eine URL eingibt.
Das ist nur möglich, wenn man den PI auf Listendarstellung setzt, außerdem war es nötig, um nur einen Teil des Textes als Link zu gestalten, zuerst nur diesen zu schreiben, dann das Link im PI einzutragen und anschließend vor und hinter dem Link den nicht-aktiven Text zu schreiben, denn auch eine Eingabe der Range hat nach verlassen des HyperlinkRange-Feldes im PI dieses wieder auf den Bereich des ersten bis letzten Zeichens gesetzt!)
Die dabei erzeugten Argumente übergibt man in einem Skript an die Funktion on hyperlinkClicked me, data range (Download HyperlinkText.sit)

Man kann mittels getNetText auch Text aus einer Webseite übernehmen. Näheres dazu findet man in der Lingo-Anleitung oder hier.

4.3.5 Menüsteuerung

Die Steuerung von Abläufen über Menüpunkte geschieht folgendermaßen: Zunächst erzeugt man einen Felddarsteller (nicht Textdarsteller), der die Menüpunkte in folgender Form enthält:

menu: Stundenplan
Unterrichtszeit/U | _movie.go("plan")
(-------
Beenden/Q | _movie.go("beenden")
menu: Anleitung
Wie geht das? | _movie.go("hilfe")
menu: Test
Zeiteingabe/L | Uhrzeitgeben

Die erste Zeile enthält den Namen des 1. Menüs.
Die 2. Zeile enthält den ersten Submenüpunkt, daran können sich entsprechend weitere anschließen.
Die 3. Zeile enthält einen Separationsstrich.
Die 4. Zeile enthält den nächsten Submenüpunkt.
Die 5. Zeile enthält den Namen des 2. Menüs
usw.

Der Schrägstrich gefolgt von einem Buchstaben gibt das gewünschte Tastaturkürzel zu dem Menüpunkt an. Damit das wirksam ist, muss man in den Filmeigenschaften Tastenkombinationen aktivieren checken. Nach dem senkrechten Trennstrich folgt entweder eine Befehlszeile wie in den ersten zwei Menüs, oder es steht wie im dritten Menü ein in einem Filmmenü benutzerdefinierter Handler.

Die Installation des Menüs geschieht mit Hilfe des Befehls

installmenu "normalmenu"

wobei "normalmenu" der vom Benutzer gewählte Name des Textdarstellers ist, der die Menüdefinition enthält. Auf diese Art und Weise kann man auch je nach der gegebenen Situation unterschiedliche Menüs installieren, z.B. in der Phase der Programmprogrammentwicklung und des Testens.

4.3.6 Timer

Um Zeitmessungen und damit verbundene Operationen auszuführen gibt es eine Stoppuhr. Mit starttimer wird sie angeworfen, mit the timer fragt man die abgelaufene Zeit in ticks (1/60Sek) ab. (Eine Alternative dazu ist the ticks zu messen, die die Zeit in ticks seit dem Einschalten des Rechners anzeigt.

Will man Zeit verstreichen lassen (also eine Art wait-Funktion), so kann man entweder den oben erwähnten timer verwenden oder mit Hilfe der folgenden Prozedur eine bestimmte Zeitspanne vergehen lassen.

on warte(wieVieleMSEK)
  endZeit = _system.milliseconds + wieVieleMSEK
  repeat while endZeit > _system.milliSeconds
   nothing
  end repeat
end

_system.milliSeconds ist dabei die Zeit seit dem Einschalten des Computers.

Bei dieser Art des Zeit-vergehen-lassens kann aber kaum eingegriffen werden. Die CPU ist derart stark ausgelastet, dass z.B. ein MouseUp - wenn überhaupt - dann nur mit großer Verzögerung durchkommt. Für solche Fälle ist es sinnvoller in einer frameloop jeweils die Zeit abzufragen und fallweise einen Zugriff über ein MouseSkript zu erlauben. z.B.:

zuerst einmal legen wir die Endzeit fest (das kann z.B. in einem beginsprite Handler geschehen, oder in einem Frameskript eines Frames, das nicht dasjenige sein darf in dem die endzeit-Abfrage stattfindet)

endzeit= random (240) -- es vergehen also bis zu 4 Sekunden
starttimer

anschließend wird in der Frameloop die vergehende Zeit abgefragt:

global endzeit
on exitframe
if the timer>endzeit then MachWasDuWillst
go to the frame
end

Bei dieser Programmierart kann man durchaus während des Zeitzählens eingreifen.

5. Grundlagen der Programmierung

Obwohl bereits bis hierher kleine, leichte Programmierbeispiele vorgekommen sind, soll im Folgenden das Programmieren mit Lingo systematisch aufgebaut und erklärt werden.

Wichtige, immer wieder verwendete Events sind:

on enterframe - on exitframe: Dieses Event findet statt, wenn der Framepointer in das Frame eintritt oder es verlässt. In Loops passiert das andauernd und man kann sich verändernde Variable dabei stets up-to-date halten (z.B. wo sich die Maus gerade befindet - _mouse.mouseloc)

on idle: Steht in einem Frame- oder movieskript und dient dazu Arbeiten zu machen, wenn gerade Zeit dafür ist. Auch dieses Ereignis loopt und eignet sich gelegentlich auch als Ersatz für ein exitframe-Skript, wenn das schon verwendet wird.

on beginsprite - on endsprite: Wird -auch in einer Loop nur ein Mal aufgerufen, sofern der Sprite nicht neu aufgebaut wird. Sehr geeignet für Anpassungen beim Einstieg in ein loopendes Frame.

on mouseup - on mousewithin - on mousenter - on mousedown: Typische Skripts, mit denen Userinteraktionen erfasst werden.

 

Bei der Nomenkaltur der Darsteller, Sprites und Casts ist ein wichtiger Begriff dabei ist die dot-Syntax. Sie bedeutet, dass Eigenschaften der erwähnten Objekte als zwei- oder mehrteiliger, durch Punkt getrennter Ausdruck angegeben werden:

<object>.<property>; z.B. sprite(1).locH

gibt es Unterobjekte, so ist die Syntax

<object>.<sub-object>.<ev. weitere subobjects>.<property>
z.B. member(1).text.line[2].word[7].char[1]

Spritenummern, sowie Namen oder Nummern von Members und Casts werden in runden Klammern referenziert, wobei Namen als String unter ANführungszeichen stehen.

member("Bild")

Es gibt aber auch Ausnahmen: So ist das Hinzufügen und Löschen von Zeichen bei einem String nicht mit dot-Syntax formulierbar.

Bei der Namengebung für Objekte, Instanzen, Variable etc. bitte keine Nicht-Standard ASCII Zeichen wie ö ä,ü,ß usw. verwenden. Es kann gut gehen - muss aber nicht!

Eine nützliche Funktion ist der runMode der Datei. Prinzipiell kann eine Datei den runMode Author, Projector oder BrowserPlugin haben. Man kann ihn abfragen mit

if _system.environmentPropList.runMode contains "Author" then...

und so das Verhalten während der Entwicklung anders gestalten als im fertigen Projekt.

5.1 Variablentypen

5.1.2 Einfache Typen von Variablen

Der Typ einer Variablen lässt sich mit Hilfe der Funktion ilk() feststellen. Eine Übersicht über alle Variablentypen kann man hier runterladen: download ilkTypen.pdf

Typ Integer = Ganzzahl. Z.B. i = 628
Integer-Werte gehören zu den schnellsten Datentypen in Lingo. Es gibt eine größte und eine kleinste Integerzahl. Die größte ist:

put the maxInteger
-- 2147483647

Das ist (2 hoch 31)-1. Addiert man 1 zu maxinteger, erhält man die größtmögliche negative Zahl, nämlich -2147483647.
Alle Zahlen, die höher sind, werden als 0 dargestellt!

Typ Boolean, im Prinzip ein Spezialfall von Integer, bei dem es die Werte TRUE und FALSE gibt, 1 oder 0. Dabei ist alles TRUE was nicht 0 oder VOID ist. FALSE ist alles was 0 oder VOID ist. Als Schalter kann man schreiben

Schalterzustand = NOT(Schalterzustand)

Typ Floating Point = Gleitkommazahl. Z.B. x = 123.87 (Punkt, nicht Komma!)

Ist eine Floatingzahl größer als float(maxInteger), so wird sie als ±INF dargestellt.
Die Anzahl der Dezimalstellen wird the Floatprecision angegeben

Gleitzahl = 1.23456789
the Floatprecision = 3
put Gleitzahl

-- 1.235

Die maximale Nachkommastellenanzahl ist 15

Manche Operationen wandeln zwar den Datentyp automatisch um z.B.
i="1000"
i=i/2

resultiert in i=500.00 (Die Resultierende Zahl ist vom Typ Floating Point!), doch ist eine solche Vorgangsweise unsauber und daher auch gefährlich. So liefert nämlich

i=5
i=i/3

nicht Floating 1.6667 , sondern integer (truncated) 1! Korrekt hätte man schreiben müssen

i=5.
i=i/3.

Das Korrekte Umwandeln geht folgendermaßen:

Floating Point zu Integer:

put (1.5).integer
-- 2

Integer zu Floating Point

put (1).float
-- 1.0000

Typ String = Zeichenkette.

Dabei handelt es sich im Prinzip um eine Liste von ASCII-Zeichen, weshalb sich auch Listenfunktionen auf Strings anwenden lassen. Strings können mit & aneinander gehängt werden, wobei ein Zeilenschalter als RETURN eingesetzt wird. Die Quelle für Strings können Text- und Felddarsteller sein.

Z.B. a = "Erwin Schrödinger ist ein "&RETURN&"österreichischer Nobelpreisträger,"&RETURN&"Der Hamilton-Operator steht in einer Eigenwertgleichung"

Aus einem String können chunks ausgelesen werden:

put a.line[2]
-- "österreichischer Nobelpreisträger"

put a.word[2]
-- "Schrödinger"

put a.char[3]
-- "w"

put a.char[28]
-- "ö"

put a.char[27]
-- "
"

put a.char[3..5]
-- "win"

oder auch

put sprite(1).member.text.line[2].word[4].char[3]
-- "e"

Durch den ItemDelimiter - in Defaultfall das Komma, wird ein neues item definiert. Daher ist

put a.item[2]
-- "Der Hamilton-Operator steht in einer Eigenwertgleichung"

Es gibt auch item ranges: .item[3..5] oder man kann items einfügen: member("Nobelpreistraeger").line[2].item[4] = "Otto Hahn"

Die Character eines Strings können mit mystring.char.count gezählt werden.

Löschen und hinzufügen von Zeichen zu einem String kann nicht mit Dot-Syntax geschehen, da es sonst eine Verwechslung mit Listen gäbe!

FALSCH wäre: mystring.delete(mystring.char[2])
RICHTIG muss es heißen
delete mystring.char[2]
put "schade" after mystring

auch für die folgenden Properties von Strings kann man keine Dot-Schreibweise benutzen:

FALSCH wäre: mystring="Lingo"; put mystring.char.number; oder put mystring.char.last
RICHTIG muss es heißen
put mystring.length;  oder put the last char of mystring

FALSCH wäre: mystring="Lingo"; mystring.char[1]="B"
RICHTIG muss es heißen
put "B" into char 1 of mystring

Einen speziellen String stellt das Datum dar:
put _system.date()
das allerdings je nach Systemeinstellung des Benützers in verschiedenen Formen auftreten kann: sowohl als
--"27.10.2009"
als auch als
--"27.10.09"
Es ist daher sinnvoll vor der Auswertung des Strings seine .length Eigenschaft abzufragen.
Problematisch wird es, wenn man auch anderssprachige Datumsformate mit in Betracht ziehen muss. So kann die Datumsangabe in einem englischen System beispielsweise 3/26/12 lauten.

 

Will man eine Zahl in eine Zeichenkette umwandeln, so verwendet man string(x).

Umgekehrt führt value(string) zum Zahlenwert einer Zeichenkette (zB. "2001" wird zu 2001)

Eine Integer (Ganzzahl) wird durch float(i) in eine Floating Point (Fließkomma) Zahl umgewandelt und umgekehrt eine Floating Point Zahl durch integer(x) in die gerundete Integer.

Das Umwandeln von Werten aus einem Datentyp in einen anderen nennt man casten. Der Datentyp von z kann mit der Funktion ilk(z) ausgelesen werden. Mit Hilfe der Dot-Syntax kann ein Datentyp jederzeit neu zugewiesen werden. (Aber mit Vorsicht!) z.B.:

x="10"

put x.integer -- 10
put x.string -- "10"
put x.float -- 10.0000
put x.symbol -- #10
put x.list --["10"]

Typ VOID. Eine noch nicht initialisierte Variable hat den Wert VOID, nicht 0. Dieser Datentyp besteht also nur aus der Konstanten VOID selbst. Aktiv benutzt wird VOID um die Instanz eines Objekts zu löschen. Dabei setzt man den Zeiger zu dieser Instanz im Speicher auf VOID

einObjekt=(script "Obj").new() -- erzeugen einer Instanz
einObjekt=VOID -- zerstören der Instanz

Näheres siehe OOP-Praxis

5.1.3 Arithmetische Operationen und Concatenations

Für Integer und Floating Point Zahlen: +, -, *, /, =, <=, >=, <, >, <>.
Potenzieren:

put power(2,4).integer -- 16

darüber hinaus gibt es eine Vielzahl mathematischer Funktionen, die man am oberen Rand des Skriptfensters unter dem Symbol "Categorized Lingo>math" finden kann.

Für Strings: & und &&

put "a"&"b" -- "ab"
put "a"&&"b" -- "a b"

5.1.4 komplexere Variablentypen

Dazu zählen vornehmlich die Listen. Es gibt zwei Arten von Listen. In der sogenannten linearen Liste ist jedes Element der Liste ein bestimmter Wert. In der sogenannten Eigenschaftsliste besteht jedes Element aus zwei Werten, wobei der erste ein Eigenschaftsname ist, der zweite derWert, der mit dieser Eigenschaft verbunden ist.

5.1.4.1 Lineare Listen

Listen sind im Prinzip das, was man aus anderen Programmierumgebungen als Arrays kennt, mit dem Unterschied, dass die Bestandteile einer Liste von unterschiedlichem Variablentyp sein können, darunter auch selbst wieder vom Typ Liste. Außerdem ist die Dimension einer Liste fließend veränderbar.

MeineListe=["Director",#lecturenote,2003,3.14]
put MeineListe[2]
--#lecturenote

Die Anzahl der Elemente der obigen Liste ist MeineListe.count
Der größte Wert ist MeineListe.max, entsprechend der kleinste MeineListe.min

Listen können für aufeinanderfolgende Werte einer repeat-Schleife verwendet werden:

repeat with i in list [33,22,44,1]
   put i
end repeat

--33
--22
--44
--1

Man kann einen String, der als Liste formatiert ist in eine wirkliche Liste umwandeln:

einString = "[" & QUOTE & "cat" & QUOTE & ", " & QUOTE & "dog" & QUOTE & "]"
eineListe = value(einString)
put eineListe
-- ["cat", "dog"]

Mit dieser Technik kann man eine Liste in ein Field oder text-cast-Member setzen und dann wieder extrahieren und als Liste zurückformatieren.

Will man mehrere Werte aus einer senkrecht angeordneten Tabelle (member vom Typ field) auslesen, z.B. die Werte

44
23
98
17

so geschieht dies mit Hilfe von member("XDaten").line[i], wobei XDaten der Name der Feldvariablen und i die betreffende Zeilennummer ist. Achtung der gelieferte Wert ist vom Typ String! (Umwandlung in Zahl durch CharToNum)

Man kann auch Listen in Listen speichern. Die Initialisierung für 5 Listen in einer Liste wäre z.B.:
matrixA = [[],[],[],[],[]]
der Aufruf eines Wertes aus einer eingebetteten Liste, z.B. der 3. Wert der 2. Liste aus
matrixB = [[5,2],[8,4,6,0],[1],[],[]] erfolgt mit
zahl=matrixB[2][3]

Sinngemäß wäre eine dreidimensionale Liste
DreiDListe=[[[1,2,3],[10,20,30]],[[4,5,6],[40,50,60]]]
zahl=DreiDListe[1][2][3]
put zah
l
-- 30

(Download Beispiel ListeninListe.sit)

Das Hinzufügen von Werten am Ende einer Liste geschieht mit MeineListe.append("maxi"), das Hinzufügen der Zahl 3.14 an der 4, Stelle mit MeineListe.AddAt(4, 3.14), das Löschen des 17. Elements mit MeineListe.deleteAt(17), sortiert wird mit MeineListe.sort() in alphanumerischer Ordnung.

Zum Abarbeiten von Listen braucht man unter anderem oft Schleifen. Listen sind sehr langsam verarbeitbare Datentypen, je länger desto langsamer (siehe [5]).

Mehrdimensionale Listen kann man mit Schleifen initialisieren. Im folgenden eine 3-dimensionale:

on createArray3 (xcount, ycount, zcount, initVal)
  mylist=[]
  repeat with x=1 to xcount
   mylist.add([])
   repeat with y=1 to ycount
    mylist[x].add([])
    repeat with z=1 to zcount
     mylist[x][y].add(initVal)
    end repeat
   end repeat
  end repeat
  return mylist
end createArray3

put createArray3 (3,2,3,0)
-- [[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]]]

Eine allgemeine, rekursive Methode für n Dimensionen findet man in [5], S.302ff

will man einen Ausdruck wie    ][:   als Element definieren, so muss man die ASCII-Äquivalente verwenden:

Listenelement = numToChar(93) & numToChar(91)& ":"
put Listenelement
-- "][:"
Liste = Listenelement.value
put Liste
-- ][:

Spezielle Fälle linearer Listen sind die actorList und die windowList

Will man zwei Listen gleich setzen, so darf man nicht z.B.:

glasspoint=[point(340,292),point(380,292),point(420,292)]

oldglasspoint=glasspoint

schreiben, weil sonst oldglasspoint nur als weiterer Verweis auf die Speicherorte von glasspoint angesehen wird und somit jede Änderung in glasspoint auch in oldglasspoint aufscheint. Will man die Inhalte von glasspoint unabhängig in oldglasspoint speichern, muss man vielmehr schreiben:

repeat with i=1 to 3
oldglasspoint[i]=glasspoint[i]
end repeat

oder man verwendet einfach die duplicate() Funktion:

oldglasspoint=glasspoint.duplicate()


Man kann auch Werte einer Liste als Index in einer repeat-Schleife verwenden:

Alphabet=["a","b","c","d","e","f","g"]
Liste=[7,1,2,5]
repeat with Wert in Liste
  put Alphabet[Wert]
end repeat

"g"
"a"
"b"
"e"

5.1.4.3 Property Lists (Eigenschaftslisten)

Neben den oben besprochenen, sogenannten linearen Listen, gibt es auch noch die so genannten Eigenschaftslisten oder property lists. Sie sind n x 2-dimensional, da jede Eigenschaftsvariable #variablenname: auch einen Wert besitzt.

Es gibt mehrere Schreibweisen für Property Lists:

sprite1Loc = [#left:100, #top:150, #right:300, #bottom:350]
sprite1Loc = ["left",400, "top",550, "right",500, "bottom",750]
sprite1Loc = propList("left",400, "top",550, "right",500, "bottom",750)

Hier soll die Version wie in Zeile 1 verwendet werden. Eine leere Property List wird so definiert:

a=[:]

Eigenschaftslisten bedienen sich der Variablentype Symbol

myVar = #Lingo
put ilk(myVar)
-- #symbol
die folgende Funktion checkt, ob ihr Argument ein Symbol ist oder nicht
put symbolP (myVar)

-- 1

Dieser Datentyp ist ebenso schnell wie der Integer-Typ. Der Datentyp Symbol (mit dem Zeichen #) hat keinen Inhalt, sondern ist ein Pointer. Der Name eines Symbols darf keine Leerzeichen und Sonderzeichen und sollte keine Umlaute enthalten.

Das vom # angeführte Symbol ist der Name der Eigenschaft, der lediglich dazu dient, den nach dem Doppelpunkt angeführten Wert dergestalt zu referenzieren, dass der Name der Eigenschaft mit einem Punkt an die Variable angehängt werden kann. Eigenschaftslisten bestehen üblicherweise aus Eigenschaftsvariablen, denen ein Wert zugewiesen wird:

Robert = [#Fuesze:2,#Status:"lebendig",#Hirn:1]
Maus = [#Fuesze:4,#Status:"lebendig",#Hirn:1]
Tisch = [#Fuesze:4,#Status:"tot",#Hirn:0]

put Robert.Status
-- "lebendig"
put Tisch.Fuesze
-- 4

Diese Listen können selbst wieder in einer Liste enthalten sein
Wesen=[Robert, Maus, Tisch]

Natürlich können die Listenelemente auch über eine Variable definiert sein:

b=8
s="tot"
h=1
Spinne = [#beine:b,#Status:s,#Hirn:h]

put Spinne.beine
-- 8

Das Ändern einer vorhandenen Eigenschaft geschieht einfach durch

Tisch.beine=3

Das Hinzufügen einer neuen Eigenschaft am Ende einer Liste geschieht am einfachsten durch:

Tisch[#material]="holz"
put Tisch
-- [#beine: 3, #status: "tot", #Hirn: 0, #material: "holz"]

Will man in einer sortierten Liste - sortiert wird mit Liste.sort() in alphanumerischer Reihenfolge - ein Element an der richtigen Sortierstelle einfügen, so verwendet man

MeineKlangListe.addProp(#Klang, "Gitarre")

Das Löschen eines Elements einer PropertyListe muss unter Angabe der Property erfolgen:

note.deleteProp(#Tonhoehe)

Eine Plist kann aber auch eine Stringvariable enthalten. Z.B.

a=[:]
ichbin="Robert" --Stringvariable -- oder ichbin=#Wolff
Alter=56
a.addProp(ichbin,Alter) -- eine Stringvariable mit dem tag 56 wird der Liste angefügt
put a
put a.Robert -- oder put a.Wolff

-- ["Robert": 56]  oder  --[#Wolff:56]
-- 56

Die Referenzierung eines Elements kann auf 3 verschiedene, gleichbedeutende Arten erfolgen:

Note=[#Tondauer:"Ganze",#Tonhoehe:60]
wert=Note.Tondauer
put wert
-- "Ganze"

oder

wert=Note[#Tondauer]

oder

wert=Note[1]

Analog die Zuordnung auf dieselben 3 Arten:

Note.Tondauer="Halbe" oder Note[#Tondauer]="Halbe" oder Note[1]="Halbe"
put Note
-- [#Tondauer:"Halbe",#Tonhoehe:60]

Achtung: um Note[1] setzen zu können, muss die Liste bereits Werte enthalten

Downloadbeispiel PropertyListen

5.1.4.4 Point

Der Datentyp ist im Prinzip eine Liste mit 2 Elementen. Üblicherweise speichert Point die Koordinatenwerte eines Punktes auf einer Ebene.

put sprite(1).loc
-- point (120,709)

Für Lingo ist dieser letztere Fall eine Form der folgenden Property list: [#locH:120, #locV:70]. Deshalb kann man bei Points auch die Werte als Properties abfragen:

a=point (5,3)
put a.locH --
klarer wäre aber put a.[1]
-- 5

Das Setzen geschieht analog

a[2]=6

Beachte, dass die Properties der Listenelemente von point Integers sind. Das kann sich auswirken, wenn man z.B. eine Sprite in Stufen von Punkt A nach B rücken will, wie mit dem in der Directorhilfe für point() angegebenen Beispiel:

on mouseDown
-- Set these variables as needed for your own movie
  theSprite = 1 -- Set the sprite that should move
  steps = 40 -- Set the number of steps to get there
  initialLoc = sprite(theSprite).loc
  delta = (the clickLoc - initialLoc) / steps
   repeat with i = 1 to steps
    sprite(theSprite).loc = initialLoc + (i * delta)
    updateStage
   end repeat
end mouseDown

will man die Pointproperties in floating umwandeln, so nützt zwar float(the clickLoc - initialLoc) nichts, aber wenn steps eine Floatingzahl ist, so ist auch das Resultat delta ein Floatingwert. Also

delta = (the clickLoc - initialLoc) / float(steps)

statt z. B. point(3,4) hat delta dann den Wert point(3.0000,4.0000). Addiert man diesen Wert zu einem Point mit Intergerproperties, so resultiert wieder einer mit Float. Setzt man dann ein Spriteloc gleich diesem Floatwert, so werden die Floats gerundet. (Siehe Prozedur DreiklangaufStart im Beispiel Dreiklang).

Mit integer(point(3.0000,4.0000)) erhält man NICHT point(3,4), sondern eine eindimensionale, nicht sinnvolle Integerzahl.

Alle auf Points anwendbare Funktionen gelten auch für Quads oder Vertexlisten

5.1.4.5 Rect

Der Datentyp ist im Prinzip eine Liste mit 4 Elementen. Rect speichert den linken oberen und den rechten unteren Eckpunkt eines Rechtecks.

put sprite(1).rect
-- rect(40,60,160,140)

Für Lingo ist dieser Fall wieder eine Form der folgenden Property list: [#left:40, #top:60, #right:160, #bottom:140]. Deshalb kann man bei .rect auch die Werte als Properties abfragen:

a=[#left:40, #top:60, #right:160, #bottom:140] -- oder: a=rect(40,60,160,140)
put a.top
-- 60

Im Zusammenhang mit den .rect Eigenschaften gibt es eine interessante Funktion, nämlich map(). Diese Funktion bildet einen Sprite von einer "Zeichenfläche" auf eine andere ab. Näheres dazu findet man im Beispiel (Download map-Funktion.zip)

5.1.4.6 Object

a = (script"Objektname").new()
put ilk(a)
-- #instance
die folgende Funktion checkt, ob die ObjectProperty TRUE ist oder nicht
put objectP (a)

-- 1

in der Variablen a liegt der Pointer zur mit new erzeugten Instanz eines Parent Scripts namens Objektname. Weiteres weiter unten

Ein paar spezielle Eigenschaften von Loc, Quad, Vertexlist

Sie haben die Eigenschaft, dass eine Änderung ihres Wertes in der Liste zwar zur Kenntnis genommen wird, der Wert wird aber erst in die Liste geschrieben, wenn der ganzen Liste neu die Eigenschaft zugeordnet wird:

put sprite(1).loc
-- point (10,30)
sprite(1).loc[1]=100
put sprite(1).loc
-- point (10,30)

x=sprite(1).loc
x[1]=100
sprite(1).loc=x
put sprite(1).loc
-- point (100,30)

Gleiches gilt für Quads und Vertexlisten

5.2 Reichweiten von Variablen

5.2.1 Lokale Variable

existieren nur in dem Handler, in dem sie definiert worden sind. Verlässt man den Handler und tritt später wieder ein, so existieren die Werte der lokalen Variablen nicht mehr. Die Function showLocals zeigt alle lokalen Variablen an:

on mouseup
  i=5
  repeat with j=1 to i
    m=i*j
  end repeat
  showLocals()
end

-- Local Variables --
i = 5
j = 6
m = 25

5.2.2 Globale Variable (Globals)

existieren von ihrer Initialisierung an bis zum Beenden des Programms. Um sie beim Programmieren besser zu erkennen, ist es üblich, sie mit dem Kleinbuchstaben g beginnen zu lassen, also z.B. gWert1. Eine als global definierte Variable hat auch bereits durch diese Definition einen Wert. So würde das fogende Beispiel

on exitFrame me
if the ticks > exitticks then
sound(1).play(member("PapageiHelloKurz"))
repeat while soundbusy(1)
end repeat
exitticks=the ticks+random(270)
end if
go to the frame
end

einen Compilerfehler liefern. Schreibt man jedoch die Zeile

global exitticks

darüber, so wird kein Fehler mehr angezeigt.

Globale Variable müssen mit dem global-Statement als solche definiert werden. Dieses Statement kann in einem Skript mit mehreren Handlers entweder vor allen Handlern als erste Zeile(n) des Skripts stehen, womit sie dann für alle Handler dieses Skripts zur Verfügung stehen. Schreibt man sie innerhalb eines Handlers, wird die globale Variable nur von diesem einen Handler erkannt.

Spezialfall ist das do-Statement. verwendet es eine globale Variable, so muss diese innerhalb des Handlers definiert sein, also

on TuEtwas
  global EineStringVariable
  do EineStringVariable
end
TuEtwas

Aus dem Manual: Damit globale Variablen im gesamten Film verfügbar sind, müssen sie in der Prozedur prepareMovie deklariert und initialisiert werden. Wenn Sie anschließend den Film verlassen und dann aus einem anderen Film zu diesem zurückkehren, werden die globalen Variablen auf die Anfangswerte zurückgesetzt, falls Sie nicht zuerst überprüfen, ob sie nicht bereits eingestellt sind.

_global.showGlobals() zeigt alle zur Zeit vorhandenen Globals mit ihrenWerten und die Versionsnummer von Director an, nicht aber the actorList und the windowList.

mit der Funktion clearGlobals() werden alle globalen Variablen aus der Liste entfernt.

Die Variable the actorlist ist jederzeit global abrufbar (put the actorlist). Sie ist eine Movie property und besteht aus einer linearen Liste üblicherweise von child objects, die dieser Liste explizit hinzugefügt worden sind - man kann aber jede Art von Datentyp in der actorlist speichern, wenn man die Variable braucht, aber nicht in einer global speichern will. Achtung, diese Liste wird nicht automatisch beim Aufruf eines neuen Films gelöscht und bei Verwendung mehrerer Fenster hat jedes Fenster seine eigene actorlist. Sie ist auch für das StepFrame-event nötig. (Näheres siehe Director>Help>Lingo Dictionary>actorlist.

put the actorlist
-- []
(the actorlist).add("deutsch")
(the actorlist).add("english")
put the actorlist
-- [put the actorlist
-- ["deutsch", "english"]

löschen mit: the actorlist=[]

Eine ähnliche Sonderform der linearen Liste ist the windowList. Sie ist bei Vorhandensein mehrerer Fenster im Gegensatz zur actorList nur einmal vorhanden. Sie enthält üblicherweise Referenzen zu den geöffneten Fenstern, kann aber im Prinzip jeden beliebigen Datentyp speichern. Der clearGlobals()-Befehl tangiert sie nicht.

5.2.3 Property Variable

Es sind dies die einem Objekt (das kann sein: ein Sprite, die Bühne, die Instanz eines Xtras oder eines Parent Scripts) zugeordneten Variablen. Die Property-Variable ist verfügbar, solange das Objekt existiert.

Bei Objekten wie einem Sprite sind diese Variablen vordefiniert, wie z.B. die loc-Property eines Sprites, sprite(19).loc, als Variable vom Typ point. Erzeugt man eine eigene Instanz eines Objekts und benötigt eine Property, so muss die Property-Variable als solche am Skriptanfang gekennzeichnet werden:

on new me
property p
p= "eine Eigenschaft"
return me
end new

on EinHandler
return p
end EinHandler

EinObjekt = (script "eineEigenschaft).new()
put EinObjekt.EinHandler()
--"eine Eigenschaft"

Näheres im Kapitel über OOP

Einen Überblick über die Geschwindigkeit mit der die einzelnen Variablentypen verarbeitet werden findet man in [5, S. 33ff]

5.3 Schleifen

repeat while -irgendeine Bedingung-
  statement(s)
end repeat

---

repeat with i= 18 to 937
--statement(s), die i als Variable enthalten, z.B.
  x=i*i

  if x>10000 then
   put x
   exit repeat

  end if
end repeat

wichtig ist, die Schleife nicht unnötig weiter laufen zu lassen, was mit dem exit repeat statement geschieht. Umgekehrt ist es möglich, vorzeitig zum nächsten Schleifendurchlauf zu springen:

repeat with i= 18 to 937
  x=i*i

  if x<10000 then next repeat
  put x
  exit repeat

end repeat

 

Schleifen braucht man auch in Statement(s), die i als Argument enthalten, z.B.

...
  zahl=zahl+value(member("Darstellername").line[i])
end repeat

statt i kann irgend ein anderer Ausdruck stehen und die obere und untere Grenze können selbstverständlich auch beliebige positive Zahlen sein, wobei bei dieser Form des Statements die 2. die höhere sein muss. Eine andere Form ist:

repeat with n = 77 down to 1

und bedeutet ein Abwärtszählen

Auch Werte einer Liste können in einer repeat-Schleife abgearbeitet werden:

repeat with i in [7, 13, 8, 4]
put i
end repeat

nach "in" steht ein Liste, z.B. auch

repeat with i in eineListe
---

Ein Problem besteht darin, dass Schleifen beim Abarbeiten die höchste Priorität haben. Deshalb kann man andere Events verwenden, die regelmäßig immer wieder auftreten, wie z.B. exitframe. Man kann dann schreiben:

on exitframe
  if gInc<10 then
   gInc=gInc+1
   tuwas(param)
  end if
end

on tuwas(x)
  x=x*gInc
end

Zuvor muss man noch, z.B. im on preparemovie gInc = 0 initialisieren und die Variable gInc als global überall dort angeben, wo sie gebraucht wird.

 

5.4 Bedingungen

5.4.1 IF

Es gibt 3 Arten if-Statements zu schreiben:

if <bedingung> then
   <statement>
   <statement>
  ...
else
   <statement>
   <statement>
   ...
end if

oder ohne else

if <bedingung> then
   <statement>
   <statement>
  ...
end if

oder, wenn es nur ein Statement gibt

if <bedingung> then <statement>

alle dreiFälle sind, verschachtelt, im Beispiel ifundcase.sit enthalten

Achtung beim Vergleichen von Characters. Der Vergleich

"h"="H"

liefert den Wert true, weil nicht zwischen Groß- und Kleinschreibung unterschieden wird. Will man diesen Unterschied trotzdem evaluieren, so muss man mittels charToNum über den ASCII-Wert der Zeichen gehen:

charToNum("h") = charToNum("H")

liefert den Wert false.

5.4.2 CASE

Das Case statement sagt was zu tun ist, wenn die Bedingung eine Reihe von Werten hat

case <bedingung> of
   Wert1: <statement was dann geschehen soll>
   Wert2: <statement(s) was dann geschehen soll>
   Wert3: <statement was dann geschehen soll>
   Wert4, Wert5: <statement was dann geschehen soll>
   ...
   {otherwise: <statement(s) was ansonst geschehen soll>}

end case

Auch eine Anwendung von case kann man im Beispiel ifundcase.sit enthalten

5.5 Eigenschaften von Objekten und dem System

5.5.1 Objekteigenschaften

Eigenschaften (Properties) von Objekten können in zweifacher Weise formuliert werden, wobei erstere veraltet ist

put the locH of sprite(1)
put sprite(1).locH

die zweite Schreibweise bedient sich der Punktnotation, bei der eine Eigenschaft hinter dem Punkt des vor dem Punkt stehenden Objekts angesprochen wird. Im konkreten Beispiel die Horizontalkoordinate des Sprite im Kanal 1.

Eigenschaften können auch verschachtelt auftreten. Im folgenden Beispiel

put sprite(1).member.type
-- #field

wird die Eigenschaft einer Eigenschaft eines Objekts angesprochen, nämlich die type des members das zu sprite(1) gehört.

Spritekanäle, die nicht über das Drehbuch, sondern über Lingo gesteuert werden, nennt man puppets (auch in die Spezialkanäle kann man zu Puppets machen!). Eigenschaften wie z.B. .width, .height, .left, .right, .top und .bottom können in Lingo abgefragt und auch gesetzt werden, wobei manche, wie z.B. .left erst nach einem updatestage-Befehl ihren Wert zeigen. Natürlich muss der Sprite, um die Eigenschaften überhaupt zu besitzen einem member entsprungen sein, entweder durch Eintrag ins Drehbuch, oder z.B. durch sprite(i).member = member "Bezeichnung". Andernfalls ist der Sprite entweder <void> oder enthälten ältere Werte. (Download Spriteeigenschaften.sit).

Beim Verzerren von Sprites ist größte Vorsicht geboten, besonders, wenn im Drehbuch nicht explizit ein Sprite gesetzt wird und Darsteller über die .member Eigenschaft ausgewechselt werden. Hat man nämlich einmal den Sprite verzerrt (durch setzen einer Eigenschaft wie z.B. .right, so wird das nächste member ebenfalls in diese Spritegröße und -dimension eingepasst und nur ein puppetsprite <kanalzahl>,false und Setzen des Sprites im Drehbuch kann Abhilfe schaffen. Braucht man an einem Ort des Films sowohl angepasste, als auch unverzerrte Sprites, so sollte man für jede der zwei Typen unterschiedliche Kanäle verwenden. (Download Spriteverzerrung.sit).

Das Drehbuch ist nicht von vornherein ohne Informationen, sondern ist eigentlich schon mit Sprites belegt, nur haben diese noch keine Informationen über Darsteller, Farbe, Script und so weiter. Das kann man mit Hilfe des Nachrichtenfensters beweisen:
 
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

[ev. Notenpuzzlespiel einfügen]

5.5.2 Systemeigenschaften

Es gibt eine Reihe von Eigenschaftsvariablen, die über das System Auskunft geben

Viele sind Komponenten der globalen Variablen »the environment«:

put the environment
-- [#shockMachine: 0, #shockMachineVersion: "", #platform: "Macintosh,PowerPC", #runMode: "Author", #colorDepth: 16, #internetConnected: #offline, #uiLanguage: "English", #osLanguage: "German", #productBuildVersion: "383", #productVersion: "9.0", #osVersion: "Macintosh OS 10.2.6"]

put the environment.platform
-- "Macintosh,PowerPC"

version (oder »the environment.productversion«) gibt die Director-Versionsnummer wieder. Es ist mitunter zur automatischen Wahl der passenden Xtras (z.B. bei XMidi) nützlich festzustellen welche Version von Director in Verwendung ist.

directorVersion=version.float
if (directorVersion >=9.0) then
  set xm to new(xtra "XMidiMX")
else
  set xm to new(xtra "XMidiClassic")
end if

the deskTopRectList ist eine Liste von rect-Variablen, die jeweils die linke obere und rechte untere Ecke des Bildschirms bezeichnen (also die Auflösung in px angeben)

put  the desktoprectlist -- ergibt für einen Monitor eine Liste mit einem rect-Wert
-- [rect(0, 0, 1024, 768)]

5.6 Prozeduren (Procedures, Methoden, Handler)

Unter Prozeduren versteht man Programmteile, die auf eine Event-message reagieren und eines oder mehrere Statements ausführen. Selbst geschriebene Procedures dienen oft dazu, dass man ein und dieselbe Befehlskette nicht in verschiedenen Skripts wiederholt schreiben muss. Statt dessen referiert man an diesen Stellen nur ein einziges Skript, das dann gewöhnlich ein Filmskript ist.

Ein einfaches Beispiel einer selbstgeschriebenen Procedures ist in ProcedureBeispiel.dir.sit zu finden

Eine Konvention besagt, dass man Zugriffsmethoden mit dem Präfix "get", modifizierende mit "set" beginnt. Z.B. könnte etwa on getmeineFarbe den vorhandenen Farbwert eines Objekts liefern, hingegen wird setirgendwelcheKoordinaten eher eine Methode zum setzen von Koordinaten eines Objekts sein. Natürlich gibt es eine Unzahl anderer denkbarer Methoden, die weder Zugriffe noch modifizierend sein müssen und daher nicht durch einen der beiden Präfixe zu charakterisieren sind.

Ein Handler-Aufruf kann mittels eines do-Statements auch indirekt erfolgen, indem eine in einer Liste abgespeicherte Stringvariable angesprochen wird. z.B.:

a=["beep","AndererHandler"]
mit
do a[1] wird der systemeigene Handler "Beep" (Ausgabe des Warntons) aufgerufen, mit
do a[2] wird der vom User definierte Handler "AndererHandler" aufgerufen. Es muss also irgendwo ein
on AndererHandler
Handler deklariert sein.

5.6.1 Parameterübergabe

Eine Prozedur kann Werte erhalten, etwas damit unternehmen oder sie auch verändern und über eine globale Variable wieder zurückgeben. Streng genommen ist der Begriff Parameter auf die Liste der in einer Prozedur angegebenen veränderbaren Werte anzuwenden, also etwa auf a,b und c in on doit (a,b,c), während die Werte im Aufruf, also doit (2.3, 3, "abc") als Argumente zu bezeichnen sind. Jedoch wird diese Unterscheidung im allgemeinen Sprachgebrauch meist nicht so scharf getroffen.

Diese Werte können aber nicht über die Parameterliste zurück übergeben werden. Beispielsweise wird die Variable x nicht verändert, wenn man schreibt

on mouseup
x=2
quadr(x)
put x -- LIEFERT x=2 !!!
end

on quadr(x)
x=x*x
end

man erhält im put- Befehl den Wert 2 - nicht 4. Will man einen Wert ohne Zuhilfenahme von globalen Variablen übergeben, so bedient man sich der Function. Für einen Vergleich siehe das Beispiel ProcedureFunction.dir.zip

Mitunter schadet es nicht abzufragen, ob das übergebene Argument dem geforderten Datentyp entspricht. Sollte er also z.B. vom Typ #integer sein, dann schriebe man:

on mitZweiMultiplizieren (i)
    if NOT(ilk(i,#integer)) then -- alternativ ginge auch: if NOT(integerP(i)) then
       _player.alert "Parameter ist kein Integer!"
       exit
    end if
    i=i*2
end mitZweiMultiplizieren

Die Form der Übergabe, in der im aufrufenden Statement, z.B.

machWas(k,strg,prop)

und im empfangenden andere Variablen stehen

on machWas(i,Zeichen,wieIstEs)

nennt man "Passed by value", denn der Wert von k wird nach i kopiert, der von strg in die Variable Zeichen und der von prop nach wieIstEs. Es werden also die Werte der Parameter im aufrufenden Statement nicht verändert, auch wenn i und/oder Zeichen und/oder wieIstes verändert werden.

global i,s,p
on mouseup
  i=2
  s="gut"
  p=#schön
  ichrufedich(i,s,p)
end mouseup

on ichrufedich(k,z,e)
  put "i,s,p, vorher: ",i,s,p
  put "k,z,e, vorher: ",k,z,e
  k=3*i
  z=z&"gläubig"
  e=#schiach
  put "i,s,p, nachher: ",i,s,p
  put "k,z,e, nachher: ",k,z,e
end

-- "i,s,p, vorher: " 2 "gut" #schön
-- "k,z,e, vorher: " 2 "gut" #schön
-- "i,s,p, nachher: " 2 "gut" #schön
-- "k,z,e, nachher: " 6 "gutgläubig" #schiach

Man muss darauf achten, dass der Aufruf einer Prozedur erfolgreich sein kann. Wenn man z.B. in einem Verhaltensskript eine Prozedur aufruft, die in einem z.B. Frameskript steht, so kann dieser Aufruf nicht erfolgreich sein und man erhält beim die Fehlermeldung, dass es eine entsprechende Prozedur nicht gäbe. Befindet sich diese Prozedur aber in einem Filmskript, so ist sie von überall her erreichbar.

Neben dem oben erwähnten "Passed by value", das ist also das Kopieren des Ursprungswerts in die Parameter der aufgerufenen Prozedur, geltend für die Datentypen Rect, Point, Integer, Float, String, Symbol und Void, gibt es außerdem auch "Passed by reference", wobei statt eines Wertes ein Pointer übergeben wird, wodurch der Wert des Arguments bei Veränderungen innerhalb der Prozedur auch verändert wird. Dieser Typ tritt nur bei Listen, sowie Objekt- und Xtra-Instanzen auf.

Da lingo non-typed ist (man muss die Variablentype nicht vorher deklarieren wie bei Fortran, C/C++ oder Java) ist es sinnvoll bei Variablenübergaben, besonders in Prozeduren und Funktionen den Datentyp zu checken, da sonst unvorhersehbare Dinge eintreten können.

on addiere(wert1,wert2)
  if integerP(wert1) AND integerP(wert2) then
   return wert1+wert2 --durch return wird die Prozedur beendet
  else
   _player.alert "Integerfehler in Funktion addiere"
  end if
end addiere

Eine Besonderheit stellt der Fall dar, bei dem der Aufruf eine beliebige Zahl von Parametern enthalten kann und erst in der aufgerufenen Prozedur die Anzahl der Argumente festgestellt wird:

on mouseup
global sum
AddNumbers(1,3,7,15,8)
end

on AddNumbers
global sum
sum = 0
repeat with currentParamNum = 1 to the paramCount
sum = sum + param(currentParamNum)
end repeat
return sum
end

5.7 Functions

Functions stellen eine wichtige Gruppe von Prozeduren dar, besonders in Hinblick auf OOP. Die Function kann mehrere Parameter im Aufruf haben, aber nur einen Wert zurück geben. Will man mehrere Werte verändern, so muss man diese als globale Variable definieren und verändern. Meist ist dann eine Procedure eher angebracht als eine Function. Die Struktur einer Function ist folgendermaßen:

Aufruf:

put GibmirEineZahl()

Function:

on GibmirEineZahl()
  derWertderFunktion = random(100) -- z.B. eine Zufallszahl zwischen 1 und 100
  return derWertderFunktion
end

oder

Function:

on ErsetzeErstenDurchM(was)
  delete char 1 of was
  put "M" before was
  return was
end

Aufruf:

x=ErsetzeErstenDurchM("Weile")

put x
-- "Meile"

Wichtig ist, dass im Aufruf der Function immer eine Klammer steht, selbst wenn sie keinen Parameter enthält und dass die Function selbst, so wie eine Prozedur, in einem Filmskript untergebracht ist und nicht in einem Verhaltensskript. Jede Function muss außerdem das Statement return xxx enthalten, welches angibt, dass der Variablenwert xxx als Funktionswert zurückgegeben werden soll. Es kann jeder beliebige, in der Function vorkommende Wert übergeben werden. Die folgende Function gibt den Wert 3 zurück:

on gibEinenWert()
a=1
b=3
c=8
return b
end

Der Aufruf kann auch mehrere Werte enthalten wie im folgenden Beispiel:

on mouseup
x=2
y=5
z=-1
x=rechne(x,y,z,10)
put x
end

on rechne(x,y,z,n)
a=x*y*z-n
return a --liefert den Wert -20
end

Die Function ist in Lingo nicht typisiert, d.h. es ist bei ihrer Deklaration nicht nötig zu wissen welcher Datentyp zurückgegeben wird. Das Gleiche gilt sowohl für den Datentyp, wie auch für die Anzahl der übergebenen Parameter. Trotzdem sollte man in dieser Hinsicht nicht schlampig sein und auf Übereinstimmung zwischen aufrufendem und empfangendem Statement achten.

Einen Spezialfall stellt die Situation dar, wenn es sich nicht vermeiden lässt mit einer wechselnden Zahl von Parametern zu arbeiten. In diesem Fall gibt man gar keinen Parameter in der Function an, erhält aber dennoch übergebene Parameter über die intrinsischen Funktionen param() und paramcount():

on MeineFunktion()
  parameterliste=[]
  repeat with i=1 to the paramcount
    parameterliste.add(param(i)
  end repeat
  put "Parameter: && parameterliste()
  put"Parameteranzahl:" && paramcount()
end

MeineFunktion ("Text",2,[#Robert])
-- "Parameter: ["Text",2,[#Robert]]"
-- "Parameteranzahl: 3
"

(Download FunctionWertUebergabe.sit)

5.8 Was die Maus verrät

_mouse.mouseloc gibt an wo gerade die Maus sich befindet (h,v-Koordinate in _mouse.mouseH und_mouse.mouseV)

put _mouse.mouseloc
liefert
-- point(773, 218)

put _mouse.mouseH oder
put _mouse.mouseloc.locH
liefert
-- 773

_mouse.mouseLine gibt die Zeilennummer einer Zeile eines Field Members über dem sich die Maus gerade befindet

currentLine = _mouse.mouseMember.line[_mouse.mouseLine]

Ist keine Zeile gewählt,so ist_mouse.mouseLine gleich -1.

_mouse.mouseMember gibt den Darsteller an, über dessen Sprite sich die Maus gerade befindet.

Mit der Eigenschaft _mouse.clickon kann geprüft werden welcher Kanalnummer das zuletzt angeklickte Sprite angehört. Wurde als letztes auf die Bühne geklickt, so ist _mouse.clickon gleich null. Achtung: damit ein Sprite klickbar ist, muss entweder es selbst oder der zugehörige Darsteller ein Skript mit einemMouseUp oder MouseDown Handler enthalten! (Man gibt dort sinnvollerweise zumindest ein pass statement ein, damit das Ereignis weitergereicht wird.)


5.9 Spriteeigenschaften

sprite(17).loc gibt die Horizontal- und Vertikalkoordinate an, .locH, .locV und .locZ die Einzelkomponenten, wobei locZ die Ebenen-Schichtung auf der Bühne darstellt (welcher Sprite ist vor oder hinter welchem anderen)

sprite(1).within(2) zeigt an ob ein Sprite mit einem anderen zumindest teilweise überlappt. Das folgende Anwendungsbeispiel ist runterladbar (d/l withinBeisp).

5.10 QuicktimeMovies

Um überhaupt festzustellen ob das Member ein QT oder QTVR ist kann man #quicktimemedia abfragen:

if sprite(1).member.type = #quickTimeMedia then
  if sprite(1).isVRMovie then
   _player.alert "ich bin ein QTVR"
  else
  _player.alert"ich bin kein QTVR"
  end if
else
 _player.alert"ich bin überhaupt kein QT-Darsteller"
end if

Gewöhnlich startet das DV wenn der Abspielkopf in sein Frame eintritt und läuft bis zum Schluss. Die Lautstärke des QTs ist die .volume-Eigenschaft seines Sprites

sprite(26).volume=200 (Werte zwischen 0 und 255)

Will man nur einen Ausschnitt sehen, so kann man mit der loop-property undloopBoundsarbeiten.

#loopBounds ist eine QT-Sprite-Listeneigenschaft [startTime, endTime], wobei die Zeit in Ticks gegeben ist. Default ist [0,0]. Der Film beginnt bei 0 und loopt dann. #loopBounds funktioniert nur, wenn #loop des Films auf TRUE steht. #loop kann on-the-fly geändert werden, womit sich der Film dann anders verhält. (Für Details siehe Lingo-Help von #loopBounds). Im folgenden Beispiel beginnt der Film und loopt dann von Sekunde 16 zu Sekunde 32

on beginSprite me
  sprite(me.spriteNum).loopBounds = [(16 * 60),(32 * 60)]
end

Eine andere, noch flexiblere Art der Zeitsteuerung ist #currentTime(früher #movietime). Diese Eigenschaft gibt den Punkt der Zeitachse des Movies an, an dem es sich gerade befindet. Sie kann abgefragt und gesetzt werden. Setzt man z.B.

sprite(9).currentTime = 0

so hat man das Movie zurückgespult. die movieTime wird in Ticks gemessen, 1 Tick = 1/60 sek. So kann man bestimmen, dass etwas passiert, wenn die movieTime   eines QT-Sprites einen gewissen Wert überschritten hat (entspricht im Effekt einem Marker in einem Soundtrack).

Mit der Eigenschaft #duration kann die Gesamtlänge eines Movies im msek abgefragt werden, wobei diese Eigenschaft eine des Members - nicht des Sprites ist. Die Dauer des Streams ist erst bekannt, wenn die Wiedergabe des Darstellers beginnt. Wenn der Stream aus einem Live-Feed stammt oder noch nie abgespielt wurde, ist der Wert dieser Eigenschaft 0.

put member("King Kong").duration

The MovieRate (the PlayRate bezieht sich entsprechend nur auf DVDs) gibt die Geschwindigkeit und Richtung des Abspielens an. 1 ist normal vorwärts, -1 normal rückwärts, 0 ist stop. Andere Werte sind ebenfalls möglich (-0,5, +3 etc.) und haben entsprechende Bedeutungen. Das Maximaltempo hängt allerdings von der Hardware ab und davon ob der Sprite verzerrt oder in Originalgröße auf der Bühne ist. (download QT.sit)

Die Lautstärke eines QTmovies wird über #volume eingestellt (0…256). z.B. sprite(7).volume = 256

Wie schon früher angegeben kann ein DTS Movie eine Maske haben. Dazu verwendet man die #mask Eigenschaft eines QT-Darstellers. Z.B.:

on prepareFrame
member("Bahn").mask = member(2)
end

#mask ist also eine Cast member property des QT-members und spezifiziert ein s/w (1-bit) cast member, das als Maske für einen DTS-Mediendarsteller dient, wobei dieser in jenen Bereichen aufscheint, in denen die Maskenpixel schwarz sind. #mask kombiniert die Geschwindigkeitsvorteile von DTS mit der Möglichkeit einer individuell geformten Bühne. Auf non-direct-to-Stage Members hat #mask keinen Einfluss.

Director richtet den registration point des mask cast member mit dem oberen linken Eck des QuickTime movie sprite aus. Deshalb muss auch der registration point des bitmap-members ins linke obere Eck verbracht werden. Das mask cast member kann nicht bewegt werden und wird nicht von #center und #crop betroffen.
Die mask-Eigenschaften eines QuickTime cast member sollte man im on beginSprite event handler setzen bevor der Sprite gezeichnet wird, da es sonst zu unvorhersehbaren Effekten kommen kann. Um eine Maske zu entfernen setzt man die mask property auf 0.

Je nach dem Wert der Eigenschaft #invertmask  zeichnet Director den Film auf die weißen (invertmask #true) oder auf die schwarzen Pixel (#false) der Maske. Um den Effekt der Maske umzukehren setzt man:

member(whichQuickTimeMember).invertMask=NOT(member(whichQuickTimeMember).invertMask)

QTs können, so wie normale Bitmaps, animierte GIFs oder Flashmovies auch rotiert werden mit der Eigenschaft #rotation. Z.B. wird im nächsten Skript ein sprite um 16 Grad-Inkremente rotiert und der Kopf loopt, bis 360 Grad erreicht worden sind:

on exitFrame
  if sprite(5).rotation < 360 then
   sprite(5).rotation = sprite(5).rotation + 16
   --updatestage
nicht nötig, weil das der frame head ohnehin macht
   go the frame
  end if
end

Der folgende Handler rotiert ein Movie Sprite um 360° in 10° Inkrementen:

on rotateMovie whichSprite
  repeat with i = 1 to 36
   sprite(whichSprite).rotation = i * 10
   updatestage
  end repeat
end

Um den Rotationsgrad bei fortgesetzter Drehung nicht ins Unendliche wachsen zu lassen, muss man etwa folgendermaßen formulieren:

sprite(spriteNum).rotation = integer(sprite(spriteNum).rotation + 2) mod 360


Mit der Eigenschaft #scale kann man Cast members und Sprites vom Typ QT, vector shape oder Flash Movie verzerren. Für QuickTime wird dabei nicht das umschreibende Rechteck oder der Controller verändert. Stattdessen wird das Bild um seinen Mittelpunkt innerhalb des umschreibenden Rechtecks skaliert. Scaling ist in einer Liste spezifiziert, die zwei Prozentangaben vom Typ #float enthält: [xPercent, yPercent].

Ist die crop property des Sprites TRUE, kann die scale property ein Zoomen simulieren. Ist die crop propertydes Sprites FALSE, wird #scale ignoriert. Default ist [1.0000,1.0000].

Für Flash movies oder Vector Shape Members, ist the scale ein floating-point Wert. Das Movie wird von seinem origin point skaliert, der wiederum in der originMode property spezifiziert wird:

on beginSprite me
  sprite(spriteNum of me).originMode = #point
  --oder
  sprite(spriteNum of me).originH = 100
  sprite(spriteNum of me).originV = 80
end

Diese Eigenschaft muss auf den default Wert gesetzt sein, wenn die scaleMode property auf #autoSize gesetzt ist, damit der Sprite sich richtig verhält.

Im folgenden Beispiel wird geloopt während das QuickTime Sprite inKanal 5 in 5% Inkrementen runterskaliert wird. Wenn der Sprite verschwunden ist, geht der Abspielkopf weiter

on exitFrame me
  scaleFactor = sprite(spriteNum).scale[1]
  currentMemberNum = sprite(spriteNum).memberNum
  if member(currentMemberNum).crop = FALSE then
   member(currentMemberNum).crop = TRUE
  end if
  if scaleFactor > 0 then
   scaleFactor = scaleFactor - 5
   sprite(spriteNum).scale = [scaleFactor, scaleFactor]
   go the frame
  end if
end


Über den Effekt von Mausklicks auf ein QT-Sprite siehe bei QTVR.

5.11 Cursorformen

Eine gute Übersicht zu diesem Thema findet sich hier.

5.12 QTVR

5.12.1 Allgemeines

QTVRs werden so wie QT movies importiert. die besten Resultate erzielt man mit DTS.

Um festzustellen ob ein Darsteller ein QTVR ist siehe weiter oben.

Lingo erlaubt die Kontrolle darüber wie QuickTime VR reagiert, wenn ein User ein QuickTime VR sprite anklickt. Man kann Spezifikationen erteilen zur image quality, Klicks und Rollovers eines QuickTime VR Sprites, Klicks auf Hotspots, und Interaktionen mit QuickTime VR nodes.

5.12.2 Mausaktionen

sprite(whichQuickTimeSprite).mouseLevel; Wie Director Maus Klicks auf ein QuickTime sprite an QuickTime weiterleitet. Die möglichen Werte dieser Eigenschaft sind:
#controller-- Klicks auf den Controller werden von QT erkannt, Klicks außerhalb übernimmt Director. (Default für normale QT-Sprites).
#all-- Sämtliche Mausklicks innerhalb des das QT-Sprite umgebenden Rechtecks werden an QT geleitet. Das übrige Lingo bekommt nichts davon mit.
#none--Sämtliche Klicks werden an Director weitergeleitet, QT bekommt nichts davon mit.
#shared-- Jeder Mausklick geht zuerst an QT und dann weiter an Directorlingo. Defaultwert für QuickTime VR.

Beispiel:

on prepareFrame
  if sprite(5).member.name contains "QTVR" then
   sprite(5).mouseLevel = #all
  else
   sprite(5).mouseLevel = #none
  end if
end

5.12.3 HotSpots

Das QTVR-Kommando enableHotSpot(sprite whichQTVRSprite, hotSpotID, trueOrFalse) spezifiziert ob der Hotspot für das angegebene QTVR sprite enabled (TRUE), oder disabled (FALSE) ist.Enable oder disable einen bestimmten Hotspot mit dem enableHotSpot command: enableHotSpot(sprite whichQTVRSprite, hotSpotID, trueOrFalse).

Das ungefähre umschreibende Rechteck eine Hotspots ist sprite(whichQTVRSprite).getHotSpotRect(hotSpotID).

Mit den Eigenschaften #hotSpotExitCallback und #hotSpotEnterCallback kann man feststellen ob die Maus einen Hotspot verlässt oder in ihn eintritt. Analog sprite(whichQTVRSprite).triggerCallback. Es enthält den Namen des Handlers der läuft, wenn der User einen Hotspot in einem QuickTime VR movie klickt. Der Handler erhält 2 Argumente: me und die ID des geklickten Hotspots.
Der zurückgegebene Wert bestimmt wie das movie den Hotspot verarbeitet. Bei #continue, setzt das QuickTime VR sprite fort den hotspot normal zu verarbeiten. Bei #cancel wird das default behavior für den Hotspot gecancelt.
Null setzen löscht den callback.

ptToHotSpotID(whichQTVRSprite, point) retourniert die ID des Hotspot, wenn überhaupt vorhanden, am spezifizierten Punkt. Ist dort kein Hotspot, gibt die Funktion 0 zurück.

Bewegen des QTVR, view

sprite(whichQTVRSprite).nudge(#direction ). Verschiebt die Blickperspektive in die Richtung #direction. Mögliche Werte: #down, #downLeft, #downRight, #left, #right, #up, #upLeft, and #upRight. Nudging nach rechts bewirkt, dass sich das Image des Sprites  nach links bewegt.
Im folgenden Beispiel verschiebt der Handler die Perspektive des QTVR sprite nach links:

on mouseDown me
  repeat while _mouse.stillDown
   sprite(1).nudge(#left)
  end repeat
end

pan of sprite whichQTVRSprite
Der momentane pan des QuickTime VR movie in Grad.


WhichQTVRSprite.swing(pan, tilt, fieldOfView, speedToSwing)
oder swing (whichQTVRSprite, pan, tilt, fieldOfView, speedToSwing) Swingt ein QuickTime 3 Sprite beinhaltend ein VR Pano zum neuen view Setting. Die Function läuft augenblicklich ab, aber der Sprite setzt seine Aktion fort, bis es den Endzustand erreicht hat. Um zu testen, ob der Swing fertig ist, checkt man ob die pan property des Sprite seinen Endwert erreicht hat. Mit dem folgenden Statement wird die view des QTVR sprite 1 auf 300°, einen Tilt von -15°, und einem field of view von 40°: sprite(1).swing(300, -15, 40, 1)

tilt of sprite (whichQTVRSprite) gibt den momentanen Tilt, in Grad des QuickTime VR movies.

member(whichQuickTimeMember).translation oder sprite(whichQuickTimeSprite).translation. kontrolliert den Offset des Images eines QuickTime sprite's innerhalb der bounding box. Näheres siehe Lingo-Help.

Um den Blickwinkel (Weite des Sehfeldes in Grad) abzufragen oder anzugeben verwendet man sprite(whichQTVRSprite).fieldOfView

Node-Funktionen

Unter Node versteht man eine neue Ansicht des Objekts.

Die derzeitig angezeigte Node-ID wird abgefragt mit sprite(whichQTVRSprite).node

sprite(whichQTVRSprite).nodeEnterCallback beinhaltet den Namen desjenigen Handlers der läuft nachdem das QTVR zu einem neuen aktiven Node gewechselt hat. Die Message hat 2 Argumente: me und die ID des gezeigten Nodes. Der callback wird durch Null setzen gelöscht. Entsprechend zeigt sprite(whichQTVRSprite).nodeExitCallback den Name des Handlers der gerade läuft, wenn das QuickTime VR movie ansetzt, zu einem neuen aktiven Node auf der Bühne zu wechseln. Die Message hat 3 Argumente: me, die ID des Nodes das das Movie gerade verlässt unddie ID des Nodes zu dem das Movie wechseln will. Der vom Handler zurückgegebene Wert bestimmt ob das Movie zum nächsten Node geht. Bei #continue fährt das QTVR mit einem normalen Node-Übergang fort. Bei #cancel, bleibt das Movie im ursprünglichen Node.
Mit 0 wird der callback gelöscht.

Die Eigenschaft sprite(whichQTVRSprite).nodeType kann getetstet werden und gibt die Art von Node an, das zur Zeit auf der Bühne ist. Mögliche Werte sind #object, #panorama, oder #unknown (Wert für einen Sprite, das kein QTVR ist).


Codec

staticQuality of sprite whichQTVRSprite. Spezifiziert die Codec quality die verwendet werden soll, wenn das panorama image statisch ist. Mögliche Werte sind #minQuality, #maxQuality, und #normalQuality.Um die Codec quality zu setzen für den Fall, dass der Benutzer an einem QTVR anzieht, verwendet man sprite(whichQTVRSprite).motionQuality mit denselben Werten.

6. Imaging Lingo

6.1 Farben

Sprites können in Lingo Farben zugeordnet werden. Um einen Sprite in einer bestimmten rgb-Farbe einzufärben benutzt man die .color Eigenschaft:

sprite(1).color=color(#rgb,255,10,58)

Wichtig ist, dass der Sprite schon auf der Bühne besteht bevor man ihn einfärbt. Will man also einen Sprite einfärben und in dieser Farbe erscheinen lassen, so kann man das ein Frame vorher ausführen, wobei der Sprite dazu außerhalb des Bühnenbereichs platziert wird. Im nächsten Frame macht man ein neues Keyframe und stellt den eingefärbten Sprite dorthin wo er sich auf der Bühne befinden soll.

6.2 Transparenz

Die Deckkraft eines Sprites kann zwischen 0 und 100 eingestellt werden. Z.B. sprite(1).blend=35

6.3 Formen auf die Bühne bringen

Will man auf der Bühne zeichnen ohne einen Sprite eines Darstellers zu erzeugen, so bedient man sich der .fill Methode

6.3 Bitmapkopie der Bühne

Mit dem Befehl

member("Darst").picture = _movie.stage.picture

kann man das momentane Bild der Bühne in einen Darsteller mit dem Namen Darst reinkopieren.

7. Objektorientierte Programmierung (OOP)

OOP musste wegen seines großen Umfangs ausgelagert werden und ist hier zu finden

8. Daten Ein- und Ausgabe

8.1 FileI/O

Als erstes muss ein neues IO-Objekt erstellt werden, sofern noch keines existiert:

if IO = Void then IO=(xtra "FileIO").new()

Ich habe dem Objekt hier den Namen IO gegeben. Dieser Name muss an allen Stellen, an denen ausgeschrieben oder gelesen wird in den globalen Variablen angeführt werden (global IO). Danach wird eine Ausgabedatei erzeugt:

IO.createFile("LisssnSicherung")

Ich habe ihr den Namen LisssnSicherung gegeben. Hier kann auch, soll nicht in das selbe Verzeichnis geschrieben werden, eine Pfadangabe für die Datei vorangestellt sein. Also z.B. im Falle eines Macs MeineFestplatte:Sicherungen:"LisssnSicherung" wenn die Datei in den Ordner Sicherungen auf der Platte MeineFestplatte gehen soll. Als nächstes ist abzuchecken, ob dieser Vorgang erfolgreich war. Es könnte ja sein, dass schon eine Datei dieses Namens existiert:

FehlerStatus=IO.error(IO.status())

IO.status() ist ein Fehlercode der aufgerufenen Methode IO, IO.error(n) gibt eine angegebene Fehlermeldung der Methode zurück. Nur wenn alles ok ist, ist dieser Code=0

die gesamte Messageliste von FileIO erhält man ins Message-Fenster geschrieben mit put mMessageList (xtra "FileIO").

Ein Codebeispiel kann aus download FileIO.zip geladen werden. Weitere Erklärungen in deans director tutorials. Eine kleine Routine zumAusschreiben und Einlesen von String-Listen findet sich hier im Adobe-Forum

Man kann das Xtra auch dazu benutzen, um den Laufwerksbuchstaben eines Windows-Pfades herauszufinden (siehe tech-Note).

Letztlich ist es wichtig nachzusehen ob das FileIO-Xtra in der Liste der zu publierenden Xtras auch eingeschlossen ist (Modifizieren>Film>Xtras). Die Datei mag im Authoringmode klaglos funktionieren steigt im veröffentlichten Modus jedoch dort aus, wo das Xtra  erschaffen wird, wenn man vergessen hat, es beim Authoring dazu zu laden.

8.2 Externe Besetzungen

Neben der automatisch vorgegebenen internen Besetzung besteht eine andere Möglichkeit zum Abspeichern von Daten darin, Werte oder Bilder in einer externen Besetzung abzuspeichern. Sie verringert den RAM-Bedarf, da sie erst nach dem Start des Films eingelesen wird und in verknüpften Filmen je nach Notwendigkeit gar nicht vorkommen muss. Das ist der Fall, wenn ihre Darsteller nur in bestimmten Filmen einer Gruppe von verknüpfte Filmen gebraucht wird. Wichtig dabei ist, dass diese externe Datei nicht nur dort in die Besetzungsliste aufgenommen wird, wo sie beschrieben oder gelesen wird, sondern mitunter auch in dem Film, in dem einer ihrer Werte gesetzt wird,wie beispielsweise globale Variable, die zu Beginn eines Filmes gesetzt, aber erst später in einem anderen anderen Film gebraucht werden. Globale Variable bleiben beim Wechsel veknüpfter Filme erhalten.

Prinzipiell kann mn über die Funktion fileName(Cast) auch ganze Casts einlesen (interne und externe) oder auch ausschreiben (nur externe). Näheres dazu findet man hier.

Eine Besetzung kann auch, besonders nachdem sie sich im Ablauf geändert hat, gesichert werden. Genügt es, den Cast am selben Speicherort upzudaten, so lautet der Befehl

castLib(whichCast).save()

Will man aber eventuell auch einen neuen Speicherort und einen neuen Namen angeben, so schreibt man

save castLib whichCast {,pathName&newFileName}

So würde man also die englische Version einer Besetzung Textseiten in einer Datei TestseitenEnglisch folgendermaßen speichern:

castLib("Textseiten").save(the moviePath & "TestseitenEnglisch.cst")

 

9. Der Projektor / exportieren

Um ein Stand-alone Programm herzustellen wird das Directorprojekt "veröffentlicht". Dabei darf man nicht darauf vergessen, etwaige abhängige Film- oder Besetzungsdateien mit Hilfe der "Veröffentlichungseinstellungen" mit einzuschließen.

Ob das Fenster der fertigen .app- oder .exe-Datei eine Titelleiste hat und ob es maximiert werden kann ist eine Fenstereigenschaft des Fensters "stage". Z.B.

window("stage").titlebarOptions.visible = false
window("stage").resizable = true

So wie auch schon in den frühen Versionen des Programmes, ist es ab Version 2004MX möglich, mit einem einzigen Programm Projektoren für beliebige Plattformen zu erstellen (die Windowsversion und die MacVersion ab 11.5 können allerdings keine MacClassic-Projektoren mehr erzeugen):

publishing

bug Gelegentlich kann es vorkommen, dass sich ein veröffentlichtes Projekt anders verhält als vor der Veröffentlichung Das liegt zumeist daran, dass ein oder mehrere Xtras nicht oder nicht richtig geladen wurden. Dazu genügt es manchmal - sofern es sich um ein Problem mit Standardxtras handelt, im Menü Modifizieren>Film>Xtras... einmal auf den Button "Standard hinzufügen" zu klicken und dann zu veröffentlichen - auch wenn das gewünschte Xtra schon vorher im linken Teil des Fensters angezeigt worden war.

the runMode ist eine Property der Umgebungsvariablen the environment; sie liefert einen string, der angibt in welchem mode das movie läuft. Die möglichen Werte sind: Author—Das Movie läuft in Director.
Projector—Das Movie läuft als Projector.
Plugin—Das Movie läuft als Shockwave plug-in (oder in einer anderen scripting Umgebung)
Java Applet—Das Movie läuft als Java applet.

Beispiel:

Dieses Statement bestimmt ob externe Parameter verfügbar sind und speichert sie im positiven Fall in einer Variablen:

if the runMode contains "Plugin" then
  -- decodiere die Parameter
  if externalParamName(swURL) = swURL then
   put externalParamValue(swURL) into myVariable
  end if
end if


9.1 Pfadangaben

Bei der Verwendung verknüpfter Dateien müssen sich diese immer am gleichen relativen Pfad im Verhältnis zum exekutierenden Programm befinden. Dabei gibt es in den Pfadbeschreibungen mittlerweilen keine Unterschiede mehr zwischen Mac und Windowssystemen.

Der Speicherort des Ordners des aktuellen Films befindet sich im Zeichen @. (Beachte, dass bei voneinander abhängigen Filmen @ nicht den Ordner des Startfilms betrifft, sondern den desjenigen Films, der gerade läuft, wenn @ referenziert wird). Man kann den Ort auslesen mit

put the moviePath oder moderner
put _movie.path

Ein Unterordner u1 wird angesprochen mit

@:u1

ein darin befindliches File f1 mit

@:u1:f1

zu einer Datei f2 im ersten oder zu f3 im zweiten über dem Film befindlichen Ordner gelangt man mit

@::f2
@:::f3

download Pfadbeispiel für Mac   download Pfadbeispiel für Win

Allerdings hat der @-Operator den Nachteil, dass man keine Möglichkeit hat, den tatsächlich ermittelten Pfadnamen auszugeben und die meisten Xtras damit auch nicht klarkommen. Außerdem bekommt er seine eigentliche Bedeutung ja auch erst, wenn man Unterverzeichnisse adressieren willst. Genau darin unterscheiden sich nämlich Mac, Windows und Unix (bei Shockwave-URLs): bei dem Zeichen (unten im Code in der Variablen delim), das Pfadnamen in Verzeichnisebenen aufteilt: auf dem Mac ist das ":", auf Windows "\" und auf Unix "/". Eine elegantere Möglichkeit sieht folgendermaßen aus:

mp = _movie.path
delim = the last char of mp
--zum Beispiel (ohne Unterverzeichnisse):
_movie.go (1,mp & "goStart") -- 1 ist die Nummer des anzusteuernden Frames
--mit Unterverzeichnissen:
_movie.go (1,mp & "Verzeichnis1" & delim & "Verzeichnis2" & delim & "goStart")

Achtung: Filenamen dürfen keine Punkte enthalten. Ein File Name.3 wird zwar in der Pfadangabe gefunden, so lange die Dateien nicht geschütz sind. Werden sie aber geschützt, so ist das resultierende Name.3.dxr nicht mehr zu finden.

Man muss allerdings Acht geben, dass Ordner und darin enthaltenes Objekt nicht den selben Namen haben, da es dann passieren kann, dass die Ordnerhierarchie um das letzte Element zu wenig enthält. Das lässt sich aber leicht im msg-Window mit put _movie.path kontrollieren.

Will man während des Programmierens die Pfadangabe für einen cast ändern, so wählt man einen Darsteller des Casts und anschließend im PI den Reiter cast. durch klick auf den Button rechts unter der aktuellen Pfadangabe, kann man einen neuen Pfad eingeben.

Um den Laufwerksbuchstaben eines Windowssystems herauszufinden kann man sich des FileIO-Xtras bedienen (siehe tech-Note)


9.2 Kompression

Mit der zunehmenden Größe der Bilder (etwa 1024x768px) jedes einzelnen Frames lässt es sich bei ausgedehnteren Projekten heutzutage (2012) nicht mehr vermeiden Filme zu komprimieren. Eine Kompression der Grafiken auf 94% kann schon eine Verringerung der Datenmenge auf weniger als 1/4 der unkomprimierten Größe bringen. Es gibt allerdings Darstellertypen, die nicht komprimiert werden können, insbesondere solche, die einen Alpha-Kanal enthalten, da dieser bei der Komprimierung verloren ginge. Man kann also die Bilder mit Alpha-Kanal in die interne Besetzung geben, die komprimierbaren in einen externen Cast und dann den Film einmal unkomprimiert veröffentlichen, dann komprimiert und den dadurch komprimierten externen Cast in den unkomprimierten Film stecken. Dieses Procedere ergibt weitere Einsparungsmöglichkeiten, wenn man Zwischenbilder, die nur kurz in einer Animation auftreten in einen weiteren externen Cast gibt, den man in einer stärkeren Kompression sichert. Das ist deshalb möglich, weil die Übergangsbilder in einer Animation meist recht schnell ablaufen und daher keine größe Detailtreue benötigen.

Zum Komprimieren geht man in den Veröffentlichungseinstellungen folgendermaßen vor:
Auch wenn der Playertyp "Standard" ist, kann komprimiert werden. Man muss auf jeden Fall einmal angeben, dass Dateien überhaupt komprimiert werden sollen

und weiters wie stark sie komprimiert werden sollen:

Wenn Flächen mit geringen Helligkeitsunterschieden in der Kompression flach werden (die geringen Unterschiede verschwinden zu Gunsten einer größeren Fläche von einheitlicher Farbe) so kann man diese Bildteile vor der Kompression leicht verrauschen. Durch die dadurch erzeugten artifiziellen Gardienten, kann das Bild an dieser Stelle nicht mehr so stark vereinfacht werden.


9.3 Sicherheit

Kopierschutz: Man kann verhindern, dass die Skripts und Darsteller eines Films als MIAW von einem aufrufenden Film kopiert werden können [2, S.639]. Dazu genügt der Befehl

on startMovie
the windowList = []
end

Arbeitet man mit einem Startfile, das alle weiteren Dateien aufruft, so sollte man von einem zum nächsten Directorfilm ein Passwort übergeben, damit niemand den abhängigen Film selbst benützen kann. Der Film startet zwar, aber wenn er zu der Abfrage kommt und keinen passenden Wert in der Schlüsselvariablen hat, beendet er.

Freischalten mittels Registrierungscode: Dazu ist es nötig, Informationen, die eigentlich global verfügbar sein müssen zu tarnen, indem man sie z.B. in eine ObjectProperty eines Parentskripts steckt.

Über Verschlüsselungen siehe[5],S.347ff

Eine weitere Möglichkeit sollte im Unsichtbarmachen von Dateien auf dem Datenträger bestehen, was man allerdings nur auf einer tieferen Ebene der Plattform machen kann, also z.B. am Mac unter UNIX.

9.4 Startfiles

In heutigen Directorversionen (ab 2008) kann man mit einem Programm für eine bestimmte Plattform Versionen sowohl für Mac, als auch für Windows erzeugen, leider noch nicht für iOS und Android. Dabei ist zu beachten, dass auch allfällige Xtras von Drittherstellern für die gewünschten Plattformen vorliegen müssen.

Früher behalf man sich mit Startfiles. Ab Director 2004 konnte man mit einem Programm Projektorfiles für verschiedene Plattformen erzeugen. Bei früheren Versionen konnte man den Programmieraufwand dadurch hintan halten, dass man Startfiles des Typus

on exitFrame
_movie.go (1,"INTRO.DIR")
end

verwendete, die plattform- und versionsspezifisch kompiliert wurden, aber dann in der Lage waren .dxr-Filme aufzurufen, bei denen es egal war auf welcher Plattform sie erstellt worden waren, solange sie nicht neue, in Start.dir nicht vorkommende Xtras verwendeten. Es konnte also in der Regel ein Startfile, das z.B. mit Programmversion 7.0  erstellt wurde nicht ein File, das mit Version 8.0 erstellt wurde öffnen. Auch konnte ein auf dem Mac erstelltes Startfile nicht auf einer Windows Plattform laufen; wohl aber konnte es ein unter Windows erstelltes File auf einem Mac starten - vice versa konnte ein Windows Startfile ein auf Mac erstelltes File auf einem Windows-Rechner starten. Das aufgerufene File durfte unter Windows aber nicht auf einem shared Volumen stehen, weil der aufrufende Projektor sonst eventuell nach dem Shockwave Player verlangte und nicht Director als zuständige Anwendung suchte. Außerdem musste das Startfile schon alle benötigten Xtras aufrufen, da diese ja auch plattformspezifisch sind.

Verwendet man Startfiles um abhängige Filme aufzurufen, so ist es sinnvoll einen Schlüssel mit zu übergeben (also ein Passwort) damit nicht jemand den abhängigen Film starten und damit eine eventuell nötig gewesene Registrierung umgehen kann.

9.5 Icons

Dem Projektor ein eigenes Icon zuzuordnen ist am Macintosh leicht. Man sichert ein Bild, das als Icon verwendet werden soll in PS und stellt die Voreinstellungen von PS so ein, dass beim Sichern ein Thumnail-icon für das Bild erzeugt wird. Dieses öffnet man mit Get Info und kopiert das angewählte icon in die Zwischenablage. Anschließend Get Info des Projektors, generisches Macromedia-Icon anwählen und das andere aus der Zwischenablage hinkopieren.

Am PC ist das weitaus komplizierter. Man benötigt dazu im Normalfall ein eigenes Programm, wie etwa Microangelo

Seit Neuerem (2009) gibt es eine günstige Software, den iconworkshop mit einem 30 Tage Trial, der ein ziemlich einfaches Erstellen von eindrucksvollen Icons verspricht.


9.6 Exportieren

Man kann auf unterschiedliche Art und Weise aus Diector exportieren: Man kann 1 Bild exportieren, mehrere oder sogar einen Film erzeugen. Für Letzteres wählt man für den Export Alle Bilder oder einen Bildbereich und stellt im Dialogfenster unter Format auf QT-Film um. Unter Optionen kann man die weitere Einstellungen vornehmen. Leider gehen dabei aber etliche, unter Umständen wichtige Informationen verloren. So werden etwa die Bildrateninformationen im Tempokanal nicht gesichert. Ebensowenig funktioniert die currentTime Funktion, wodurch eine Soundsteuerung der Bildfolge unmöglich wird.

Abhilfe bringt der Screenrecorder Screenflow. Man nimmt einfach das von einem Projektor Gespielte damit auf, konvertiert in ein QT-movie oder lädt es gleich z.B. auf YouTube hoch. Natürlich gibt es dabei keine Interaktivität, aber es ermöglich die Erzeugung ansprechender Animationen (siehe Beispiel Intro.mov.zip)

Mittlerweile ist es auch möglich Directorfilme im iOS Betriebssystem zu veröffentlichen. Näher Angaben dazu findet man hier bei Adobe.

 

10. iOS

Seit Director 12 können auch iOS-Geräte gesteuert werden. Eine Übersicht über die Programmierung der dafür typischen zusätzlichen Funktionen findet sich hier.

 

11. Dreidimensionalität

um 3D-Szenen in Director zu importieren, muss man das Datenformat OBJ oder W3D wählen. Im 3D-Shockwave Fenster sind die Namen aller Objekte der Datei verzeichnet. Mit dem Xtra Havok kann man den Objekten zusätzlich physikalische Eigenschaften wie Elastizität und dergleichen verleihen. Weiteres in MacWelt 6/2001 S. 66ff. Seit der Version 11 braucht man das Xtra nicht mehr. die Physics Engine ist im Director seither integriert.

12. Shockwave und Flash

Bei Verwendung älterer Browser und Shockwaveplayer ist zu beachten, dass z.B. bei Verwendung von Safari 5 die Info zu Safari im Finder geöffnet und der 32-bit Modus angeklickt werden muss, weil man sonst mit 64 bit-untauglichen älteren Shockwaveplayern nichts sehen kann.

Die beiden angeführten Formate sind für die Verwendung animierter und eventuell auch interaktiver Inhalte auf Webseiten gedacht. Die Entscheidung darüber welches der beiden Formate man verwendet, ist eine Frage der unterschiedlichen Nischen. Die Stärke von Flash, einem eigenständigen und Director ähnlichen Programmes, liegt in seiner Sparsamkeit (weil vektororientiert), die von Shockwave, einer Sicherungsoption von Directordateien, in der größeren Vielfalt der Möglichkeiten. So können Shockwaves im Unterschied zu Flash Bitmaps verwenden und auch interaktiv im Netz 3-D verarbeiten). Auch im Videobereich bietet Flash nur rudimentäre Möglichkeiten, da es auf seinen eigenen Sparc Codec beschränkt ist, wohingegen gute Qualität (etwa 1024x768 bei 25fps) nur mit QT und Sörensen 2 Pro Codec in Director erzielt werden kann (5/2004). Flash-movies haben die Erweiterung.swf (small web file) [nicht verwechseln mit den Flash-files - die haben *.fla] und werden über Datei>Veröffentlichen gemacht, Shockwave hat .dcr und die Filme werden analog wie .dxr-Files erzeugt. Am einfachsten erzeugt man ein .dcr File mit Datei>Veröffentlichen, weil dann alle nötigen Files am richtigen Ort erzeugt werden. (Unter Xtras>Filme aktualisieren… wird das .dir File erst verschoben). Die fertigen .dcr werden in einem HTML-Editor wie z.B. Dreamweaver unter Einfügen>Medien importiert.

Wird ein Movie im Shockwaveformat gesichert, werden alle non-linked Bitmaps komprimiert gesichert. Mit Hilfe der Eigenschaft the movieImageCompression oder in den Veröffentlichungseinstellungen kann die Art und Weise vorgegeben werden, mit der komprimiert werden soll. Der Wert kann sein #standard oder #jpeg. Üblicherweise wird das in der Director Publish Settings dialog box eingerichtet. Man kann aber diese allgemeine Vorgabe für einzelne Bitmaps ändern, z.B. wenn man viele Zeichnungen und da und dort ein Foto hat, für das jpeg sinnvoller wäre. Man verwendet dann dazu die membereigenschaft .imageCompression. Z.B.:

member("Foto").imageCompression=#jpeg

Im Falle der jpeg-Kompression kann dann noch über die Eigenschaft .ImageQuality der Grad zwischen 0 und 100 eingestellt werden. Z.B.:

member("Foto").imageQuality=75

(analog dazu the movieImageQuality für den gesamten Film).


Natürlich kann man .swf und .dcr-Dateien auch als e-mails verschicken, wenn das empfangende Mail-Programm HTML versteht. Damit können im empfangenen Brief animierte Gifs, Filme, Links usw. sein.

Wird eine Shockwavedatei von einem Browser gesehen, so sucht sie nach dem Shockwave Player. Ist dieser nicht vorhanden, verlangt sie nach einem Download und führt auch auf die zuständige Seite von Adobe. Allerdings benötigt der Enduser Adminrechte, da er ja ein Programm installiert.

Besonders bei der Verwendung von Loops muss man beachten, dass ein Shockwave im Allgemeinen weniger CPU-Kapazität zur Verfügung hat als eine .dir-Datei. So kann es dann viel eher passieren, dass ein on mouseup event oder ähnliches nur sehr schwer erkannt wird. Abhilfe dagegen schafft einerseits die Reduktion von Arbeitsspeicherbedarf (kleine Darstellergrößen), was aber auch bei einem Directormovie berücksichtigt werden sollte, andrerseits aber ist es sinnvoll "on exitframe go to the frame"-Loops im Zeitkanal auf weniger als die 30bps default einzustellen, also z.B. auf 10bps.

Prinzipiell muss man bei Verwendung von Shockwaves bedenken, dass nicht alle Funktionen im Web verwendet werden können und dass sich manche schlecht eignen oder schlichtweg abnormal benehmen, insbesondere wenn man die Vielfalt an Endgeräten bedenkt, auf denen so ein Programm dann laufen können soll. Probleme treten speziell bei Buttons und bei Sounds auf.

Will man auch Filme, die in einem Browser gezeigt werden debuggen und braucht dazu ein Message-Fenster, so sollte man folgendes Skript einbauen:

on prepareMovie
  player.debugPlaybackEnabled = true
end

12.1 Flashkomponenten

In der Bibliothekspalette von Director gibt es nützliche vorgefertigte Flash-Komponenten: Will man eine Ganzzahleingabe mit schrittweiser Erhöhung oder Erniedrigung oder allgemeiner eine Eingabe vorbestimmter Ganzzahlwerte, so kann man sich des NumericStepper aus demKomponentenverzeichnis der Bibliothek bedienen.

NumericStepper

die Eigenschaften der Komponente (Maximum, Minimum, Stepwidth...) werden im PI eingestellt. Dabei stellt man sinnvollerweise auch den EventPassMode auf Always, der by default auch Never steht. Den eingestellten Wert, der in Sprite(me.spritenum).value zu finden ist sollte man nicht mit einem Mouseup Befehl auslesen (und schon gar nicht bei Mousedown, weil noch keine Änderung im Feld eingetreten sein muss). Der User kann nämlich den Wert auch direkt in den Stepper eintragen und dann gibt es kein mouseup-event. Sinnvoll wäre ein Auslesen etwa beim Verlassen des Frames. Änderungen werden auch nicht registriert, solange sich der Cursor noch hinter der Zahl befindet.

Über die Integration von Flash mit Director siehe Kap.11 in [7]

13. Steuerung externer Geräte

13.1 Über USB

Da man mit key sehr einfach einen bestimmten Tastendruck abfragen kann, z.B.:

on prepareMovie
the keyDownScript = "WelcheTaste"
end

on WelcheTaste
if (_key.key = "1") then.......
end

ist die externe Steuerung dann möglich, wenn man einen Schalter (Sensor oder dergl.) an eine USB-Tastatur statt der entsprechenden Taste anschließt. Das erfordert ein wenig Lötarbeit, ist aber dafür recht kostengünstig. Um so etwas als berührungsempfindliche Steuerung zu bauen, verwendet man kapazitive Näherungssensoren, die auf die Annäherung z.B. eines Fingers reagieren und und dann schalten.

13.2 Midi

XMidi Xtra erlaubte ein Interfacing mit Midigeräten für MacClassic und MacOSX, scheint aber in Director MX2004/OS10.4 (DE)-Kombination nicht mehr zu funktionieren. Ein möglicher Ersatz war SequenceXtra von Sibelius. Dieses Xtra erzeugte auch einen eigenen Eintrag in der Bibliothekspalette, allerdings wurde auch für dieses Xtra 2009 die Weiterentwicklung eingestellt.

Eine Möglichkeit MidiFileswenigstens abzuspielen besteht darin, sie in ein Quicktime zu verpacken. Man hat dann für das Midifile alle Steuerungsmöglichkeiten, die die QT-Steuerung bietet. Siehe lecture notes AV-Medien, Kap. 5.2

13.3 ComPort (veraltet)

Für die Ansteuerung des communication ports gibt es ein Xtra bei der Firma DirectXtras. Er funktioniert für serielle und parallele Anschlüsse. Für die Kommunikation mit USB muss man einen seriellen Adapter verwenden. Damit kann man beispielsweise Modems, Kartenleser, mini discs, Instabussysteme, andere Computer usw. ansprechen.

14. Externe Anwendungen

14.1 MIAW (Movie in a window)

 Die einfachste Form einer externen Anwendung ist das Movie in a Window. Dabei besteht die externe Anwendung wieder aus einem Directorfilm. Es ist möglich in einem Directorfilm mehrere Fenster zusätzlicher Directormovies zu öffnen und zu verwalten (z.B. um temporär Hilfswerkzeuge zur Verfügung zu stellen). Die Namen der Fenster stehen in einer Liste, der windowlist. z.B. bei einem Hauptfilm ("stage") und einem Film Namens "Test"

put the windowlist
-- [(window "stage"), (window "Test")]

14.1.1 Fenstereigenschaften

the desktopRectlist[n] gibt die Größe des Monitorfensters des Monitors n an. (Üblicherweise ist n = 1, wenn nur ein Monitor dran hängt).
(the stage).rect gibt das rect der Koordinaten der Stage bezogen auf das Monitorfenster an.
(the stage).drawRect gibt das rect der Koordinaten der Stage bezogen auf das Fenster in dem sich die Stage befindet an.

Das Aussehen eines Fensters zu gestalten gelingt über die Liste appearanceOptions. Will man sie für ein bestimmtes Fenster sehen, so schreibt man

put(window("Fenstername").appearanceOptions) oder sinngemäß für das Fenster der Bühne:
put(the stage.appearanceOptions)

Mit der Option Mask kann man dem Fenster einen 1-Bit Darsteller als Maske zuordnen, etwa durch

window("movie2").appearanceOptions.mask = member("BitMapMaskenDarsteller")
(the stage).appearanceOptions.mask = member("BitMapMaskenDarsteller")

Eine Übersicht über die definierbaren Eigenschaften findet man in der Hilfe von Director 11 unter Contents > Director-Skriptreferenz > Eigenschaften > appearanceOptions.

14.1.2 Erzeugen eines MIAW

Zunächst muss im aufrufenden Film das Fenster des aufzurufenden Films deklariert werden:

window().new ("NameAufzurufenderFilm")

dann kann man es öffnen

open window ("NameAufzurufenderFilm")

Globale Variable des Stammfilms sind in allen MIAWs verfügbar.
Ebenso kann auf Eigenschaften oder sogar Prozeduren eines aufgerufenen movies zugegriffen werden. Z.B.:

window("Film_xyz").movie.member(1).name = "geänderter_Name"
oder
window("Film_xyz").movie.ProzedurVonFilm_xyz()

Ein spezieller Fall ist der, bei dem statt "Film_xyz" der Begriff "stage" steht. Dann wird nämlich das Fenster des Hauptfilms angesprochen.

(download movie1+2)

Die Position und Größe des Fensters setzt man in den movie properties size und location im PI festsetzen . In Lingo geht es mit

window("Sample").rect = rect(10,10,500,200)

Die in der Hilfe angegebene Form

window("Sample").rect = [0, 0, 200, 300]

funktioniert nicht, da hier ein #rect mit einer #list gleichgesetzt werden soll (siehe rect). Die Schreibweise window.rect "Sample", wie sie in der Director-Hilfe angegeben wird, ist darüberhinaus laut Compiler syntaktisch falsch.

ACHTUNG: Wenn eine Window-Eigenschaft angegeben wird, darf zwischen window und ("... kein Zwischenraum stehen!

mit Hilfe der Stage-Koordinaten ist es möglich, das Fenster des Child Movies relativ zum Stammfilm auszurichten. Z. B.

window("Sample").rect = rect(the StageLeft+10, the StageRight-170, the StageTop+10, the Stagebottom-130)

Wenn das Movie das Fenster nicht mehr benötigt, kann es wieder geschlossen werden:

window("movieName").close()

oder überhaupt zerstört werden mit

window("movieName").forget()

der Unterschied besteht darin, dass sich das Stammprogramm nach close die Größe und Position des Child Movie-Fensters gemerkt hat. Bei forget öffnet das Child Movie in seiner ursprünglichen Größe und Position, so wie diese beim Erstellen ursprünglich festgelegt worden waren.

Der Fenstername muss nicht mit dem Filmnamen identisch sein. würde z. B.:

window("laufen").open()

den Film "laufen" öffnen, so hätte die gleiche Wirkung:

window("xy").filename="laufen"
window("xy").open()

Im Fensterbalken des Child Movies steht dann statt "laufen" natürlich "xy".


Wird nichts Näheres für Windowtype spezifiziert, so wird für windowtype die Eigenschaft #document angenommen. Weitere mögliche Werte sind

sie werden gesetzt mit

window("Fenstername").type = #document

Man sollte diese Eigenschaft schon vor dem Öffnen des Fensters setzen, am besten am Filmbeginn um Redraw-verzögerungen zu vermeiden.

14.1.3 Kommunikation zwischen den Fenstern

Ein Movie kann mit einem anderen Fenster mit Hilfe des tell - Befehls kommunizieren.

Entweder in der Form

tell whichWindow to statement(s)
z.B.: tell window "Simulation" to go frame "Save"

oder

tell whichWindow
  statement(s)
end

Das Fensterobjekt muss entweder mit seinem vollen Pfadnamen identifiziert sein oder mit seiner Nummer in der windowList. Verwendet man the windowList, benutzt man getAt(the windowList, windowNum), wobei windowNum eine Variable ist, die die Nummer des Fensters in der Liste anzeigt. Da aber das Öffnen und Schließen von Fenstern ihre Position in der windowlist verändern kann, ist diese Methode nur mit Vorsicht zu genießen.

global childMovie

tell window childMovie -- in childmovie liegt der Pfadname
  _movie.go ("Intro")
  the stageColor = 100
  sprite(4).member = member "Diana Ross"
  updateStage
end tell


Ruft eine Message einen Handler, so kann ein vom handler errechneter Wert in den global result properties gefunden werden, nachdem der Handler den Wert errechnet hat. Im folgenden Beispiel wird dem Child-Movie Fenster die Message calcBalance geschickt und anschließend das Resultat retourniert:

global childMovie

tell window childMovie to calcBalance
-- a handler name
myBalance = result()
-- return value from calcBalance handler

Im speziellen Fall, dass ein Resultat an das Fenster des Hauptfilms geschickt wird, verwendet man die stage -system property:

tell the stage to go frame "Main Menu"

Ruft man einen Handler in einem anderen Movie auf, so ist es wichtig, dass nicht ein anderer Handler mit dem gleichen Namen im gleichen Skript des lokalen Movies existiert, da sonst das lokale Skript aufgerufen wird. Diese Einschränkung bezieht sich nur auf Handler im selben Skript, in dem sich der tell-Befehl befindet.

Will man den Informationsfluss vom Stammfilm zum MIAW abschalten (z. B. weil das MIAW die ganze Prozessorleistung erfordert, oder weil erst dort geklickt werden muss, bevor man weitermachen kann, wie es bei Alertdialogfenstern der Fall ist), so kann man the modal des Fensters auf TRUE setzen.

window("sample").modal=TRUE

Ab Director 11.5 bietet sich statt des tell-Befehls die Verwendung der Eigenschaft movie eines Fensters an. So kann z.B. das Fenster eines MIAW mit

window("stage").movie.aktion()

einen Handler "aktion()" im Hauptfilm ausführen. Ein Zugriff auf ein member, z.B. um seinen Namen zu ändern, ginge mit

window("FensterImAnderenFilm").movie.member["Geraeusch"].name="Glocke"

14.1.4 Xtra-MIAW

Man kann während des Authorings ein fertiges Director Movie in einem anderen Movie als MIAW öffnen, wenn man es in den Xtras-Ordner gibt und dann im Xtras-Menü öffnet. So kann man sich z.B. Hilfswerkzeuge basteln.

14.2 Xtras

Xtras sind Programmkomponenten, die die Funktionalität von Directorprojektoren und Shockwave Movies erweitern. Manche Xtras werden nur während der Arbeit mit Director verwendet, während andere zur Laufzeit benötigt werden. Xtras sind Plattform-spezifisch. Windows spezifische Xtras haben die Erweiterung .X32. Mac Xtras benötigen keine Erweiterung.

Solche Xtras werden von Drittherstellern (so kann man unter anderem angeblich auch geeignete Photoshop Plug-Ins verwenden [6, S. 70]), aber auch Macromedia selbst hergestellt. Man bindet sie dadurch in das Programm ein, indem man sie in einen Ordner Namens Xtras legt, der sich im Ordner mit der Anwendung Director befinden muss. Ein Xtra kann bis zu fünf Ordner tief in den Xtras-Ordner gelegt werden.
Spezielle Scripting Xtras kann man mit dem openXlib Befehl beim, Start von Director öffnen und muss es beim Beenden mittels closeXlib wieder schließen.
Neben den bereits als Default geladenen Xtras kann man weitere dazuladen, indem man sie in MODIFY>MOVIE>XTRAS hinzufügt. Auf die gleiche Art und Weise kann man auch checken, ob ein bestimmtes Xtra vorhanden ist (z. B. wichtig, wenn man QT-Filme verwendet - siehe oben). Beim Laden und Kompilieren (also dem Erstellen des Projektors oder Shockwavefilms) werden diese Codeteile dann mit eingebunden.

Um Xtras von Drittherstellern einzusetzen, kann man sie über das Menü Xtras aufrufen, wo allerdings die meisten nicht zu finden sind. Man findet sie hingegen im Xtras-Tool des Skriptfensters:

Für Musiker wichtig war das Xtra XMidi, das ein Anbinden von Midi-in und -out an Director ermöglichte. Leider wird es seit einigen Jahren nicht mehr weiter gewartet. Der Autor muss, wenn er es verwenden will, von Fall zu Fall probieren, ob es in der gewünschten Anwendungsart noch funktioniert. Eine Übersicht über verfügbare Xtras findet man bei Adobe. Einen Ersatz findet man im SequenceXtra der Firma Sibelius, das jedoch in der momentan gültigen Version 1.9.4 nur bis Director 10 funktioniert (zumindest am Mac).

Gelegentlich, besonders nach einem Versionswechsel von Director kann es vorkommen, dass ein Xtra nicht mehr funktioniert. Beispielsweise wenn es im Authormode zwar seinen Dienst tut, beim Kompilieren und Laden (also beim Erstellen des Projektors) aber nicht mehr gefunden wird. In diesem Fall kann man unter Umständen dadurch Abhilfe schaffen, dass man in MODIFY>MOVIE>XTRAS erst alle Xtras hinauswirft und dann diejenigen, die mit der verwendeten Directorversion kompatibel sind wieder lädt. Eine andere Möglichkeit der Fehlerbehebung besteht darin, das fehlende Xtra in einen Ordner mit der Bezeichnung "Xtra" zu stecken und diesen Ordner auf die selbe Ebene wie den abzuspielenden Film zu legen.

Die Anzahl der verfügbaren Xtras erhält man in Lingo mit put the number of xtras

Die Liste der verfügbaren Xtras kann man mit put the xtralist abfragen.

Das Interface eines bestimmten Xtras liefert die interface() Funktion. Sie funktioniert allerdings nicht mehr als put interface(xtra "XmidiMX"), sondern nur in der Punktschreibweise,also beispielsweise put Xtra("QuickTimeSupport").interface(). Man erhält dann eine Beschreibung des Xtras und eine Liste seiner Methoden, sofern Solches vom Autor des Xtras implementiert worden war.

Über MIAWs im Xtra-Menü eines Films siehe weiter Kap. 12.1.4

Wenn man mit mehreren abhängigen Filmen arbeitet, so muss man bereits im ersten Film alle Xtras laden, die man in späteren, abhängigen Filmen braucht. Das Laden passiert dann nicht von selbst, wenn gewisse Funktionen (wie z.B. das Verwenden eines Flash-Elements) erst in späteren Filmen verwendet werden. Also im ersten Film unter Modifizieren>Film>Xtras... vorausladen. Mitunter, wenn man das entsprechende Xtra nicht findet, kann man einfach den Darsteller (Vektor, Flash, usw.), der erst in einem späteren Film vorkommt schon im aufrufenden Film verwenden (z.B. außerhalb des Bühnenfensterbereichs), damit Director gezwungen wird, das richtige Xtra zu suchen.

14.3 Starten fremder Applikationen

Um eine Datei Storyboards mit dem Programm Textedit, das sich im Ordner Applications auf der Festplatte mit dem Namen HD befindet zu öffnen schreibt man:

open "Storyboards" with "HD:Applications:TextEdit"

Es kann aber auch nur ein Anwendungsprogramm ohne spezielle zugehörige Datei geöffnet werden. Befindet sich diese im gleichen Ordner wie der Film, hieße es schlicht:

open "Safari"

15. Anhang:

15. CD-ROM/DVD Fertigung

Denkt man an einen weitreichenden Verkauf eines Projekts auf CD oder DVD nicht nur am Mac - oder auch noch in verschiedenen Sprachversionen, so empfiehlt es sich wegen des Wusts an Versionen und Kombinationsmöglichkeiten in der Windowswelt, möglichst auf externe Programmelemente wie Xtras von Drittherstellern zu verzichten um allfälligen Kompatibilitätsproblemen aus dem Weg zu gehen.

Etliche Firmen bieten von der Leer-CD bis zum Aufbewahrungskasten ein Fertigungsprogramm, wie z.B. graphicdisc

Weitere Beispiele

Tontaubenschießen; Beispiel für Counter, programmiertes Bewegen von Sprites
Dreiklängeerkennen; Beispiel für das Ziehen von Sprites

16. Verwendete Abkürzungen

AVI Filmformat, vornehmlich unter Windows verwendet
DTS DirectToStage (QT member Eigenschaft)
DV Digitalvideo
MIAW Movie in a window
OOP Objektorientiertes Programmieren
PEH Primary Event Handler
PI Property Inspector
Plist Property list, Eigenschaftsliste
PS Photoshop
QT QuickTime
s/w schwarz-weiß

17 Literatur

[1] Dean Utian et al.: Foundation Director 8.5; friendsofed 2001, ISBN 1-903450-38-1
[2] Gerd Gillmaier und Joachim Gola: Director 7 Workshop, Addison-Wesley, 1999
[3] Gary Rosenzweig: The Director 6 Book, Ventana Communications Group, 1997
[4] Tobias Hauser und Christian Wenz: Das Einsteigerseminar, Director 8.5; verlag moderne industrie Buch AG, Landsberg 2001
[5] Martin Kloss: Lingo objektorientiert, 2. Auflage 2002, Galileo Press GmbH, Bonn, ISBN 3-89842-219-4
[6] Jason Roberts: Director 6, (Addison-Wesley 1998, 1. Aufl.)
[7] Nik Lever: Director MX2004 Games (Game development with director), Elsevier 2005 ISBN 0-240-51949-3
James Newton: Director Shockwave Studio Developer's Guide, McGraw-Hill/Osborne 2002

18. Links

Code (unprotected movies) von James Newton
LingoPark Forum (Beiträge seit 1997 bis heute)
Lingo Tutorials (2008)
Adobe Director-Produktseite
Ressourcen, Hilfsprogramme, Xtras
Weitere Tipps zu Director
http://www.adobe.com/support/director/downloads.html

Eine Liste von mit Director erstellten CD-ROMs

--ENDE--

------------

ye ol' countas

bluenet: Kostenlose Counter -- BlueNetDesign