Game embedding experiment

@Primal_Nexus had asked about embedding Space Rocks 3D in The Biggest Game. Technically this seems possible, and I got nerd sniped into trying it. However, I don’t think that’s a good idea from a gameplay point of view - more on that below.

Here’s a simple example: https://makecode.com/_TaV7k3RJbadx

The basic idea is to wrap the game code in a function so that it can be called from elsewhere, and then use game.pushScene() and game.popScene() to save and restore the scene state in between. When the sub-game is done (in this case when finishing the wave, or when the ship is destroyed), it calls the supplied function and reports back what happend.

game.splash("Other Game")
let testSprite = sprites.create(assets.image`reticle`)

function waitForEmbeddedGame(score: number) {
    game.popScene()
    if (score < 0) {
        testSprite.say("That went badly...")
        scene.setBackgroundColor(2)
    } else {
        testSprite.say("Great! Score: " + score)
        scene.setBackgroundColor(7)
    }
}

controller.A.onEvent(ControllerButtonEvent.Pressed, function() {
    game.pushScene()
    spaceRocks3D(/*wave=*/1, /*isEmbedded=*/true, waitForEmbeddedGame)
})

The sub-game can change its behavior when running in embedded mode, in this case disabling the custom menu and starting directly at a specified wave.

There are some gotchas with this approach. For example, if the callback function gets run from a game.onLifeZero handler, it crashes since that ends up popping the scene in the middle of updating the info overlay.

More seriously, encapsulating all the game code in a function can be a bit tedious, but it seems unavoidable. You need to ensure that the game state is correct each time the sub-game starts. Normally a game reset just re-runs the main.ts code again from the top, but that wouldn’t work right if the project contains multiple sub-games which can be started separately in an arbitrary order. On the bright side, this also helps isolate the sub-games from each other so that they don’t step on each other’s variables and other state.

I think this approach could work for something like a game collection or a set of mini-games, especially if the component games are developed independently. It would need some cooperation to have common interfaces such as handling the “done with the game” callback. Separately, I think it could also be useful for a large game where some individual parts are being developed independently.

However, I don’t think it’s a good idea to just stick a random pre-existing game into another game as a component . At minimum, you’d want to modify it to fit the overall theme and styling, and to ensure that the gameplay makes sense in the bigger context. It would feel very jarring if the games are mismatched, and if the sub-game is well-known (I think Space Rocks 3D is getting somewhat notorious by now…) it may also feel stale.

2 Likes

This is pretty much how we did combined the 5 second gamejam games too (https://makecode.com/_CrT6UTgCKCXc, it’s on the homepage under javascript games) - if you’re doing it for multiple mini games then having multiple files and putting each game in their own namespace works to keep things a bit more separate~

Namespaces are great to avoid name collisions, but if you want to be able to launch a minigame more than once, I think that just a namespace doesn’t seem sufficient. The game would need to be written to carefully reset all state on a restart.

It’s pretty natural in Arcade to set initial game state at the file’s top level, for example game.setLives(3), and then rely on the game over logic to fully reset everything for the next game by essentially restarting the application. Unless I’m misunderstanding it, just putting the game.setLives(3) in a namespace would mean that a restart which just calls the game’s main function again would keep the lives at zero, right?

Ah, right, I didn’t mean to imply that the namespace would solve things - only make it easier to organize / distinguish multiple mini games. You still need to wrap most things up and correctly reset any state, but when combining games from different sources it helps to minimize conflicting names :slight_smile:

1 Like