Intermission

Alrighty, so a bit late this post was by my standards, but life throws things at you. You know how that goes. That said, I wanted to at least talk about some of the things I have been working on!

The Python Discord Code Jam

Recently, the Python Discord released a qualifier for their latest code jam! I have never taken part in a code jam, so I felt it was the perfect time to amend that. I successfully submitted my qualifier and while I regret to inform that it was not hyper-optimized, it definitely did the job.

I’m excited to see what sorts of ideas my team and I can come up with for the code jam. It’d be neat to place really well in the contest, but since it is my first one I’m really looking for the learning experience.

A super secret Rust project

Yep, that is indeed a thing I am working on. It may or may not involve Bevy and an additional developer. Stay tuned 👀

The media posting app

I still intend to try and Dockerize the Django application I have been working on within the past month and change. I only have some experience using Docker, so it’s gonna take a bit longer there. Once I have it in place though, I may have an easier time incorporating it into a Gitlab CI pipeline that I mentioned in my last post.

And that’s about it

Taking up multiple projects has certainly been an interesting experience for me, as I am still also trying to improve myself in other ways that aren’t just coding. There are even more coding-related plans that I have, but I’ll keep those under wraps because it’s harder to start them if I start talking about them.

Short post but we take those. Stay cool friends 😎

The avoider game is complete! (enough)

For the anxious and the ravenously impatient, here is a link to the game. For more info, it can also be found in the Games and Experiments part of the website.

Whew! What an absolute experience it was getting this one out the door. I would say great strides were made in early March, with diminishing returns coming in towards the end of march and into April. I had hoped to have this done before my trip in mid-April, but sadly that was not the case. Thankfully I was able to still knock things out after and all is well!

My main goal here was to learn about Rust/Bevy while making something that seemed fun, no matter how basic and unoriginal it may be. I’ve found that waiting on the perfect idea is for people who never act on it, so I just went with my gut when starting production.

For me to consider this small project complete, the game needed to be fully functional with the ability to pause, resume, die, retry, and even win the game. Some of those features were vastly easier than others, but we got there.

Things I learned

While I am glad I finished this, it was definitely starting to get the rot of ignorant technical choices towards the end of development. This is fine. Making mistakes is a fact of life when doing complicated stuff. A lot of this stuff will echo what I have in the readme in the github repo for this game, but will go into a bit more detail.

Listeners and state changes

In Bevy, you can have systems listen for change of state and for events. These are two distinct things.

At the beginning, I thought the change of state was not something you can listen to. So, in some cases, when there was a change in application state I would also include an event that occurred alongside it. This did work, but it was inefficient. Once I figured out that change of application state could be listened to, I did not need to use events for those particular cases.

There is another distinguishing feature that events have however. They can carry data along with them. For example, there’s two ways the game can end. It can end with the player dying, or the win condition of the game being met. Depending on what causes the game to end, that is what the “end” screen will say.

  • If the player loses, the end screen will say something like “you died press these buttons to restart”
  • If the player wins, the end screen will say, and I know this may come as a surprise, it will say “you won”

So functionally, winning and losing is the same. This hits a bit too close to home but we’ll just not think about that for now. The only difference between the two is the string that is presented at the end state. Therefore, we can carry that string alongside the endgame event and just slap whatever we want on the end screen based on what occurred beforehand.

Here are some links for more technical info on events and state-based stuff. The latter is based on Bevy 0.10 which is the latest stable version as of writing.

Asset handling

Early on I wanted to just get my assets into the game without thinking about it too much. It turns out that people include loading screens in games for a reason. A more reasonable approach is to load up the assets by the asset server at the beginning and then pull upon them when the game is running.

What I did instead was pass the asset server into effectively any system that may or may not need to utilize an asset. That’s pretty goofy since passing it around everywhere is not only just a waste of performance if the game were scaled up, but also because it just created code clutter.

The solution to this, like I mentioned earlier, is next time to load the assets at the beginning, then refer to them using a resource.

I actually just don’t know how cargo works

When I read the Rust book, I may or may not have glossed over the cargo system since I figured it would be pretty straightforward. While in many regards it is simple to use when using other people’s libraries it’s a bit more intricate when you’re working with creating your own modules.

I’ve made it a point to learn more about the logic behind setting up my own modules, as this may also help with the architecture of future projects, too.

The biggest problem with this that I had was that I had to basically copy a function a couple of times because I could not get two files to share it. My code comment here kind of explains it some more. Definitely not one of my proudest moments but that’s why I’ll be reviewing how cargo and modules work.

Other things

The github repo readme has more points on things I should consider in the future. However, I think the above things are the things that stuck out to me the most, so I shall leave it at that for now.

And that’s about it

I’m looking forward to future projects. I have reason to believe my next stop will be the rapier physics engine. But first I’ll want to learn more about cargo and modules. ‘Till next time!

