GitHub Repo

I think I can start on a collision detection thing. Shall I test it, or spike it?

It seems pretty clear that in the new “centralized” code, the main loops will be something like:

for ( attacker in knownObjects.attackers ) {
    for ( target in knownObjects.targets ) {
    	interact(attacker, target)
    }
}

It follows that the interesting bit is to work on interact. It seems to me that it will be sort of trivial. Let me sketch it in, just to see:

    // spike sketch of centralized interaction
    fun interact(attacker: ISpaceObject, target: ISpaceObject, trans: Transaction) {
        if ( attacker == target ) return
        if ( outOfRange(attacker, target) ) return
        if ( attacker is Missile ) {
            if (target is Ship) {
                remove(attacker)
                explode(target)
            } else if (target is Saucer) {
                remove(attacker)
                explode(target)
            } else if (target is Asteroid) {
                remove(attacker)
                if ( attacker.missileIsFromShip ) addScore(target)
                split(target)
            }
        } else if ( attacker is Ship ) {
        	// do something similar
        } else { // attacker is Saucer
        	// do something similar
        }
    }

I see a bit of duplication there: it begins to look as if the whole thing comes down to “if these two things are colliding, destroy them, and if the target is an Asteroid and is destroyed by a Ship missile, score it”. (Maybe we’d score for a ship-asteroid collision as well. I think we score that now.)

I think that if I were to cast those parameters to Collider and use the Transaction, that would work right now. Keeping the game actually working would be a bit harder, because the other objects want to receive interactions as well. In a centralized version, of course, we’d subsume their logic up into Game somewhere.

To pull all the game logic up to Game, we’d need to count the asteroids, count the missiles, push the score to the ScoreKeeper, and so on. In addition to this interact function, we’d have one for move and so on. At least some of those changes might be hard to make in a combined version, but I see no deep difficulty.

I’ll add some stub functions so that the above code will compile. It seems worth saving.

    private fun outOfRange(a: ISpaceObject, b: ISpaceObject) = false
    private fun remove(o: ISpaceObject) {}
    private fun explode(o: ISpaceObject) {}
    private fun split(o: ISpaceObject) {}
    private fun addScore(o: ISpaceObject) {}

Summary

It’s easy to see that the code above will collapse way down. if we get past the outOfRange function, we know the two things are colliding and just have to do anything special, like scoring, exploding, splitting … and all of those could be implemented as a common method on the various classes, or, I think, would already be handled by finalize.

Sketches like this will tell us a lot about what a centralized implementation would look like, but as long as we keep them in the same app as the decentralized, we can’t crunch things down too far.

Here’s a thought that I hadn’t previously had … what if I were to clone this version and then proceed to refactor to centralize it, maybe even moving it to fixed arrays of data objects. Perhaps working that way, I could get down to a much more compact, procedural approach, without quite so much work recreating things that I already have.

I’d really like to see the end result of a centralized approach. Starting from scratch is one way. Refactoring (it’s almost DEfactoring) would be another.

Which should I do? Or is there some third thing? I can’t wait to find out what I do. I hope you’ll join me.