# SWA SLTD - Design decisions and learnings
**NEXT MEETING:** Mittwoch, 2. Februar 2022, 13:00 Uhr, Zoom
## Useful Resources
* [Squeak Image](https://moodle.hpi.de/pluginfile.php/22994/mod_folder/content/0/SWA2021-22_v1.zip?forcedownload=1)
* [Documentation](https://hackmd.io/oe9SAebTSvGLwM_FVAePaA)
* [Github](https://github.com/hpi-swa-teaching/swa21-22-group17/commits/main/)
* [Vortragsleitfaden](https://hackmd.io/s/ryQo0bCKF)
* [Vortragsvorbereitung](https://hackmd.io/@aganew/SJ-G75lqK)
* [UML-Chart](https://lucid.app/lucidchart/66de8349-9433-42bf-ac23-19b0e058b0a9/edit?viewport_loc=-11%2C-11%2C1579%2C869%2C0_0&invitationId=inv_ad601a18-d3ee-49f5-9684-c58f761dd907)
* [Präsentation](https://docs.google.com/presentation/d/1nOLQlpmhJvF1ZYTZMV4nN49GLX9yG-t6TVEsXBNEAdA/edit?usp=sharing)
* [H.U.G.O in Space](https://hackmd.io/@aganew/r1agmg_aK)
* [Code style guide](https://moodle.hpi.de/plNuginfile.php/24660/mod_resource/content/1/swa-code-leitfaden_.md)
### nochmal unbedingt drüber reden
* [x] BouncingProjectile>>attemptSelectNextTarget
* [ ] kommentar mittendrin
* [x] doNext: ([:anEnemy | self doDamage: anEnemy] value: self target)
* [x] wird das 2 mal ausgeführt?
* [x] warum nicht das target direkt reinschreiben
* [x] doNext: [self doDamage: self target]
### aller newste New todo (almost final)
* [ ] Konstanten auf KLassenseiten (Raban)
* [x] categorize constants
* [x] x @ y explicit in constants
* [x] initial/startGold statt (default-) gold
* [x] tower >> uiColor statt defaultColor
* [x] Enemy>>healthbarBaseColor is only ever set to green and can be made constant
* [x] improve Game replacement (Nils)
* [x] removeDependent
* [x] Cursor gold indicator (Anton)
* [x] remove cursor color
* [x] remove visual indicator from cursor
* [x] Simplify? schedule call, spelling (intervallll) (Hannes, Anton)
* [x] Update class comments, spelling (Fynn)
* [x] SLTDBouncingProjectile>>>attemptSelectNextTarget why changed? (inconsistent unsage, block, comment)
* [x] graphicPath categorization / all recategorization (Simon)
* [x] accessing through game 7 HelperClasses (Simon)
* [x] gameSpace und -Statistics werden nur vom Game aufgerufen
* [x] in jedem anderen Fall muss eine Methode
* [x] remove unnecessary Colors (Nils)
* [x] borderColor in Enemy / Entity
* [X] Enemy >> setPath (Hannes)
* [X] Enemy>>setPath LoD entfernen -> Methode im Game anlegen, die Punkte des Pfades zurückgibt
* [X] path zu pathpoints umbenennen
* [x] isNextBossWave -> modulo zu rem: (Hannes)
* [x] rename anObject in setters, remove dots(Simon)
* [x] MagicProjectile selectNetxTarget move to default value (returns boolean) (Nils)
* [x] Remove unreferenced variables (Fynn)
* [x] Effekt des MagicTowers mit zurückgehen ist nicht sauber
* [x] Rücklaufeffekt entfernen (Hannes)
## Fragen
* Architekturfrage -> Spiel ist von Innen nach Außen gewachsen
* Null-Handling, wann ist es okay? (siehe Cursor)
* Wie mit dem Rundungsfehler auf Seiten von Squeak umgehen?
## TODO
* Performance Issues
* Bilder werden immer wieder neu von Platte geladen
* [x] Grafiken cachen (Raban, Anton)
* [x] Magic Numbers für Size (Projectile Magic and Canon sowie Enemies)
* [x] rename imageForm statt TowerImageForm
* [x] Brenneffekt bei Enemies
* [x] boolean für brenneffeft -> nur einmalige Zuweisung
* [x] grafiken in SLTDGraphics
* SpyOnIt nach BottleNecks suchen (Fynn, Simon, Nils)
* gameTime >> stepExecutionLimit höher Stellen (e.g. 2 Sekunden)
* game >> stepTime höher Stellen (e.g. 2 Sekunden)
* game Starten, über GameTime, dann "self step" und spy on it
* besonders spannend ab Wave 100 + Tower
## Woche X
* [x] (Raban) GameTime schedule: at: by: repeatEvery: überarbeiten, GameEvent sollte nur initialisier werden bei schedule: at: by:
* [x] überarbeiten von moveFor (Hannes, Fynn, Nils):
* [x] StopStepping für Entities entfernen
* [x] (Anton) Kategorisieren der Klassen:
* [x] Entities (GameEntity)
* [x] UI
* [x] Core (Game, Space, Statistics)
* [x] Scheduling (WavePlanner, Wave, GameTime, GameEvent)
* [ ] Klassenkommentare (Simon, Raban)
* [x] Ballistic-, Bouncing-,Projectile
* [ ] GameSpace,
* [ ] Statistics
* [ ] Law of Demeter self game resourceManager imageLoader
## Lightningtalk
* [ ] Screencasts von mehreren Spielausschnitten
* [ ] typischer spiel Anfang bis Wave 10 (Hannes)
* [ ] verlieren (Simon)
* [ ] Wave 50 mit ein paar Türmen
* [ ] Dumm verlieren (Simon)
* [ ] überall Ice Tower und Feuertower ca. 13 Türme (gerne ein wenig schummeln)
* [x] EPISCHES endgames! (Nils)
* überall Tower, -> echter Spielverlauf bei Wave 100
* [x] Übertriebenes ENDGAME (Nils)
* überall Tower, 90 Millionen Gold, Wave 1000
* [ ] Squeak Roaster, WIN vs MAC OS (Anton und Hannes)
* [ ] WIN flüssig, wave 50 reales Game Play 16x Geschwindigkeit
* [ ] MAC OS macht halt MAC OS Zeug...
* [ ] Sounds (selbst aufgenommen) Kurz! (Anton)
* [ ] Schüsse
* [ ] Gegnergeräusche
* [ ] Grunzen
* [ ] Schnitt.......... (Raban, Fynn)
* [ ] LEvel, UI Sounds ("GAME OVER", "Lost a Live", "next Wave"...)
* [ ] Hintergrund musik (kann auch aus dem Internet genommen werden, ausnahmsweise)
## LEON FRAGEN
* Wo die Defaults parken?
* Muss text resizable sein?
* Wie stark sollen Methoden auf die Klassenseite ausgelagert werden?
* game open als statische Methode zum Starten des Spiels
## Template for Refactoring
1. Klassenkommentare !
2. wird methode überhaupt verwendet?
3. keine debug Methoden?
4. Methoden Kategorisieren
5. werden alle Attribute der Methode verwendet?
6. ist die Methode aussagekräftig benannt?
7. 9 Zeilen maximal - 7 Zeilen Code + 2 Zeilen Kommentare
8. Instanzvariablen nur über Accessors zugreifen
9. maximale Verwendung von Collections und Methoden
10. Kaskaden verwenden
11. Law Of Demeter beachten! Ggf. Vereinfachung möglich?
12. keine Metaprogrammierung!
13. Blockstrukturen sind in einer Zeile oder als Block definiert
14. Lazy initialization
```
ifTrue: [self recomputeAngle].
ifTrue: [self clearCaches;
recomputeAngle].
```
14. keine defensive Klammerung (source>>prettyPrint)
15. keine MagicNumbers
16. keine punkte am ende
```
methodName: anAttribute1 with: aValue
| sinnvollerName |
sinnvollerName:= self calc: aValue.
self operationA;
operationB: anAttribute1.
^ self result
```
--> danach umbedingt prüfen, ob sich die Methode noch so verhält, wie sie sich verhalten sollte!
Nils:
* unify control flow in GameTime scheduling
* clean up movement
Klassenaufteilung: (16 Klassen )
2. Runde:
Nils und Raban:
* [ ] ControlPanel
* [x] ControlPanel >> startAndEndscreen
* [ ] stringmorph
* [x] Noch ausgewählter tower platzierbar
* [x] Towerkosten auf Klassenseite
* [x] ref von TowerButton
* [ ] Towerbutton Layer mit ':'
* [ ] EnemyPath
* [ ] Game
* [ ] GameSpace
* [ ] Statistics
Fynn und Han'Ens:
* [ ] GameEntity
* [ ] Tower
* [ ] Cursor
* [ ] MovingMorph
* Enemy
* [x] generic healthbar position (in dependence of image height?)
* [x] BUG: wird bei erstem Schuss kurz größer
* Projectile
Simon und Anton:
* Wave
* WavePlanner
* GameTime
* [ ]
* GameEvent
* ResourceManager
## Next weeks tasks
* Graphics
* [x] Magic tower projectiles
* [x] center projectiles
* [x] generic healthbar position (in dependence of image height?)
* [x] burningProjectile
* Enemies (Raban)
* [x] difficulty und game einreichen für Health calc (boss und strong)
* Healthbar
* [x] BUG: wird bei erstem Schuss kurz größer
* ControllElements
* [x] visuelle anzeige, wenn Tower nicht finanzierbar (Vgl BaseTower)
* Start/EndScreen
* [x] (magic placing numbers)
* MovingMorph
* moveFor:, moveTowards:byAtMost:
## TOP
* Feedback zum Vortrag/Code
* Plan was gemacht wird
* Codereview
* Feedback
* Unberechtigt
* Plan was gemacht wird
* [x] MagicProjectile Objekt wiederverwenden statt neu zu spawnen (Raban)
* Buttons canAfford (Nils)
* (Path not need to be square) (Nils?)
* Aufspalten der Gameklasse: (Raban)
* [x] GameSpace -> CollisionHandler
* Magic Tower überarbeiten (Hannes)
* Grafik (Simon, Raban)
* Gegner Lebensbalken
* initializeGraphics refactorn
* Problem with changing color of enemys
* change enemy graphics from wave
* Enemy Klassen Methode mit symbol für typen
* Bilder zentrieren + quadratisch cropen
* [x] Start / Endscreen (Fynn, Anton)
* Game, GameTime, ... receives `replaceWith: aGame`, sends update to Observers (GameTime same), those remove themselves from old games and attach to new one.
* ControllPanel observed Game für Endscreen
## Refactoring
* reararnge references of Game to GameTime, GameSpace, GameStatistics
## Feedback von Leon
* 7 Zeilen ziemlich harte Grenze
## Bugs
Basic Tower button verändert Farbe wenn Gold = 0 und ist nicht mehr clickbar
Tower werfen zufällig Fehler wegen updatePreview
Tower preview bleibt nach GameOver bestehen
## Refactoring
* Game knows Controlpanel for livesDepleted
* movingMorph --> movingEntity
* Minigun affectInterval: 20 ms is pretty fast (More than 1 per frame at normal speed)
* Shoot collisions are not synchronized
* 'basic' vs 'standard' tower, unify information obout tower types (cf. somewhere below)
* Names in minigun aiming are a little unclear
## Currently actually active questions
* Veränderungen im Vortrag
* Double Dispatch
* Zweckgebundene Sequenzdiagramme
* Folie 42: Einzelne Funktionalitäten
* Reflexion Arbeitsweise weniger wichtig
* Türme warum keine Komposition?
## Questions for consulting
* [ ] Müssen triviale Rollenbezeichnungen in das UML Klassendiagramm?
* wenn keine Instanzvariablen existieren, dann gestrichelte Linie
* Kreuz auf Seite ohne Variable oder Doppelpfeil wenn beidseitig
* [ ] Beim Vortrag Objektdiagramm? Redundanz --- Nein, nur wenn praktisch
* [ ] Squenzdiagramme -> darauf achten wann und wo der Pfeil ist und das Objekt anfängt un d aufhört (Hannes)
* [ ] Wie genau soll ein Entwurfsentscheidungs-Fazit aussehen?
* [ ] Gut/Schlecht?
* [ ] Vor/Nachteile nochmal auflisten?
* [ ] Ausblick für Erweiterungen?
* [ ] Kurz! / Abwägung
* [ ] Spezifische Argumentation für genau unser Spiel (Simon, Nils, Raban)
* [ ] Wiederverwertbar *in anderen Klassen* (muss in Abgabe sein)
* [ ] Wie mit zukünftigen Implementierungsideen umgehen?
* [ ] Als angehangene Folien für ergänzedes Material?
* [ ] kann rein, muss nicht wie später sein (Raban)
* [ ] Wann verschiedene Klassen-Kategorien nutzen?
* [ ] Sollen wir auf Rot/Grünschwäche o.Ä. mehr Rücksicht nehmen?
* [ ] Sind die Farben / Symbole verständlich gewählt? (Fynn macht grün und Rot)
* [ ] Wie viele Sprecher:in im Vortrag sind erfahrungsgemäs sinnvoll?
* 2 - bis alle
* neuer code perfekt, alter Code **KLARER KENNZEICHNEN**
## (""Active"") questions
* Wie ist der Vortrag als Referenz für später gemeint?
* Dinge, die es nicht in den Vortrag geschafft haben
* je nach Slidelayout -> falls sie sich nicht selbst erklären noch Informationen auf hidden-Slides
* Wie viele/wie wichtig Patterns? Sollten wir non-patterns vorstellen?
* auf Zwang müssen keine Pattern vorgestellt werden!
* Abwägung zwischen unserer Lösung und Pattern denkbar
* Erfahrungen bzgl. Zeitmanagem ent (erster Vortrag...)
* Designentschiedungen: grob 15min <-- Fokus
* Architektur: eher unter 10min
* Wie erweiterbar muss der Code sein?
* es kommt drauf an -> theoretisch will mensch ein System so offen halten wie möglich
* Fokus: das Spiel sollte funktionieren und unseren Anforderungen entsprechen
* Lieber Morphs reusen oder unsichtbar machen?
* weg schmeißen - neu initialisieren
* Domänenfrage
* (Tower platzieren: Geld überprüfen eig. Game-Logik nicht shadowmorph?)
* Architekturdiagramm anschauen
* SLTDGameEntity wie mehrere Morphtypen unterstützen und dennoch mehrere Kindklassen (Decorator o.ä.?)
* SLTDGameEntity vom Type Morph
* Entities können dann submorph hinzufügen, als ihr Aussehen.
* GameEntity Morph ist dann auf Transparenz
## TODOs
* ALLE: Schnittstellen der geschriebenen Klassen dokumentieren
* Balancing
* refactoring /umbenennung von sachen
## Post Presentation
* [ ] general class `Schedule` that can be used for entities, waveManager, wave
* [ ] New attempt at ShotVisualization
---
## Woche 8
### Refactoring
* [ ] wave könnte gameTime als instanzvariable haben statt über game abzufragen?
* [ ] sachen umbenennen
* [ ] `SLTDControlElement>>newReflecting` `aModel` zu `aPublisher`?
* [x] `SLTD>>shootingInterval` zu `affectInterval`
* [x] `SLTDGame>>enemiesWithin:` accessor für entities
* [x] `SLTDCursor` soll über Türmen angezeigt werden
* [ ] dictionaries für Fallunterscheidung vermeiden -> double dispatch
* [x] `ControlElement>>on` zu `newOn` (zumindest anders)
* [x] `Game>>inGame` / `Game>>outGame` sinnvoller benennen
* [x] entfernen: `ControlElement>>model` ist das ein gängiger Begriff? sonst umbenennen
* [x] on: addDependent
* [x] so lassen:`Enemy>>takeDamage:aNumber from:aSource` benutzen wir aSource nie.
* [x] `SLTDControlPanel` zu `SLTDEntryPoint` (to be discussed) / (has been discussed)
* [x] `Game>>initializeCursorVisualizer`
* [x] `SLTDWaveManager>>fromGame` zu `newFromGame`
* [X] `GameEvent>>occur` zu `execute`
* [x] Accessors: anObject spezifizieren
* [ ] Path class: rename NewFromGame
* [x] remove isTest
* [x] Class comments
* [ ] increase cohesion in Game?
* [ ] more specific protocols
* [x] Rename: setTagetMode -> useTargetSelector
* [x] specific: attackClosest, ...
* [ ] private categories
* [x] EnemyPath: proper adapter!
* [x] WaveManager step: delete?
* [x] Wave: `event*` umbenennen
* [x] move defaults to initialize
* [ ] Enemy>>path in pathPoints ( weil das ist ja kein "SLTDEnemyPath" Objekt)
* [ ] SLTDWave scheduleEvents ?
* [ ] use defaultBounds for default extents
* [ ] Make Cursor go on top of towers
* [ ] Wave: NewFrom:Type: ... seperate methods for types? (Simon, Fynn)
* [ ] do we need dictionaries in wave mapping/enemy builders
* [ ] Architektur
* [x] "...Visualization" entfernen
* [ ] Rollen in Assoziationen im Diagramm!
* [ ] Entscheidungen
* [ ] Problem immer wichtig
* [ ] Layout eher so meh
* [ ] Tower: Erweiterbarkeit Strategy & Template Method
* [ ] Vielleicht nicht immer der Observer
* [ ] Kombination von Strategy und Template Method
* [ ] curser Visualizer wirklich als gameEntity? vielleicht sinnvoll tower und enemies nochmal einzeln von einer klasse erben zu lassen?
## Woche 7
### Features must-do
* [x] **!!!!isTileFree!!!** (wenn Pfad oder Tower -> nein!) (Simon, Hannes)
### Balancing (optional)
* [ ] Tower costs, rewards, damage... (Simon)
* [ ] neuen starken Enemy?
### Refactoring / Code smells / Linting
* [x] ShadowMorph mit alpha background, schuss besser (Hannes, Simon)
* [x] addAlarm:after: für Schuss (Hannes, Consulting: Anton)
* [x] ControlPanel (Nils, Raban)
* [x] Universal ControlElement
* [x] Tower sollen nicht auf clicks reagieren (Fynn, Anton)
* [x] Remove TestEntities, Enemy_old (Fynn, Anton)
* [x] remove TestWave (Fynn, Anton)
* [ ] Sachen mit Konsequenzen aufschreiben (Fynn, Anton)
* [x] remove reference to master from game
* [x] Pluggable umbenennen
* [x] waves als eine Klasse?
* [ ] ControlPanel Layout: deduplicate creation of helper morphs
* [ ] Gold logic not in CursorVisiualizer
* [ ] CursorVisiualizer changes look depending on the used towerclass & show range
* [ ] Move Factory functionality to Wave?
* [ ] Implement or remove age from WaveManager
* [ ] Why are the lasers flickering?
* [ ] Either Towers as **template method** or strategy, not both
* Add one tower with
* [ ] ShotVisualization als Submorph statt eigenes GameEntity
* [ ] getter and setter!
* [ ] Projektile getrennt implementieren
* [ ] Tower use `subclassResponsibility`
* [ ]
* [ ] Game changed: only if value is actually different
* [ ] aStrategy oder aBlock?
* [ ] Accessors: anObject spezifizieren
* [ ] Send game with update?
* [ ] Enemies Observable
* [ ] Use this to check enemy death / path reached
* [ ] Maybe for towers too
* [ ] towerType / updatelook: remove or repair
* [ ] Wave: NewFrom:Type: ... seperate methods for types?
* [ ] Enemies fetch path from game?
### Veränderungen
* Wavemanager stept sich selbst statt von Game gestept zu werden
* defaultExtent als getter
* Game::eventHandling >> mouseDown,
## Woche 6½
* [x] Waves
* [x] Wellen Interface (Fynn)
* [ ] (Difficulty)
* [ ] Mehrere Waves schedulen - automatisch generieren?
* [ ] aktuelle Wave --> Name? Nummerierung?
* [ ] (Factory umbenennen, basicSpawn (Refactory™️))
* [ ] Control panel
* [ ] Statistikgedöns
* [ ] wave counter
* [ ] (next) Wavebutton
* [ ] SLTDText (Nils) - Kapselung des Updates
* [ ] **!!!!isTileFree!!!** (wenn Pfad oder Tower -> nein!)
* [ ] IsBlocking in Entities
* [ ] Pfad extra prüfen
* [x] ShodowMorph (Raban)
* [x] Kapselung des Towerspezifischen spawning
* [x] rework Layout
* [x] Baubutton überarbeiten -> kommunikation mit dem Shadow Morph
---
## Woche 6
* [ ] Nils?
* [ ] Wellen Interface
* [ ] (Difficulty)
* [ ] Mehrere Waves schedulen - automatisch generieren?
* [ ] (Factory umbenennen, basicSpawn (Refactory™️))
* [ ] Control panel
* [x] (Observer-pattern --> Dependents (addDependent)) -->Simon, Hannes
* [ ] Statistikgedöns (Anton, Raban)
* [x] update von text in step von control (Raban)
* [x] Score (Totalgold) (Raban)
* [x] Counter an gekillten Enemies (Raban)
* [x] aktuelle Wave --> Name? Nummerierung?
* [x] Leben, nachdem Nils und Fynn enemies repariert haben
* [ ] (next) Wavebutton
* [ ] Baubutton
* [x] klick Tower, klick tile (Anton, Raban)
* [ ] überprüfen ob Pfad --> Tower plazieren
* [x] Path als Klasse, Path / Enemies reparieren (Fynn, Nils)
* [x] Enemy end of life (Fynn, Nils)
---
Designentscheidung:
Dependet -> sagen die die Objekte welche Optionen sie haben oder entscheidet die Controlloberfläche welche Optionen dargestellt werden
---
* [ ] TowerTyp-Klassen --> Simon, Hannes
* [ ] Angriffsmodi als Block übergeben
* [ ] Geschoss Linie
* [ ] Runde logik --> Nils
* [ ] Tower Targetting modifizieren während Runtime
* [ ] observer pattern einlesen -> siehe squeak addDependent
---
* gamelogic
* Pfad visualisieren
* UI
* Enemyspawner
* tiling anpassen --> für andere Klassen zugreifbar machen
* enemies ordered collection
* enemySpawner path nearest tile
* enemy death unregisterAtWorld
* enemy spawner send message for drawing path
## Stage 1: Prototyping
* [x] REFRACTORING
* korrekte Koordinaten für Enemy
* Überflüssige klassen entfernen
* [ ] Raster verkleinern, Raster an Pfad belegt (Fynn, Anton)
* [ ] erstmal Pfad ablaufen
* [ ] Enemy mittig auf Tile spawnen
* [ ] Gamelogic (Nils)
* [x] Runden
* [ ] Wellen --> als Objekt, "schwierigkeit" mit übergeben um unendlich viele wellen haben zu können
* [ ] einfache "intro"-Wellen hardcoden?
* [ ] Geld
* [ ] UI
* [ ] Masterpanel inkl: (Raban)
* [x] eingebetteter Spieleoberfläche
* [ ] remove Masterpanel vom Game
* [x] Controllpanel
* [ ] Score (Totalgold)
* [x] Counter an gekillten Enemies
* [ ] Wave
* [ ] Leben
* [x] Towerbutton
* [ ] Wavebutton (future)
* [x] Geld
* [x] Message flow
* Master panel knows game, control panel
* Control panel knows game -> Control panel asks game if values changed
* [ ] Funktionalitäten
* klick Tower, klick tile, überprüfen ob Pfad --> Tower plazieren
* [ ] Tower improvements (Simon, Hannes)
* [ ] neue Towertypklassen(Sniper, Casual ....)
* [ ] improv. getObjectOfInterest (attack lowest, strongest, nearest (to goal), etc...)
* [ ] Enemy refactoring (Anton, Fynn)
* [ ] enemyClasses
* [X] Object>>EnemySpawner als Instanzvariable von Game
TODOs:
* [ ] defaultVariablen anstatt von magic numbers im Initiationsprozess
Anton und Fynn Liste 30.11.
* Wie funktioniert Enemy Movement
* Andere Leute Code schreiben
* Keine Dokumentation
* Enemies sterben gleichzeitig anstatt gleicher Punkt
-----
## Documentation
week 1:
* Implementierung von Tower- und Enemyklasse, sowie der Gameworld Instanz mit eigenem Tiling
* Modellieren Wellen als Objekte
## Old questions
* wofür gibt es verschiedene morphs? zb BorderedMorph, RectangleMorph, SketchMorph
* Basic sinnvoll
* Rectable, Border für Spezialeffekte
* PolygonMorph, Imagemorph;;
* warum ist redButtonPressed nicht nur linksclick?
* ?
* Koordinatensystem relativ zum owner/morph unserer wahl
* self position vs. self owner position
* setDirection das erste mal nach initialisierung aufrufen —> startStepping oder so ähnlich?
* Conflicts resolven --> keine conflicts entstehen lassen...
* changes stashen/reverten --> vergiss es
### Next refactoring suggestions:
* [ ] Game should not care about its positioning in the master panel (negotiable: game should not care about the master panel at all, only provide unidirectional interface)
* [ ] Masterpanel: `addEntity:` rename or use `addMorph:` as anEntity is not SLTDGameEntity
* [ ] `SLTDControlPanel>>buildButton` does not need to `openInWorld`. `addMorph` takes care of that.
* [ ] Optional: additional class positionable.
### Erdöl
* [ ] EnemyFactory
SLTDGameTime
```
schedule: eventBlock in: aDuration by: responsibleObject repeat: repeatDuration
self
schedule: eventBlock
at: (self passedDuration + aDuration)
by: responsibleObject
repeat: repeatDuration
```
```
schedule: eventBlock at: aDuration by: responsibleObject repeat: repeatDuration
self events
add: (SLTDGameEvent new
actionBlock: [self schedule: eventBlock in: repeatDuration by: responsibleObject repeat: repeatDuration. eventBlock value];
occurTimeDuration: aDuration;
responsibleObject: responsibleObject).
```