The falling sand Bevy app is available to mess around with! (and how I got it on the website)

For those who just want the goods, here’s the main attraction.

In my last post, I talked about the falling sand experiment I made with Rust’s Bevy library. I planned to get it to work on the website but I had a feeling it would be a headache. Turns out it was exactly enough of a pain for me to not immediately give up on it!

The rest will just be going into the technical details for the curious. For those who don’t care about the tech stuff, this is effectively the end of the post!

Essentially, it boils down to the following steps:

  1. Utilize wasm-bindgen to generate the files needed to run the game in the browser.
  2. Create a script that launches the .js file generated from the previous step.
  3. Create an HTML file that wraps around the script.
  4. Place all of the above files together somewhere that can be accessed publicly in my website, then point to the HTML . This HTML file is the one I linked to above.

Here’s some details on the steps:

Utilizing wasm-bindgen to generate files

I utilized the bottom portion of the Unofficial Bevy Book which talks about wasm-bindgen. If you have a project that utilizes Rust and Bevy and follow the instructions you should be good. I should mention though that when running the wasm-bindgen command, it is not made clear in the linked book (at least at the time of writing) that you need to point to the .wasm file that is generated in the wasm32-unknown-unknown folder generated by the previous cargo build command. So for example, you’d want to run something similar to this:

wasm-bindgen --out-dir ./out/ --target web ./target/wasm32-unknown-unknown/release/falling_sand.wasm

This should generate the files (in this case inside the out directory) for the next step.

Creating a script to launch the .js file from the previous step

Inside the out folder generated from the last step, a collection of files should exist. The one we care about is the .js file. It will most likely have its own name based on whatever the name of the project is. What I did here was create a new file in that folder with an init_game.js that has just the following:

import init from './falling_sand.js';
init();

…and that’s it! Well, for this step. The falling_sand.js will need to be replaced with whatever the .js file is in your case.

Create an HTML file that wraps around the script created above

From there, create an HTML file. It can be super bare bones, or you can get fancy with it. I’ll start with bare bones:

<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <script type="module" src=./init_game.js></script>
  </body>
</html>

Note that the init_game.js script (the two-line script) that we created is located in the script tag. The following is a fancy approach I did with the falling sand game:

<html>
  <head>
    <meta charset="UTF-8" />
    <style>
      body {
        background-color: black;
      }
      p {
        color: white;
      }
    </style>
  </head>
  <body>
    <p>Space: Change your brush to a different block type. The order is Sand (initial), Water, Solid</p>
    <p>Left click: Place block</p>
    <p>Right click: Delete block</p>
    <script type="module" src=./init_game.js></script>
    <script>
        function modify_initial_canvas () {
            const canvas = document.querySelector('canvas');

            if (canvas) {
                canvas.oncontextmenu = function(e) {
                    e.preventDefault(); 
                    e.stopPropagation();
                }
            } 
             else {
                setTimeout(modify_initial_canvas, 300); // try again in 300 milliseconds
            }
        }
        modify_initial_canvas();
    </script>
  </body>
</html>

This fancier approach solves the problem I was having where right clicking was causing the context menu to pop up when trying to right-click in the game. In addition, I have some style stuff there too. Also as an irrelevant note, this is HTML file is different from the actual falling sand HTML because I realized there was some styles I didn’t even need.

Place the files somewhere your website can access and link to it

The title says it all. All you need to do at this point is put the files somewhere that your website can access and link to. In my case, I put it along with my public WordPress media files. This involved going into my web server files and looking to see where my public media is located and how the website links to them. Then, I linked to the HTML file in the same way. There may be a better way of doing this, but this will at the least give another approach that could be useful for certain situations. At the end of the day, if you can provide a mechanism to open the HTML file, you’re good to go.

Anyway, that’s about it! That was a lot of stuff. If you’ve gotten far, I hope this helps. If I keep doing Bevy stuff, I at least know future me will appreciate it.

Falling sand!

Future me here, with an edit for this post: I got it working on the website! Here is a link to the falling sand. This does not work in mobile, only desktop.

As a side project that was also done in Bevy Rust, I decided to make a falling sand sim. I’ve always liked the idea of defining specific behaviors of individual entities and letting things unfold as they, or the user, interact with each other. Plus, who doesn’t like messing around with physics sims?

Here’s a sick and excessively dope demonstration of gravity working itself upon a buncha pixels (except those green guys, they don’t care what you think until they’re removed from existence. At that point, their ability to not care is completely overwritten by their inability to exist, which is entirely understandable).

Of course, this is hosted on Github for all to gawk at and chortle about. It was made in two days plus an evening as a hackathon at my job so it is at best a proof of concept. I do plan to leave it as-is though, unless I have a sudden burst of passion to expand on the falling sand idea.

