The 2024 Wheel Reinvention Jam just concluded. See the results.

Update #1

Ben
Over the last few weeks I've been working on a variety of different aspects of Nirion. Probably the one that I spent the most time on recently was music and sound. So far I had been neglecting sound and music to an extent, having only gotten basic sine waves playing way back when I first started the project. It's a relief to have made some progress in this area, and I think I have a lot more confidence going forward. I've also updated the art, added a 3D effect for upgrades, and finished off a first pass of the first major boss. Here's an overview of some things I've done since the last update.

3D Upgrades

A while ago I decided that I wanted a few select things in the game to have a 3D effect, influenced mostly by Sonic 3 and Sonic Mania, where the player can come across giant 3D rings that transports them to special stages. To me this makes the things that are 3D feel more special, and they stick out more.

I first tried exporting and loading PLY files from blender. This worked fine, except I don't have any experience whatsoever in 3D modeling. I don't think learning enough blender to make the simple models I needed would have taken that long, but I'd prefer to not have to spend the time to learn it right now.

What I settled on was generating a 3D mesh from pixel art. The process is basically to just draw the 2D sprite in Aseprite, create the 3d model asset:
1
2
3
4
5
Model
{
	bitmap = Common.png;
	source = (32, 240, 16, 16);
}


And then tell the game to render that 3D model. During asset preprocessing, the code will load the given region of the bitmap, loop over every pixel, and for each non-zero alpha pixel, it will create a cube. The cube's colour is the pixel's original colour, and the cubes depth is some constant multiplied by the pixel's alpha. I'm basically just extruding the pixel art, but manipulating the alpha to change the depth makes the model look more interesting.

The result:


The source art:


I think this works pretty well and suits my needs. Using alpha to control depth is a bit difficult, it's mostly just guessing, and using alpha this way makes it a bit harder to visual in Aseprite.


First Major Boss

The "first pass" of the first major boss in the game is done. There's a few balance/visual issues I'll want to fix eventually, but the basic functionality is there.



The boss will cycle through different attacks which require the player to dodge and block/reflect. Successfully blocking certain things will stun the boss, allowing the player to do much more damage for a short amount of time. I'm aiming to design bosses similar to the more difficult boss fights found in the Kingdom Hearts series. The focus is mainly on learning the enemy's patterns and blocking/dodging correctly to get openings.

The boss is animated entirely in code allowing me to dynamically position his different limbs based on stuff like IK and the player's current location. I think this does make some animations more cumbersome to create, but overall I think it's the right direction for this game.



Updated Art

Over the course of about a week, I updated a lot of the environment art. I redrew tiles, objects and added some more interesting designs and variety to the map.





I think it's looking a lot better overall, and feels more like an actual mine now! I'm still in the process of updating some tilemaps. Another thing I finally got around to fixing was the scaling of tilemaps. Before, tilemaps were just using nearest neighbor filtering, which was fine for layers that the player was currently on. However, in some rooms, layers below the player use a parallax effect and are scaled down to make them seem far away. This caused shimmering and cracks in the tiles depending on the camera's sub pixel location.

I solved this using the method described here by Ryan Fleury. I've always used this for rendering the player and other objects, but struggled to get it to work with tiles. Ryan explained that you can get this to work on tiles by first compositing the tiles onto a separate texture at an integral offset, and then using that texture to render the tilemap using the algorithm.

So every frame for each visible tilemap, I first render it to a texture(tilemaps are 512*512 always) and then draw that texture in the world. This works great.



Unfortunately, I'm using entities(not part of the tilemap) placed on top of tilemaps for stuff like doors. This produces visible seams that I've yet to work out. Besides this though, I've very happy with the results. The camera also occasionally zooms out for boss battles, so this helps with that as well.

Music and Sound

As I mentioned before, I spent a lot of time on music and sound. I've never done any sort of music or sound design ever, I barely even knew what a note meant in music. So I found it pretty difficult to jump in, but over the course of a few days, I got the hang of the basics. I used Reaper, and found some free instruments and synths. I used these to make a couple of basic background tracks for the mines and was reasonably content with my third attempt.

I think I found sound design even harder. With music, I actually have an interest in composing and I would love to be competent at it one day, but not so much with sound design. I've ended up settling on using a mixture of synthesizing and buying sounds packs with some editing. I've made a few sounds now, and I'm reasonably happy with them.

