Category: coding jabber

  • 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.

  • story and art and code, oh my

    This game has become something of an obsession. Or, as the folks over in the meme-posting land of LinkedIn would tell you, a follow-your-passion moment worthy of some stock photography of me running through a field with my arms flung into the air.

    Seriously, in this few weeks of downtime between leaving my part time job and starting back up some professional upgrading and curricular activities—and still, given that the weather is in deep-winter mode—I have little else to occupy my time besides consuming books and Netflix or making something cool.  So the video game design project has won.

    All that is to say that I’m made some serious progress.

    I am nearing the home stretch of Space Carrot, which was my design phase set on building out the equivalent of a game board.  Yeah, there is still more to do as the game design progresses, but this phase was all about building the world in which the game takes place, and in addition to previous updates I’ve made on this phase in the last few days I have added a lot more stuff.

    I think the biggest of these is the furthering of my story system. Tweaks, again, will continue, but the core of it is in place.  The story-proper is a collection of ordered text events that appear on the screen moving the “plot” of the game along. When a room is first entered, when an area is first accessed, when anything of interest happens that could benefit from explanation, this all triggers a bit of the story to be loaded into the game and displayed on the screen. The game, as I have alluded to in other bits of writing, started as a story that I decided would make a good game, so there is a bunch of lore and narrative and characters that are all part of playing it.

    Another big behind the scenes piece is the database system that is coming closer to a solid initial implementation. Behind every good game is a good database, after all. Databases in games store more than just player information and scores, but are sort of the malleable memory of the game itself. I can set all the pieces up as a starting point in the code and have it all initialize when a player first starts the game, but from there the whole point is the player moving, changing, unlocking, and advancing the game itself. Every time something happens the game can try to keep track of this and save it at some point, or—as I am doing—it can basically save as it goes. The advantage of the first method is that someone can reload and go back. That is by design not an option in a rogue-like because the point isn’t to save and progress, but to play over and over again trying different approaches, so a point-in-time save file makes no sense for that. Instead, the state of the single play-through is pushed to the database frequently unlocking and changing the state of the game so that when the player “loses” the game goes back to an almost fresh state—but certain aspects stick and are unlocked ever after and for the next play. A tool. A room. Et cetera.  The foundations of that are now in place as I creep closer to the end of Space Carrot phase.

    And along with these two big bits of work I have not only done some bug clean up but also some key refactoring of the code as I (a) learn better approaches to things because I’m learning the language better and (b) encounter decisions that impede progress because of how I tackled it the first time. Not only does this mean simpler algorithms and code-reusability, but also building little functions that are like little single purpose tools to transform some data or extract a bit of something and give it to something else. 

    Oh, and I’ve leaned into public constants. As I build it’s often easier to hard code numbers into things for the sake of speed and debugging, but as things grow and complexify, one realizes that changing over, say, a number used eleven times to define a spawn point to a constant makes it easier to update when the map shifts ten pixels to the right because of a design change. I spent an afternoon just replacing hard-coded numbers.

    In the end, what this all means is that I am probably one more subversion away from declaring the end of Space Carrot phase and moving into the next one.  More on that later. So stay tuned.

    The obsession is palpable.  Maybe, those LinkedIn people are right and when you lay awake at night puzzling over a code problem and are not laying there dreading the morning, but rather considering creeping downstairs at 3am to try it out—maybe that is a passion project. Grab onto that, huh?

  • after more seriously cold coding, progress abounds

    I hunkered. It helped that it’s been twenty-five degrees below zero outside and I can’t do much besides sit in the warm house and look out through the frosty windows. No dog walks. No running adventures. No casual outdoor excursions. Instead, I’ve spent two full days coding.

    I wrote just a couple days ago about my intention to work on this current phase of development (Space Carrot) and barely forty-eight hours later I’m posting again to say that I’m moving my efforts to a new sub-sub-version. I updated the milestone log with the results of 0.2.1 and I’m moving on to 0.2.2 as of my next coding session.

    What goes into writing a game like this?

    I’m not an expert, I’ll remind you. I’m winging this and hoping something comes out of it.   I’ve been working on some game story lore, fleshing out the mapping system on (digital) paper (ie sketching out things on my tablet) and sitting down to think about the mechanics of creating a game space. 

    After all, the whole point of Space Carrot (I realize that some people might read that as the name of the game and not just a development phase) is to create a navigable world for the game-proper to exist in.

    First, I worked through the nuances of creating a collision detection system that doesn’t weigh down the processor checking everything constantly. Now you can’t walk through walls. And since I have now forced every movement to happen inside the boundary of virtual walls, my player sprite can navigate around without falling out into the void. Testing will continue on this, but so far it works.

    Second, I had to figure out the strangenes of door-to-door inter-room navigation. This, also a foundational aspect of the game, seems simple at first but in reality it’s a kind of interplay of a player “colliding” with door, waiting for an action to be triggered, and then figuring out what door she collided with is (specifically) and where it leads. Since this whole thing will exist as a series of  virtual rooms, any given door maps to a corresponding door on a different room map, all of it encoded into a few lines of data and “match” statements in the little door collision detection function. In other words, a door collision is detected and if that happens a trigger action can be accepted and validated, and if that happens the player’s location can be updated, and if that happens the code goes uh-oh, I’m displaying the wrong room because the player isn’t here anymore and then the code despawns wrong room and then spawns the new room where the player is now located and also standing at the cooresponding door she just walked through.  And all that happens in a fraction of a second so it seems to the player (maybe you) that your little dude just walked through a door into a new room. Sketch that out in a math equation, huh?

    Finally, I wanted to add a bit of explanatory text to the scene. Specifically,  this comes in the form of a little corner notice room label, when a new room was entered (it’s going to get confusing otherwise, believe me) and any other little notices that might help the player poke around the game.  This was relatively the most simple part, but I did need to figure out Bevy’s new (0.15) Text system, which has not been updated in almost every 3rd party tutorial and code sample. Every explanation of how to use this leaned into the TextBundle constructor which has been deprecated in the latest version. Good thing this whole langauge is starting to make more sense to me with each new function I create.

    So. That’s that. Two solid days in front of Visual Studio and a compiler—and countless times typing the run command and debugging my buggy code until I incrementally added all this stuff and it seems to work.

    But then, this is just a few more basic building blocks of a much bigger plan.

  • the obligatory “Hello world!”

    As of late 2024 I’ve been incrementally teaching myself how to do this Rust Language coding thing and it has somehow started to emerge as a game. My first love is and will always be words, tho, so here begins many, many words on the topic of building a game from scratch.

    So.

    Thing is, as of this week my efforts have come full circle.

    Kinda.

    An early attempt to build a game tick time loop was a factor of trying to create a series of nested loops that managed random things in a database. It would count off the seconds and if sufficient time had passed it would tell the database to +1 to the age of a game object —the game is about running a little [redacted] and [redacted] exists [redacted] but age consistently across all [redacted] blah blah—I’ll explain it more as we go, later. Needless to say I was leaning pretty heavily into the database design as an active tool to manage all my game variables all the time, including during the current screen gameplay.

    That was silly.

    So I started learning about this game engine called Bevy.

    Bevy handles all sorts of things. Or, essentially, it wraps all the regular pieces you would use—should use—for a game into objects that are then managed by the game engine. This means it can spawn a player and a board and objects and they can exist as virtual game pieces, but also as things that can display on the screen or whatever. It’s all neat and tidy.

    I wrote a bunch of code to use a bunch of array data, essentially an x and y grid of tiles that maps out a player area in the game. I call these simply, obviously rooms. A room can be something like the back store room where you keep and get new products. Or there are storefront rooms which are basically all the same across dimensions but may look slightly different or have different texture files, that type of thing. But the core here is that as much as a player can move around inside each room, there will be doors that take them to other rooms.

    Hense, the full circle.

    Aaaaand—now I am back to the database.

    I started encoding a bunch of database functions just this morning that are updated at various times during play. When a room is exited, I am thinking, the database will slurp up all the room data, store the state of all the objects in that room and essentially create a kind of mapped overlay of the base map for each room, but at coordinates there may be products or tools or other things that despawn out of the active play but can be respawned when the player re-enters that particular play area.

    I lean heavily into database driven design online and I am very comfortable thinking about things that way, but in many ways it this is because databases are virtually a necessity for web based stuff if only because you need preserve a lot of data between pages and across sessions. Each page is essentially a little app that builds itself dynamically from the data in the database and doesn’t rely on a system loading the entirety of the site into memory and keeping track of everything across every session then passing all of it from page to page. Now that would be silly,

    I figure, too, that this approach may really work to my advantage in the roguelite game plan that I am contemplating. Certain data can always be persisistent across runs of the game and just doesn’t get purged from the databse on initiation.

    I sat down here to write something about the abstractions of learning this language but now that my ideas are actually starting to take shape and form I’m noticing that I can write in more than abstractions. And that’s a good thing, right? Maybe silly. Maybe more.