GitHub Repo

The game should display some info about the keys to operate it. Not that I don’t know, or the other person, but there might be one more person …

In the Zoom Ensemble last Tuesday night, one of the attendees grabbed the source and ran the game. He played rather well, in fact. I’m not sure how he figured out the controls: maybe he asked, maybe he browsed. Either way, we should make it easier.

And Hill didn’t even object to the Quarter object. He referred to the “Central Dogma” of a program, the fundamental ideas by which it operates. I think it’s easy to make the case that part of the Central Dogma of this program is the notion of independent objects in the mix, interacting to make up a game. And clearly the Quarter is more like that than is a message to the game object, which is not generally interested in the mix contents, instead just cycling the standard messages around to everyone.

Anyway, even if he had hated it, I was going to keep the Quarter: I like it and how it works. This game’s Central Dogma is a bit odd, but it pleases me the way these small objects somehow add up to a game.

Anyway … today, we’re going to add some help messages to the GAME OVER screen, and then I think we’ll try to make the game’s startup a bit nicer.

First things first, in ScoreKeeper:

    fun draw(drawer: Drawer) {
        // scale is 1/10 I think.
        drawScore(drawer)
        drawFreeShips(drawer)
        drawGameOver(drawer)
    }

    private fun drawGameOver(drawer: Drawer) {
        if (shipCount >= 0) return
        drawer.isolated{
            translate(3500.0,5000.0)
            text("GAME OVER")
        }
    }

A bit more text below the GAME OVER should be what we need. Does OPENRNDR’s text handle newlines? We’ll find out. It seems not. There is a writer thing, but I can’t make it work. [DELETED], I can just do it. After only a little tuning:

    private fun drawGameOver(drawer: Drawer) {
        if (shipCount >= 0) return
        drawer.isolated{
            translate(3500.0,5000.0)
            text("GAME OVER")
            translate(50.0, 500.0)
            scale(0.5, 0.5)
            text("Keyboard Controls")
            translate(0.0, 500.0)
            text("d     - Spin Left")
            translate(0.0, 500.0)
            text("f     - Spin Right")
            translate(0.0, 500.0)
            text("j     - Accelerate")
            translate(0.0, 500.0)
            text("k     - Fire Missile")
            translate(0.0, 500.0)
            text("space - Hyperspace")
        }
    }

hints display

That was way more work than it should have been. I must have fouled up my commits somehow yesterday and lost all the Quarter stuff, so I had to finesse around to get it back and reinstall it. I’m sure I’ve lost some small changes even so.

Now what I’d like to do is have the game start up, not with a full deck, but in GameOver mode. I think that to do that, we need to start the game with a quarter that has zero ships in it, but thereafter to create regular ones.

Let’s add a construction val to Quarter:

class Quarter(private val controls: Controls, private val shipCount: Int = 4): ISpaceObject, InteractingSpaceObject {
    override fun update(deltaTime: Double, trans: Transaction) {
        trans.clear()
        val scoreKeeper = ScoreKeeper(shipCount)
        trans.add(scoreKeeper)
        trans.add(WaveMaker())
        trans.add(SaucerMaker())
        val shipPosition = U.CENTER_OF_UNIVERSE
        val ship = Ship(shipPosition, controls)
        val shipChecker = ShipChecker(ship, scoreKeeper)
        trans.add(shipChecker)
    }

Now the game needs to initialize with a zero shipCount, and to use a regular Quarter when we trigger the q command.

The q calls

class Game
    fun createContents(controls: Controls) {
        add(Quarter(controls))
    }

And the game calls that for initial contents. Let’s rename this and add a new method for the q command.

class Game
    fun createInitialContents(controls: Controls) {
        add(Quarter(controls,0))
    }
    
    fun insertQuarter(controls: Controls) {
        add(Quarter(controls))
    }

main
keyboard.keyDown.listen {
    when (it.name) {
        "d" -> {controls.left = true}
        "f" -> {controls.right = true}
        "j" -> {controls.accelerate = true}
        "k" -> {controls.fire = true}
        "space" -> {controls.hyperspace = true}
        "q" -> { game.insertQuarter(controls)}
    }
}

Now we should get GAME OVER, which makes a nice attract mode, when the game starts, but our quota of ships when we type q.

And that’s exactly what happens. Whee. Commit: Game starts in GAME OVER / Attract Mode, displays keyboard help on GAME OVER screen.

We’ll sum up.

Summary

Tiny changes like these can be quite tedious and time-consuming. I spent a lot of time starting the game, crashing my ships to get to the GAME OVER screen, checking the look, adjusting the look …

If I were a smarter man, I’d have done the “Start in GAME OVER” first, but I was so concentrated on fiddling the text that making my job easier didn’t come to the fore. As Hill puts it, the program works for me, I don’t work for the program, and I should have made my job easier. Apparently I’m not even as clever as I look.

And you didn’t see it here in the article, but it’s clear that there are things I need to learn. I did something wrong with Git yesterday that lost the Quarter and its tests from the repo, and I fumbled a lot getting them back. Since I really only use Git to push the next thing to HEAD, I am not at all familiar with its many commands and schemes. I might do better to learn a bit more.

And I tried for quite a while to get OPENRNDR’s writer to work. I had it at one point, then in getting the Quarter back, I lost it, and I’d swear I typed in exactly the same things but this time it would never link up. So I just scaled and wrote the text the hard way, which took exactly the same number of lines as writer would have. A greater understanding of imports and Gradle would have helped, I think.

These are things that I just don’t use much as a solo developer (and only coming back to the Mac / IDEA / Kotlin after a decade away) and the upshot is that when I do need them, I don’t know them. I hope the memory of how painful it is to learn things like Gradle has faded in your mind. It’s a pain until it isn’t, if it ever isn’t.

On a day like today, with my tech support gang all not logged in yet, I’d have done better had I more familiarity with nitty-gritty Git and Gradle. Will I dig in and study them? Git and IDEA’s cover for it, probably yes. Gradle? I’ll continue to importune my friends for those incantations, and try to understand what they tell me.

For today, we’ll ship this. I have a new pair of AirPod Max phones to try out. See you next time!

Tiny Fool!
I forgot “insert 25 cents” …
    private fun drawGameOver(drawer: Drawer) {
        if (shipCount >= 0) return
        drawer.isolated{
            translate(3500.0,5000.0)
            text("GAME OVER")
            translate(50.0, 500.0)
            scale(0.5, 0.5)
            text("Keyboard Controls")
            translate(0.0, 500.0)
            text("d     - Spin Left")
            translate(0.0, 500.0)
            text("f     - Spin Right")
            translate(0.0, 500.0)
            text("j     - Accelerate")
            translate(0.0, 500.0)
            text("k     - Fire Missile")
            translate(0.0, 500.0)
            text("space - Hyperspace")
            translate(0.0, 500.0)
            text("q     - Insert 25 Cents")
            translate(0.0, 500.0)
            text("        for new game")
        }
    }

quarter