I spent a day or two implementing sound playback in the engine. I've added basic stuff like being able to play a sound, loop sounds, stop sounds, change pitch and volume. One thing I haven't done yet is streaming long tracks. The background music I made is already a 40mb wav file, which is larger than the rest of the game combined so far, so I think streaming and compression might be necessary.

Save Points

I also added save points to the game. The player can enter them, an animation will play, and then the player will be healed and progress will be saved. If the player dies, they return to the last save point having lost all of their progress since last saving. I'm not sure if I'll keep this "punishment" for dying, since it might just be annoying to lose progress, but keeping the player's progress requires some extra consideration of where it's okay for the player to die and how they can return to where they were without issues.

The player "evaporating" in the save point. He will be reconstructed by the save point after saving


Lighting

In the comments, Oliver Marsh was interested in the lighting, so I'll explain it a bit here. Basically it's doing the most straightforward thing possible. During the game update "PushRenderLight" can be called. This will add a light to a list of lights to be used for rendering that frame. A light consists of a position, a radius, an intensity value and some other location related data like roomId and layer. At the beginning of rendering, a uniform buffer is created and all visible lights are stored in this buffer.

When a tile or sprite is rendered, during the fragment shader, it loops over all lights in this buffer and calculates it's contribution to that pixel. All of the light contributions are added together. The lighting calculation I'm using is the one described in this answer

1
att = clamp(1.0 - dist*dist/(radius*radius), 0.0, 1.0); att *= att


I'm mostly using this as a placeholder, and am not overly happy with the results. Finding a nicer attenuation calculation is definitely on my to do list.

Overall the lighting is dead simple. At one point I did implement deferred shading with depth peels, but Nirion uses transparency quite a bit in the art and layer effects, so limiting the amount of alpha blends was a bit tricky. This seems fast enough for now during normal gameplay, so I haven't found a need to replace it yet.



That's All

I think that's most of the major stuff I've been working on. Upon adding save points, the game felt a bit more complete. You can save, die, and respawn at the last save point without issues. Right now I'm working on updating tilemaps and polishing the mines area. I'm hoping to have a reasonably complete demo of the mines and the first minor and major boss that I can show off to people. I'll also put a gameplay video together sometime in the next couple of days so people can see the game in action!

Comments

Looking real nice! Thanks for the in-depth post & explaining the lighting. Are you planning to add normal maps to the art (mentioned it on discord)?

Inspiring that your doing the music & sound effects aswell
Do you have any tips or resources on how to get started doing pixel art?
OliverMarsh
Looking real nice! Thanks for the in-depth post & explaining the lighting. Are you planning to add normal maps to the art (mentioned it on discord)?

Inspiring that your doing the music & sound effects aswell


Thank you!

I have actually already implemented normal maps on some things already. I don't think anything has normal maps implemented in the screenshots here, but in the last update they did. I've had some trouble getting lighting with normals looking good considering the perspective of the game. It made for a cool effect, but I'm not really sure how to make it look really good overall.

Here is a reddit post I made very early on with the effect:
https://www.reddit.com/r/gamedev/...t_lighting_using_normal_maps_and/

It's a cool effect, but I would have to go much deeper into lighting to get the entire scene to look nice I think. In the end, considering the extra work it takes to manually draw the normal maps, how it complicates the rendering process a bit(would need double the texture memory for compositing tilemaps for subpixel rendering now, one for diffuse colour, one for normals), and how it makes it harder for me to reason about my art while I'm still learning, I've pretty much scrapped it. I'm happy with the look of the game right now anyway, and for my next game I may invest a lot more time and effort into lighting.

You may not even notice the difference much from my last update which did have normal maps on some things(like the cave walls). This is because the approach was basically to light pixels based on their normals just by multiplying by the dot product of light direction and the normal, but if the pixel was within some radius of the light, light it anyway. This avoided dark areas like you can see in my reddit post and very crudely simulated ambient lighting. Unfortunately, this also made it harder to notice the effect.
OliverMarsh
Do you have any tips or resources on how to get started doing pixel art?


Probably the most important thing is to just jump in and start drawing stuff. Personally I did read up a little on some colour theory stuff, and some "tips" on how to do lighting and what things to avoid. I think approaching it more like "I'm going to drawing the light affecting this object" rather than "I'm going to draw this object" is a better mind set. The colours you choose are also very important.

Just googling "pixel art tutorials" and looking over some things there would be helpful. But yeah I think it's mostly just practice. I think I still have a long way to go, but stuff like the lighting and the tilemap composition in Nirion makes it look much better than the art actually is at times.

If you need any inspiration, then just look at how far ConcernedApe got just by practicing.