error, error on the wall

I reached an interesting point in the development cycle that necessitated that I learn more about the root of the application.

If that sounds a little sketchy for a programmer to, you know, not fully grasp the intracacies of the main() loop of the software, keep in mind that for most every simple program the main loop is simple, too. And even for a Bevy application, most every simple app you can build in that game library (or importantly for this anecdote, every online code sample) follows the same basic and simple structure: add a system to initiate, then start up, then update and run.

And while up until now I have been building a pretty complex little game, the system upon which it runs has been very simple: Launch the game and the game launches. 

Except, that’s not how games usually work. 

You usually launch the game and at the very least a title card appears, and then often a main menu. The main menu is, of course, the important part.  And in game design speak, the main menu isn’t part of the game-proper, but a kind of pre-launch state.

And similarly, another task I had set for this milestone was building an in-game menu.  Both of these things are part of the capital-G Game, but they are not part of the game, if you follow.

In other words, I had to learn about game states, and the whole complexity in my main.rs file of conditionally running bits of the application depending on a game state. 

And all this started off okay, too. I found some code samples, and dug through the API docs, and started building. And then? Then, well, I added a function to trigger the game state to switch to the menu state and put it into my game loop.  That’s to say, there are a bunch of little functions that are run over and over and over again, updating the graphics, checking the keyboard for input, monitoring the location of the character on the screen, etc, etc, and I needed to add another one that would check to see if the key that opens the menu had been pressed (and if so switch that game state over to the menu mode).

After everything I’d built it was a simple little keyboard check, except when I ran the application I got a strange error:

trait bounds were not satisfied

rust error E0599

Okay.

I searched online. I dug through the API for the input commands I was using. I even asked ChatGPT for some ideas about why I might get that error from the very simple code snippet that I showed it.

No help anywhere.

Now to be clear, this little game I have been making is starting to get very complex. Lots of moving parts. Lots of systems that run sequentially or simultaenously or (now) conditionally.  And the game loop consists of a long list of check_this, animate_that, move_littledudearoundthescreen-type systems.

I spent two hours digging and prodding and simplifying my new function. 

No use.

Then I tried putting in some code that I knew worked from another function, I mean, not just adding but completely replacing that new fn call temporarily with a different function’s guts.

Nothing.

And then I did something that any good debugger worth his salt should probably do: I started methodically flipping switches until the problem disappeared. And—well, that’s the odd part. The first switch I flipped, that is to say, the first thing I turned off—which happened to be an animation function—fixed the whole damn thing.

It just suddenly worked—well, except for that animation function.

Was something wrong with the animation function?

I tried flipping the animation back on and then flipping something else off in it’s place, just to see.

Now? Now the animation was working but the picker highlights were off and yet it still all (minus the picker highlights) worked without that error.

So, naturally, I turned everything back on and—Error.

Look. I had a hunch. There had been something I was suspicious about and yet no matter where I looked (or what AI bots I asked) I always got the same answer:

How many systems can I add to an Update’s parameters. —I would ask or search or troll through message boards seeking a clue about.

There is theoretically no limit.” —was always the answer.

Except. And here is the suspicious thing—remember how I mentioned that my app was (up until now) pretty simplistic? Yeah. So, when I say simplistic what I’m really saying is that I had neither organized nor really done any management of my function groupings.  In fact, prior to adding that function that broke everything, my .add_system(Update… parameters for my game loop had exactly twenty functions being called from it. 

My menucheck was number 21. 

I spent a solid forty-five minutes breaking things up into categories and smaller chunks.  Add the room systems. Add the animation systems. Add the input monitoring systems. Five systems in one, eight in another, and so on, and so on, until there were those same twenty one orignal systems that had broken my original scheme but now organized into four separate Update calls.

And?

Well, I wouldn’t be writing a blog post about it if it hadn’t worked, now would I? I don’t know for sure if there is a function limit specifically or maybe if there is a character limit for the parameters, or if I tripped over some other invisible fence but whatever it was I seemingly had breached it and caused an error.  

If you have come here to read a programming anecdote, that’s it. That’s how this works. That’s how a guy can bang his head on his desk for four hours on a Sunday afternoon trying to puzzle out something simple and yet completely unobvious, something that no one thought to document because programmers with more experience, maybe, would naturally organize things a bit more meticulously.

Or, if you have come here because you are searching for a solution to that same problem and because I have helpfully copied the error messages and codes verbatim into the text to assist you with you own struggles, then cool. I hope this helps. And then drop a little love and check out my game.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *