Dev Blog 17 - Windy Days Ahead

Howdy. No lengthy preamble this time - admittedly, I hardly have the energy to put down funny jokes today. But it’s important for us to maintain transparency with you all on the progress of the game, so blog post ahoy!

Let’s get into it.

Levels!

level
level
level
level
level
level

I made a bunch of introductory wind levels today. Wind, you might ask? Yes! There will be levels with wind. It’s a novel, new concept I discovered: an invisible force imparted on the ball, to move it around. Sideways, upwards, downwards… if you can name a direction, wind can blow you that way! You might be asking: who could have designed this remarkable concept? Where did I get such an intelligent and incredible idea?

Well, I looked outside, and I saw some leaves were flying around. Blew my mind - I knew I could use this right away.

I bet it would be pretty windy if you were thousands of meters in the sky. Coincidentally, we’ve been making progress on a background where this is REALITY!

pidos
pidos

Also, spooky buper.

spooky buper

Candy grabbems.

candy grabbems

Of course, here is a writeup from our wonderfully talented and smart as ever programmer, CraftedCart!


I don’t know what to title this section ¯\_(ツ)_/¯

Yet again gonna start off with a video for y’all.

The camera is almost there this time… just… turning the wrong way round sometimes.

Anyways, this is gonna be another miscellaneous tidbit from me this time. It’s hard to think of interesting or big-picture stuff to write about when most of what’s been going on is tinkering with nuances and implementing stuff you’ve already seen but in a less fragile way.

Lifetimes

Consider the scene where you’re making a custom level and want to add some scripted functionality with Lua, and for some reason you end up typing this.

1
2
3
4
5
6
local start_platform = stage:get_object("mesh_start_platform")
local position = start_platform.transform.position

start_platform:remove()

position.x = 42.8

We haven’t drafted out a Lua API yet, don’t expect the functions and stuff here to be named/used the same way here as in the final release

If you aren’t familiar with Lua, that code sample above gets a reference to an object in the level, gets a reference to that object’s position, removes the object from the world, then tries to set the X location of the now non-existent object.

Now there’s an obvious solution this problem: the script should raise an error when you try and set the X position on an non-existent object. The trickier question is how do we know whether an object exists or not? You see, with C++, there is no way to reliably tell, given a chunk of memory, whether that memory contains a valid object or not: once an object is deallocated, it becomes uninitialized memory ready for something else to use. No references to said object get updated by default

…by default… To help with memory management, some people (including us) use “smart pointers” - smart pointers own a chunk of memory, and only deallocate the memory under certain conditions (For example a “shared pointer” only deallocates memory when there are zero shared pointers to a single chunk of memory left). More notable for our purposes, there are “weak pointers”. Weak pointers point to a chunk of memory owned by a shared pointer, but do not take any ownership responsibility for the memory. When a shared pointer realizes it’s time to deallocate the chunk of memory, it also goes ahead and nullifies weak pointers - so if you have a weak pointer to an object, you can tell if it points to valid memory or not, since it will either contain a memory address with valid memory, or null.

So, how does this help us with Lua? Well, I’m making a rule here that anything exposed to Lua from our C++ codebase should have a lifetime attached to it. In the above example, we manage the memory of stage objects with shared pointers - that there defines a lifetime boundary. Lua attempts to get the transform of the start_platform object. Since transform is not managed by a shared pointer, it inherits the lifetime of start_platform (by storing a weak pointer to start_platform). The same goes for position - it inherits the lifetime of transform, which inherits the lifetime of start_platform.

Removing the start platform object causes its lifetime to come to an end. Since transform and position use the same lifetime as start platform, those references become invalidated in addition to the start_platform. Trying to access an object whose lifetime has come to an end can be detected from C++-land, and we can put a stop to that rather than potentially crashing the game, or worse, exposing a security vulnerability (as Lua should not be able to read/manipulate the contents of memory that it should no longer have access to).


CraftedCart really went out of their way to get this shrug displaying correctly in markdown.

shrug

Anyways, that’s it for this update. See you May 1st!