Kotlin 201 - Let's make a ship.
GitHub Decentralized Repo
GitHub Centralized Repo
I have a little time. Let’s try another experiment.
It’s 1545 and I have a little time. I wonder if I can spike something to detect a missing ship and create one. I’ll begin without much detail, just enough to see what it looks like to do it.
OK, this is interesting. I added this:
class Game ...
private lateinit var ship: Ship
private val waveOneShot = OneShot(4.0) { makeWave(it) }
private val saucerOneShot = OneShot( 7.0) {it.add(saucer)}
private val shipOneShot = OneShot( U.SHIP_MAKER_DELAY) { it.add(ship)}
// all OneShot instances go here:
private val allOneShots = listOf(waveOneShot, saucerOneShot, shipOneShot)
Changed the init:
private fun createInitialObjects(
trans: Transaction,
shipCount: Int,
controls: Controls
) {
cancelAllOneShots()
trans.clear()
val scoreKeeper = ScoreKeeper(shipCount)
knownObjects.scoreKeeper = scoreKeeper
val shipPosition = U.CENTER_OF_UNIVERSE
ship = Ship(shipPosition, controls)
// val shipChecker = ShipChecker(ship, scoreKeeper)
// trans.add(shipChecker)
}
With that in place, there would be no ship, ever. So then, this:
fun cycle(elapsedSeconds: Double, drawer: Drawer? = null) {
val deltaTime = elapsedSeconds - lastTime
lastTime = elapsedSeconds
tick(deltaTime)
beginInteractions()
processInteractions()
finishInteractions()
U.AsteroidTally = knownObjects.asteroidCount()
createNewWaveIfNeeded()
createSaucerIfNeeded()
createShipIfNeeded()
drawer?.let { draw(drawer) }
}
private fun createShipIfNeeded() {
val ship = knownObjects.targets.find { it is Ship}
if (ship is Ship) return
val trans = Transaction()
shipOneShot.execute(trans)
knownObjects.applyChanges(trans)
}
And now the ship appears at center screen after 3 seconds, SHIP_MAKER_DELAY. It doesn’t check for safety, but the game works fine. Some tests will surely break. One is objecting to the lateinit
variable not being initialized, that’ll just be something to add to the test I expect. The other is this one:
@Test
fun `game-centric NO MAKER saucer appears after seven seconds`() {
// cycle receives ELAPSED TIME!
val mix = SpaceObjectCollection()
val game = Game(mix) // makes game without the standard init
game.cycle(0.1) // ELAPSED seconds
assertThat(mix.size).describedAs("mix size").isEqualTo(0)
assertThat(mix.deferredActions.size).describedAs("deferred size").isEqualTo(2)
val deferred = mix.deferredActions.find { (it as DeferredAction).delay == 7.0 }
assertThat(deferred).isNotNull
game.cycle(7.2) //ELAPSED seconds
val saucer = mix.targets.find { it is Saucer }
assertThat(saucer).isNotNull
}
The deferred size is 3 instead of two. That is probably OK.
Good spike. I will in fact throw this one away, because I don’t see yet how to manage safe entry, but it shows that the basic issue is easily resolved. I am rolling back … now.
Summary
This has gone swimmingly. This morning’s spike was so clean that I kept it. This afternoon’s worked exactly as intended, the first time. If we didn’t want safe entry, we’d be done now and the code would be just fine. The thing with safe entry, however, is that we have to try multiple times, once the initial timer has elapsed, until we finally get the job done.
I’m not sure just how I’ll do that. Perhaps a flag in Game? Some kind of switch saying whether to look for the ship or try to create it again? I don’t know, needs some thought. But it surely can’t be all that difficult … can it?
Stop by next time and we’ll find out!