Changes between Version 18 and Version 19 of squeak_faq
- Timestamp:
- 10/16/2013 11:59:30 AM (11 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
squeak_faq
v18 v19 40 40 === Wie werden Grafiken im Image verwendet? === 41 41 42 Der Dreh und Angelpunkt ist hier die Klasse Form. Die Basis von Form ist die "Squeak Canvas", eine Bitmap, die Bilder enthält, oder auf der gezeichnet werden kann. Diese Objekte können dann in !ImageMorphs verwendet werden. Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form. Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt. Ähnliches findet sich auch auf den Klassenseiten von den Klassen PNGReadWriter, JPEGReadWriter,GIFReadWriter und weitere für spezielle Bildformate.43 44 Mit Klassen wie !FileDirectory oder !FileUrl kann im Dateisystem navigiert werden. Hierbei gilt es auch zu bedenken, dass die "Pathdelimiter" der Betriebssysteme unterschiedlich sein können (/ oder \).42 Der Dreh und Angelpunkt ist hier die Klasse `Form`. Die Basis von `Form` ist die "Squeak Canvas", eine Bitmap, die Bilder enthält, oder auf der gezeichnet werden kann. Diese Objekte können dann in !ImageMorphs verwendet werden. Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form. Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt. Ähnliches findet sich auch auf den Klassenseiten von den Klassen `PNGReadWriter`, `JPEGReadWriter`, `GIFReadWriter und weitere für spezielle Bildformate. 43 44 Mit Klassen wie `FileDirectory` oder `FileUrl` kann im Dateisystem navigiert werden. Hierbei gilt es auch zu bedenken, dass die Trennzeichen in den Pfaden je nach Betriebssystem unterscheidlich sind: "\" bei Windows, Linux und OSX benutzen "/"). Für Plattformunabhängigkeit könnt ihr `FileDirectory>>slash` oder `FileDirectory class>>slash` benutzen (siehe [#platform-path-separator Plattformunabhängige Dateizugriffe]) 45 45 46 46 Bilder können auch im Image gespeichert werden. Das hat den Vorteil, das ihr die Bilder über Monticello verwalten könnt und so alle Teammitglieder über das Repository die aktuellen Bilder bekommen. 47 D er große Nachteil ist, dass ihr die Größe des Images aufbläht. Wenn trotz ihr trotz dieses Nachteils Bilder in Methoden und damit im Image speichern wollt, könnt ihr Array-Repräsentationen gewinnen. Dazu laded ihr das Bild, wie oben beschrieben, zuerst in eine Form und aus dieser erzeugt ihr dann das Array (siehe. z.B. `Form>>storeOn`).48 49 Es gibt in Squeak den !ImageReadWriter als abstrakte Klasse und dazu verschiedene Implementierungen für z.B. BMP und PNG (PNGReadWriter, BMPReadWriter). Auf Klassenseite von !ImageReadWriter findet sich dann auch `ImageWriter `class>>formFromFileNamed`:`, was in der konkreten Implementierung genutzt werden kann.47 Dazu speichert ihr die Bilder in Methoden, die Array-Repräsentationen der Grafiken zurückgeben. Dazu laded ihr das Bild, wie oben beschrieben, zuerst in eine Form und aus dieser erzeugt ihr dann das Array (siehe. z.B. `Form>>storeOn`). 48 49 Es gibt in Squeak den `ImageReadWriter` als abstrakte Klasse und dazu verschiedene Implementierungen für z.B. BMP und PNG (`PNGReadWriter`, `BMPReadWriter`). Auf Klassenseite von `ImageReadWriter` findet sich dann auch `ImageWriter class>>formFromFileNamed:`, was in der konkreten Implementierung genutzt werden kann. 50 50 51 51 52 52 === Welche Dateiformate für Bilder sind für Squeak geeignet? === 53 53 54 Benutzt hier am besten PNG, JPG oder BMP. Zum Einlesen bietet sich dann beispielweise die !ReadWriter Klassen an. Übrigens können Formsauch mit Transparenz umgehen.54 Benutzt hier am besten PNG, JPG oder BMP. Zum Einlesen bietet sich dann beispielweise die `ReadWriter` Klassen an. Übrigens können Exemplare der Klasse `Form` auch mit Transparenz umgehen. 55 55 56 56 57 57 === Können !ImageMorph bzw. deren enthaltene Form mit Alphatranparenz umgehen? Wie können ganze Morphs ausgeblendet werden? === 58 58 59 Verwendet die Methode hide, um einen Morph sofort ohne Fade Out zu verstecken. Denkt bitte daran, dass ausgeblendete Morphs dennoch im Speicher verbleiben. Eine Squeak-Methoden-Suche nach "alpha" (eine Nachricht, die wahrscheinlich Konstrukte haben wird, bei denen man eine Transparenz einstellen kann) liefert eine Klasse namens: !AnimAlphaBlendingCanvas.59 Verwendet die Methode `Morph>>hide`, um einen Morph sofort ohne fade out zu verstecken. Denkt bitte daran, dass ausgeblendete Morphs dennoch im Speicher verbleiben. Eine Squeak-Methoden-Suche nach `alpha` oder `alpha:` (eine Nachricht, die wahrscheinlich Konstrukte haben wird, bei denen man eine Transparenz einstellen kann) liefert eine Klasse namens: `AnimAlphaBlendingCanvas`. 60 60 61 61 === Wie schaffe ich es, dass ein Morph nicht mehr verschiebbar ist? === … … 66 66 === Unser Spiel basiert auf Stepping und ruckelt!?! Was können wir tun? === 67 67 68 Das Stepping Model von Morphic ist relativ einfach und basiert auf einem Prozess, welcher alle stepping Methoden ausführt, wenn ihre stepTime abgelaufen ist. Im Umkehrschluss heißt das aber auch je mehr #step Methoden, je häufiger aufgerufen werden, desto mehr Zeit wird zwischen einzelnen Schritten benötigt (da mehr berechnet wird). Die #stepTime gibt dabei einen Wunschwert an, nach dem die #step Methode wieder aufgerufen werden soll. Nun kann es aber sein, dass die step Methoden soviel zu tun haben (oder andere Prozesse), dass die Überprüfung nur alle 50 ms ausgeführt wird und somit kann eine Zeit von 33 ms nicht garantiert werden. Allerdings wird durch die beschriebene Bewegung eine explizite #runStepMethods Message an die Welt gesendet, welcher die Abarbeitung aller #steps triggered. Das heißt der UI Prozess löst bei seiner Reaktivierung eine neu Berechnung aus. 69 70 Also kommen wir zu möglichen Lösungen: 71 72 In Preferences gibt es eine Option "higher performance" diese sorgt für ein häufigeres updaten des UI Prozesses, dass könnte ggf. helfen. 73 74 75 76 Anstatt häufig kleine Schritte auszuführen, kann ggf. eine größere Schrittweite die Animation flüssiger wirken lassen. 77 78 79 Eine richtige Game Loop implementieren (Design Pattern für Spiele), welche abhängig von der verstrichenen Zeit die Animation berechnet und somit immer gewährleistet, dass unabhängig von der Performance die Animation zu einem Zeitpunkt überall gleich weit ist (ruckelnd oder nicht). Dann würdet ihr komplett auf das Stepping Protokoll verzichten. 68 ==== Wieso stepping zu langsam sein kann ==== 69 70 Das Stepping Model von Morphic ist relativ einfach und basiert auf einem Prozess, welcher alle stepping Methoden ausführt, wenn ihre `Morph>>stepTime` abgelaufen ist. Im Umkehrschluss heißt das aber auch je mehr `Morph>>step` Methoden je häufiger aufgerufen werden, desto mehr Zeit wird zwischen einzelnen Schritten benötigt (da mehr berechnet wird). Die `#stepTime` gibt dabei einen Wunschwert an, nach dem die `#step` Methode wieder aufgerufen werden soll. Nun kann es aber sein, dass die `#step` Methoden soviel zu tun haben (oder andere Prozesse), dass die Überprüfung nur alle 50 ms ausgeführt wird und somit kann eine Zeit von 33 ms nicht garantiert werden. Allerdings wird durch die beschriebene Bewegung eine explizite `#runStepMethods Message an die Welt gesendet, welcher die Abarbeitung aller steps auslöst. Das heißt der UI Prozess löst bei seiner Reaktivierung eine neu Berechnung aus. 71 72 ==== Lösungen ==== 73 74 1. In Preferences gibt es eine Option "higher performance" diese sorgt für ein häufigeres updaten des UI Prozesses, dass könnte ggf. helfen. 75 76 2. Anstatt häufig kleine Schritte auszuführen, kann ggf. eine größere Schrittweite die Animation flüssiger wirken lassen. 77 78 3. Die wahrscheinlich schnellste Alternative ist, eine Game Loop zu implementieren (Design Pattern für Spiele), welche abhängig von der verstrichenen Zeit die Animation berechnet und somit immer gewährleistet, dass unabhängig von der Performance die Animation zu einem Zeitpunkt überall gleich weit ist (ruckelnd oder nicht). Dann würdet ihr komplett auf das Stepping Protokoll verzichten. 80 79 81 80 … … 132 131 Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form. 133 132 Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt. 134 Ähnliches findet sich auch auf den Klassenseiten von den Klassen PNGReadWriter, JPEGReadWriter, GIFReadWriterund weitere für spezielle Bildformate.133 Ähnliches findet sich auch auf den Klassenseiten von den Klassen `PNGReadWriter`, `JPEGReadWriter`, `GIFReadWriter` und weitere für spezielle Bildformate. 135 134 136 135 137 136 Mit Klassen wie !FileDirectory oder !FileUrl kann im Dateisystem navigiert werden. 138 137 Hierbei gilt es auch zu bedenken, dass die "Pathdelimiter" der Betriebssysteme unterschiedlich 139 sein können (/ oder \, ). Für Plattformunab nhängigkeit könnt ihr `GRPlatform>>pathSeparator`.138 sein können (/ oder \, ). Für Plattformunabhängigkeit könnt ihr `GRPlatform>>pathSeparator` benutzen. 140 139 141 140 … … 146 145 147 146 148 Das Speichern von Bildern im "Quellcode"/Image hat den einfachen Vorteil, dass ihr sie mit allen Teammitgliedern mit Hilfe des Monticello Source Code Repository teilen könnt. Bei externen Dateien muss leider ein anderer Weg (z.B. SVN) genutzt werden. Dennoch würden wir externe Dateien immer bevorzugen (welche nur bei Bedarf geladen und im Image gecached werden), da sie das Image klein halten. Unser Plan gegen Ende des Semester ist es alle Projekte in ein Image zu laden, daher ist es auch hier sinnvoll eure Resourcen extern im Dateisystem zu halten. Denkt bitte auch daran einen Unterordner für euer Projekt innerhalb des Squeak Verzeichnisses zu nutzen.147 Das Speichern von Bildern im "Quellcode"/Image hat den einfachen Vorteil, dass ihr sie mit allen Teammitgliedern mit Hilfe des Monticello Source Code Repository teilen könnt. Bei externen Dateien muss leider ein anderer Weg (z.B. Dropbox, Git, SVN) genutzt werden. Dennoch würden wir externe Dateien immer bevorzugen (welche nur bei Bedarf geladen und im Image gecached werden), da sie das Image klein halten. Unser Plan gegen Ende des Semester ist es alle Projekte in ein Image zu laden, daher ist es auch hier sinnvoll eure Resourcen extern im Dateisystem zu halten. Denkt bitte auch daran einen Unterordner für euer Projekt innerhalb des Squeak Verzeichnisses zu nutzen. 149 148 150 149 … … 170 169 === Wie kann ich das mouseDown-Event an den Owner weiterleiten? === 171 170 172 Falls der Owner alle Mouse-Down-Events seiner Kinder abfangen soll, ist #mouseDownPriority die bessere Lösung. Bei #rejectsEvent:müsste jeder mögliche Submorph-Typ modifiziert werden. Dies würde Code-Duplikation bedeuten.171 Falls der Owner alle Mouse-Down-Events seiner Kinder abfangen soll, ist `#mouseDownPriority die bessere Lösung. Bei `#rejectsEvent:` müsste jeder mögliche Submorph-Typ modifiziert werden. Dies würde Code-Duplikation bedeuten. 173 172 174 173 … … 255 254 256 255 257 2.) Du kannst in Squeak jeder Klasse #allInstances senden und bekommst dann eine Liste, die alle Objekte der Klasse enthält. An diese Liste können dann mit dem Collection Protocol (z.B. #do:) Nachrichten an alle Objekte geschickt werden. Somit kannst du die Objekte bearbeiten oder mittels stopStepping zum Stillstand bringen.256 2.) Du kannst in Squeak jeder Klasse `#allInstances` senden und bekommst dann eine Liste, die alle Objekte der Klasse enthält. An diese Liste können dann mit dem Collection Protocol (z.B. `#do:`) Nachrichten an alle Objekte geschickt werden. Somit kannst du die Objekte bearbeiten oder mittels stopStepping zum Stillstand bringen. 258 257 259 258 … … 270 269 === Wie bindet man das eigene Projekt in den Objects Explorer ein? === 271 270 272 1.) !ObjectsTool erstellt die angezeigten Kategorien in dem es einfach alle Morphklassen nach einem bestimmten Selektor durchsucht und nur diese hinzufügt. Man benötigt also einen Morph und zwar den Morph, der das Spiel darstellt (z.B. !BlyPacmanApp).273 2.) Auf der Klassenseite des Morphs wird eine Kategorie "parts bin" benötigt und in dieser eine Methode #descriptionForPartsBin. Das ist der Hook für !ObjectsTool.271 1.) `ObjectsTool` erstellt die angezeigten Kategorien in dem es einfach alle Morphklassen nach einem bestimmten Selektor durchsucht und nur diese hinzufügt. Man benötigt also einen Morph und zwar den Morph, der das Spiel darstellt (z.B. `BlyPacmanApp`). 272 2.) Auf der Klassenseite des Morphs wird eine Kategorie "parts bin" benötigt und in dieser eine Methode `#descriptionForPartsBin. Das ist der Hook für `ObjectsToo`. 274 273 275 274 {{{ … … 282 281 }}} 283 282 284 Dabei kann mit einem vierten Parameter auch ein Beispielbild angegeben werden (siehe z.B. AudioChatGUIdescriptionForPartsBin, self ... sampleImageForm:). Ansonsten wird ein kleines Icon automatisch erstellt.283 Dabei kann mit einem vierten Parameter auch ein Beispielbild angegeben werden (siehe z.B. `AudioChatGUIdescriptionForPartsBin`, self ... sampleImageForm:). Ansonsten wird ein kleines Icon automatisch erstellt. 285 284 3.) Damit sollte der Morph in dem !ObjectsTool erscheinen. Allerdings kann es sein, dass der Morph nicht richtig initialisiert wird (z.B. das Extent nicht stimmt). 286 285 287 Wenn man ein Objekt aus dem !ObjectsTool zieht, wird der jeweiligen Klasse #newStandAloneals Nachricht gesendet. Die Methode dazu sieht wie folgt aus.286 Wenn man ein Objekt aus dem !ObjectsTool zieht, wird der jeweiligen Klasse `#newStandAlone` als Nachricht gesendet. Die Methode dazu sieht wie folgt aus. 288 287 {{{ 289 288 newStandAlone … … 292 291 }}} 293 292 294 Während Morph #initializeToStandAlone einfach auf #initialize zurückführt, überschreiben andere Morphs die Methode (z.B. !PasteUpMorph) und setzen z.B. die Größe. Falls das der Fall ist, kann man die #initializeToStandAloneeinfach überschreiben:293 Während Morph `#initializeToStandAlone` einfach auf `#initialize` zurückführt, überschreiben andere Morphs die Methode (z.B. !PasteUpMorph) und setzen z.B. die Größe. Falls das der Fall ist, kann man die `#initializeToStandAlone` einfach überschreiben: 295 294 296 295 {{{ … … 327 326 328 327 329 === Wie werden plattformunabhängige Datei-Zugriffe realisiert? === 330 331 Unabhängige Trennzeichen bekommt ihr mit den Methoden: #separator, #pathSeparator, #separatorString.328 === Wie werden plattformunabhängige Datei-Zugriffe realisiert? === #platform-path-separator 329 330 Unabhängige Trennzeichen bekommt ihr mit den Methoden: `#separator`, `#pathSeparator`, `#separatorString`. 332 331 Ebenso kapselt die Klasse URI alle notwendigen Plattform-Mappings. 333 332 … … 335 334 === Gibt es in Squeak so etwas wie eine !FileDialog Klasse? === 336 335 337 Helfen kann euch hier die Klasse !FileList.336 Helfen kann euch hier die Klasse `FileList`. 338 337 339 338 … … 346 345 === Objekte als Text klassenseitig abspeichern === 347 346 348 Zum Serialisieren von Objekten gibt es in Squeak die Methoden #storeOn: bzw #readFrom:347 Zum Serialisieren von Objekten gibt es in Squeak die Methoden `#storeOn:` bzw `#readFrom:` 349 348 350 349 Hier der Code dazu: … … 388 387 Die WAFileLibrary ist nicht dafür gedacht als eine langfristige Lösung zu fungieren. Sie ist eine einfache Art Dateien bereitzustellen. Aber sowohl durch ihre Ablage der Daten im Image als auch der vergleichsweise langsamen Zugriffszeit auf diese Daten sollte sie immer nur temporär benutzt werden. Sie hat aber auch Vorteile, wie z.B. den leichten Austauschen von Dateien über Monticello. Bessere Lösung um auf statische Dateien zuzugreifen findet ihr ebenso im Tutorial (selbes Kapitel weiter unten). 389 388 390 Bei deinem Beispiel würde an der Klasse AClassName die Methode #fooBaraufgerufen werden. Hier dispatcht Seaside ein wenig mit Meta-Programming. Aber dieses Schema ist konstant und kann über den File Upload Dialog soweit umgangen werden, dass ihr die Klasse gar nicht anfassen braucht. Zum Hochladen von Dateien habe ich bereits in einer vergangenen Mail auf der Liste etwas geschrieben, da hier das Tutorial nicht mehr aktuell ist.389 Bei deinem Beispiel würde an der Klasse `AClassName` die Methode `#fooBar` aufgerufen werden. Hier dispatcht Seaside ein wenig mit Meta-Programming. Aber dieses Schema ist konstant und kann über den File Upload Dialog soweit umgangen werden, dass ihr die Klasse gar nicht anfassen braucht. Zum Hochladen von Dateien habe ich bereits in einer vergangenen Mail auf der Liste etwas geschrieben, da hier das Tutorial nicht mehr aktuell ist. 391 390 392 391 Durch die begrenzten Möglichkeiten der WAFileLibrary sind Unterordner so weit ich weiß nicht möglich aber ggf. wurde das in der neuen Seaside Version auch geändert. … … 567 566 Das kommt sehr auf eure Netzwerkimplementierung an. Nutz ihr ein Standardprotokoll, so sollte die verwendete Bibliothek im Allgemeinen auch entsprechende Methoden bereitstellen. Häufig sind diese transparent, so dass die Methoden automatisch gerufen werden, sobald ein neuer Request eintrifft. Um Beispiele dafür zu sehen, schaut euch einmal im Image den WAListener an, welcher den Webserver für Seaside implementiert. Dort wird auch gezeigt wie man Prozesse "forked" um mehrere Requests gleichzeitig zu behandeln. 568 567 569 Von dem Ansatz die ganze Sache in Morphic und dessen #step Methode abzubilden, raten wir schlichtweg ab. Der Grund: die #step Methode ist nur scheinbar parallelisiert und sollte eine Methodeauf `SocketStream>>isDataAvailable` warten, steht das ganze System. Ihr müsste also auf jeden Fall mit mehreren Prozessen arbeiten. Dafür verwendet ihr wie gesagt die `fork`-methode.568 Von dem Ansatz die ganze Sache in Morphic und dessen `#step` Methode abzubilden, raten wir schlichtweg ab. Der Grund: die `#step` Methode läuft nicht parallel. Sollte eine Implementierung von `#step` auf `SocketStream>>isDataAvailable` warten, steht das ganze System. Ihr müsste also auf jeden Fall mit mehreren Prozessen arbeiten. Dafür verwendet ihr wie gesagt die `fork`-methode. 570 569 571 570 Um das Warten zu realisieren, schaut euch die Klasse Delay an. … … 588 587 Das Cryptography package sollte alle notwendigen Funktionen liefern. 589 588 Dort habt ihr eine MD5 Klasse. Folgt dem Beispiel in der Methode 590 #hashStream:. Aber Achtung, [http://de.wikipedia.org/wiki/MD5 MD5] ist sehr unsicher, da sehr leicht Kollisionen gefunden werden können.589 `#hashStream:`. Aber Achtung, [http://de.wikipedia.org/wiki/MD5 MD5] ist sehr unsicher, da sehr leicht Kollisionen gefunden werden können. 591 590 Seaside nutzt deswegen üblicherweise den SHA Algorithmus. Diesen könnt ihr bereits in eurem Image finden unter der Klasse `SecureHashAlgorithm`. Dort schaut euch einfach die Methoden unter dem 'public' Protokoll an. 592 591 … … 603 602 'abc' , Character tab , 'abc' 604 603 }}} 605 da `String>> `,` die Nachricht #asString an seinen Parameter sendet. Unterschiedlich sieht das nur aus wenn man es per print it (cmd/strg + p) ausgibt, da tab halt je nach Position in unterschiedlicher Länge gerendert wird. Die Strings sind aber gleich (im Sinne von #=).604 da `String>>,` die Nachricht `#asString` an seinen Parameter sendet. Unterschiedlich sieht das nur aus wenn man es per print it (cmd/strg + p) ausgibt, da tab halt je nach Position in unterschiedlicher Länge gerendert wird. Die Strings sind aber gleich (im Sinne von `#=`). 606 605 607 606 Bedenkt bitte, dass ihr bei sehr komplexen String Konkatenationen besser auf Streams zurückgreifen solltet: