# Documentation of SLTD (SWA Group 17)
## SLTDControlPanel
* primary goal is to create and visualize the UI-controlls of the game
* 'knows' the game -> so buttons can trigger functions (e.g. for building new Towers)
* game is able to sent messages to the controllpanel (e.g. for statistic updates (gold, score, lives, kills, waves)) and in future for features like the changable tower attack pattern
### update:
listens to publisher. if changed is called within one of the dependents from dependents collection aParameter is received from method. depending on aParameter a method is called
## SLTDGame
A SLTDGame is an instance of our Super Lovely Tower Defence Game world (TODO: refactor to rename master panel).
SLTDGame holds universal path variable. It is currently used to add morphs for the path visualization in `initializePathVisualization`. It should later be used to hand over the path to the SLTDEnemy via the SLTDEnemyFactory.
### Comunication with ControlPanel
SLTDControllpanel added itself to SLTDGame's Dependents (so it "subscribed" to updates from SLTDGame) `SLTDControllpanel >> update:` happens when `SLTDGame >> changed:` is called.
The message-protocol is `{#message_tag. aObject}`.
### Access Entities
Do not access entities directly. If you want to access Entites from other Entities, use the `SLTDGameEntity>>*Within:` methods.
Otherwise, use `entitiesWithin: radiusNumber from: aPoint`, `towersWithin:from:`, ...
Depending on the number of entity types and their access requirements, this interface might be refactored.
### Modify Entities
To add or modify individual entities, please refer to `SLTDGameEntity`. Do not directly interfere with the entities.
To add Morphs or entities on initialization, please add their creation in a new method and modify the initializatoin methods.
* Enitites:
* Please modify the `initializeEntities` method
* Gameplay handlers or managers:
* `initializeGameplay`.
To remove `anEntity`, send `unregisterAtGame` to `anEntity`
### Positioning / Tiling
If you wish to use tiling information, use the following methods (all in game coordinates):
* `nearestTile: aPoint` - Returns the center of the nearest tile to aPoint. If you use this for positioning of morphs, first consider `SLTDGameEntity>>snapToTile`.
* `randomPoint` - Returns a random point within the game.
* `randomTile` - Returns a random point within the game that is in the center of a tile.
* `inGame:` translates an absolute point to in-game coordinates
* `outGame:` translates a relative point to absolute coordinates
## SLTDGameEntity
A SLTDGameEntity is an Actor of the gameplay.
### Accessors
`game` - the SLTDGame the entity acts in
### Creation
Creation pattern for subclasses:
```
(<SLTDGameEntity subclass> newFromGame: <game>)
<initialization>;
registerAtGame.
```
Notable initialization messages are:
* `inGamePosition:` - sets the general position (refer Positioning)
* `snapToTile` - Positions the center of this entity at the closest tile.
The `onRegisterAtGame` method is called just before the entity is added to the game. Currently it adjusts positioning as extend and therefore the center might have changed since `initialize`.
### Removal
To remove `anEntity` from a game, send the `unregisterAtGame` message to `anEntity`.
### Accessing
Collection of all entities of some type within some radius:
`*Within: radiusNumber`
e.g.
`enemiesWithin:`
`towersWithin:`
...
### Positioning
**Do not use `position`, `center` or similar within entities.**
* Use `inGamePosition` and `inGamePosition:`. They offer a uniform and almost transparent translation of coordinate systems across the game. Also, they use floating point numbers, hence do not suffer from precision loss as much. All computation within gameplay elements should be in game coordinates.
### Subclass implementation
When creating a subclass `SLTDGameEntitySubclass`, to enable interaction with other entities, add the following methods to `SLTDGameEntity`:
```
isSLTDGameEntitySubclass
^ false
```
and
```
SLTDGameEntitySubclassesWithin: radiusNumber
^ self game
SLTDGameEntitySubclassesWithin: radiusNumber from: (self center)
```
similar to the existing methods.
## SLTDEnemy
### public accessors
* distanceTraveled
* goldValue
* health
* healthFraction (0 to 1, how much of original health is left)
* isAlive
### movement
* Currently, the enemy follows the path, but in principle, you can set any pont as `targetPoint` to go to. This point can change dynamically.
* Movement is controlled by stepping, and the speed is independent from `stepTime` (although low stepTimes are smoother).
* `moveFor:` takes a Duration and moves the enemy towards the target point by the product of its speed and the duration. At any point within this distance, the enemy might reach its target and select a new one, removing the need for alignment of path points and stepTime.
* `moveTowards: targetPoint by: distanceNumber` is a helper that moves the enemy towards a static target point by at most `distanceNumber` and returns the leftover of distanceNumber.
* reachedTargetPoint is a helper callback.
* `reachedEndOfPath` calls `game enemyReachedEndOfPath`
* `takeDamage:from:` tells the enemy that it took damage from some other entity (usually a tower)
### Misc
* `kill` is invoked by `takeDamage` and notifies the game.
## SLTDCursorVisualizer (prev. SLTDShadowMorph)
* is a morph to interact with the user
* visualise the next place, where the user could place the tower
* currently: calculated if player has enough gold to place a tower. Should probably be moved to game? Would need rework of the way towers are placed because the shadowmorph registers the tower with the game so the game has no (simple) way of checking wether the user has enough gold
## SLTDTower
### accessors:
damage, damage:
range, range:
targetMode, targetMode:
### setTargetModeFirst/setTargetModeLast/setTargetModeStrongest/setTargetModeClosest
sets target mode accordingly. Can be used for Buttons later
### getObjectOfInterest
detects all enemies within the range of the tower and saves them in set
### selectFirst:/selectLast:/selectStrongest:/selectClosest:
selects the first/last... enemy from the given set.
returns enemy
### selectTarget:
applies filter to Set from targetMode-Block
## SLTDShotVisualisation
* will be created in SLTDTower>>shot, stored in SLTDTower
* is turned transparent via addAlarm:after: 50ms after the shot
* redrawn when the tower shoots the next time
## SLTDEnemyFactory
* Probably not a "real" factory. Idk.
* Holds the `game` it creates enemies for.
* There are capabilities to create enemies by prototype, but they are dangerous due to the complications of the `copy` method of morphs. Don't try this at home. We now use factories.
* Usage:
```
(enemyFactory makeEnemy: #quick)
<modifications>
registerAtGame.
```
Where `#quick` can be replaced with `#strong` or `#weak` for now.
## SLTDWaveManager
* `waves` - Collection of current waves (private!)
* `game`, `enemyFactory` as the names imply.
* Use `startWave:` and `stopWave:` to manipulate ongoing waves
* receives steps from game and forwards them to its waves
* starts new wave when old one is finished
## SLTDWave
Is organized by SLTDWaveManager, not to be interacted with.
* `age` - duration the wave has been goin on for
* `enemies` - enemies associated with this wave
* `enemyFactory` - refers to the one from WaveManager
* `manager` - SLTDWaveManager for this wave
* `spawn: aSymbol`
* `duration` - time after which this wave is removed from its manager (by default 1 second after all enemies have been spawned)
* `schedule:at:` - set a time for a type of enemy to spawn
Similar to Enemyspawner, decides what enemies should be spawned at what time.
## REMOVED ~~SLTDEnemy_old~~
### Accessors
* health, health:
* path, path:
* speed, speed:
* isEnemy
---
### movement
#### setDirection
sets movement direction towards next point on path.
sends "reachedPathEnd" when enemy reaches last point of path
---
### stepping and behavior
#### death
sends "stopStepping"
#### isAlive
returns (health > 0)
#### pathPosition
will be increased by the amount of speed every step. Enemy with highest pathPosition is first in line
#### reachedPathEnd
Called when last point of path is reached.
Currently stops the enemy from stepping
#### step
Sets new position according to the movement direction.
Once next point of path is reached, "setDirection" is sent to set it towards the next point.
#### stepTime
#### takeDamage: aNumber from: aSource
Subtracts amount from health.
Sends "death" if health is now <= 0.
Currently changes color to red, should be removed (left in for visualization for debugging)
## REMOVED ~~SLTDEnemySpawner~~
### class on: aGame
Creates an EnemySpawner that gets aGame passed to game:
### enemyTypes
ifNil-getter that defines the characterictics of different enemy types. Keys are the color names as symbols.
### spawnEnemy: aType
Spawns a new Enemy of the given type with the characteristics from enemyTypes in the game.
### Accessors
* game:
* path
## REMOVED ~~SLTDMasterpanel~~
### Initialization
* hardcoded: size of the controllPanel and the game
* sizes are points (x - width, y - depth)