The only other thing I plan to do with it is get it running on the website on its own page. It should “just work” with WASM, though I have some suspicions that may not be the case. Stay tuned for that.

Anyway go be a green pixel, friends. I’m sure there’s a cool way to expand that metaphor but you’re not gonna find that here. Look within or something.

Messing around with pixel art

A considerable step up from my last attempt

I’ve been enjoying pixel art more and more these days. It gives me a way to think without having to access the part of my mind that’s usually active when coding. Plus, you can sit down for an hour or two (or more) and usually have a finished product by the end. Is it something I’ll continue doing? Hopefully. I could use more creative outlets.

I decided to pick up Twitter to get more involved with the pixel art community ’cause why not, and I saw things that would make lots of aspiring artists quit on the spot. People make some insane stuff. One artist I’ve particularly enjoyed is Joseph Hyde. Call me basic but I’m a bit of a sucker for the landscapes honestly. Definitely worth checking out.

There’s also a twitter account called Pixel Dailies that posts a topic every day and people can make pixel art based on the topic. I like that they’re pretty open interpretation of the topics and they actually feature (by retweeting) the best works they find. Given my lack of experience, my submissions have been pretty juvenile so far; needless to say none of them have been featured yet. I’ll take my time with it. It turns out other people have been doing this for far longer than I have.

On the topic of my game, I’ve been slacking a bit on it, though it isn’t without any good news; my job does hackathons every quarter so I’ve been putting some work into a neat little side project with Bevy Rust. That’ll be a little extra something I hope to host on the site too. It’ll involve fancy sand.

One thing I know for sure is that in two weeks I’ll be taking a week-long trip to Colorado, speaking of sick landscapes. Knowing that, I want to have my projects in a complete state before I go. I highly suspect that whatever is incomplete when I get back won’t get done. I may try to mess around with pixel art during the trip though since that’s easier to pick up and put down.

Anyhow, that’s about it. ‘Till next time.

Now approaching the 20%

What I can say about this: like many things, it is an attempt.

I’m sure you’ve heard of the 80/20 rule and how it applies to effectively everything. In my particular case, I’m beginning to reach that point with the game that I showcased in my first post here. The situation is as follows:

  • 20% of the development time has taken up by 80% of my todo list
  • 80% of the development time is now being taken up by 20% of my todo list

To clarify, I have reason to believe I have reached that 20% based on the fact that I have gone from knocking out multiple things per day, to one thing per day, to potentially one thing per multiple days. I would say progress slowed down after my commits on March 23rd.

I am reaching the end of my first month for making a game and I’m hoping I can meet it. It’s tough; since I’m new to Rust and the Bevy framework, I’m now suffering the consequences of some of the mistakes I made while making a game for the first time. I’ll definitely make a reflection post on it after the fact, rather than now since hindsight is a bit of a better teacher in these sorts of pursuits. When you’re in the technical weeds, it’s easy to incorrectly assess the big picture.

I had a pretty fantastic breakthrough with the discovery of events in the Bevy framework though. I was having a hard time wrapping my mind around how the game would know the exact moment that the game was over and it was safe to clear everything exactly one time. On top of that, there was also the logic involved with resetting state back to the beginning. Thankfully I was able to figure that out and now the game restarts when you lose!

Also, I made a new enemy type which is neat. They’re far more dangerous than the standard ones that drive in a straight line (as hard as that is to believe).

Anyway, I’m hoping to get the game published to my website soon. I have no idea how that will work but apparently it’s mostly trivial to get a bevy game working on your own website. I like to hope those aren’t famous last words.

Starting a blog

This is my first post and a test to see how this website framework works. So far it’s been pretty neat with only a few snags here and there. I’ve been working on learning Rust and making games with the Bevy framework. It’s actually been a nice experience and I’m hoping to stick to a 1-game-a-month schedule. March is looking pretty good with a game I’m making that was originally supposed to be about *avoiding* bad guys but I could not resist adding a mechanic to also *destroy* the bad guys.

Currently, the annihilation works a little too efficiently and deletes the bad guys from existence with no trace of their previous existence. I’m working on trying to get an explosion sprite sheet I made to show an explosion occur when an enemy gets killed. Turns out it’s harder than I thought, due to my lack of knowledge in handling game assets in general. For the curious, here is the Github repository.

I’ve also been learning pixel art with Aseprite as a side-effort to at least come up with my own sprites for my games. I don’t expect to be good at it any time soon but that’s okay. It’s another avenue of creation if I don’t feel like coding.

Anyway, that’s all I got for now. This site may undergo lots of changes cosmetically and functionally, but for now it seems to work. Once I have a better workflow, I can hopefully start working on more in-depth and interesting blog posts. And with that, I am going to test out code blocks by writing the following:

fn main () {
    println!("Have an Awesome Day!")
}