Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

Blades of the Lotus - Ninja Platformer

A topic by Matt Hughson (NES Dev) created Apr 29, 2022 Views: 740 Replies: 10
Viewing posts 1 to 8
Host (3 edits) (+1)


Welcome to the devlog of our game "Blades of the Lotus", a side-scrolling ninja platformer!

I'm working with Abdel Oliveira (https://twitter.com/abdeloliveira80) to help bring his abandoned PC project to where it really belongs... on the NES!

Obviously the game will need to evolve for both the system, the controller, and just my own design sensibilities, but you can see there is a really great core in that PC demo to work from!

Development Details:

  • Targets Mapper 28 (Action 53) directly, rather than one of the supported discrete mappers.
  • 64KB PRG-ROM + CHR-RAM (CHR bank swapping for background animation).
  • Written in C (CC65) using NESLib and NESDoug libraries, with support from Norill for Action53 C APIs.
  • Famitone5 sound engine (also by nesdoug)

Current Status:

Things are very early. I just started last night, and so far it's just the main character standing stoicly, hair blowing in the wind. 馃榿

Next step will likely to be get basic movement in place, and then I will start looking into scrolling, something I haven't really done yet.

I'll make sure to keep this top post updated with the "latest and greatest" so that you don't need to scroll to the end to find the current state, but I'll regularly post minor updates throughout development as well.

Thanks for checking out the game!

(+1)

hi man, thanks for taking this stuff and turning it into something cool!

I've never really been involved in the production of a real NES game, so it's really exciting. :)

Host (1 edit) (+2)

This isn't exhaustive, but here's a look at most of the animations from the PC build of the game. Fitting this into the NES is going to be a challenge.


(+2)

It'll be a challenge for sure - but maybe not as much as you might think at first glance. 


There's a lot of repetition in these tiles, and running it through Tilificator, it comes out at just 281 tiles.

 

So in total around 4.5kB, and < 10% of the 64kB PRG limit for the compo. :)

And that's still with quite a few fixable problems left. Some colors will be need to be moved around to make sprite overlays work - or you might want to ditch the overlays altogether for less sprite flicker, as the skin / white difference is quite subtle anyway. Some lone pixels can also be trimmed away without it being too noticeable.

But you'll definitely need a dynamic CHR streaming system if you want to keep all these animation frames. I think it's doable to get most of the animation frames around 8 tiles, and for those frames that overflow this budget you might want to fit them statically.

You might want to consider using Tilificator at least for an initial triage. It's often pretty decent at finding ways to re-use tile data in metasprites - although it can't compete with a dedicated artist's hand-optimizations :)

Host

Neat. I haven't used that program before. I'll check it out!

If you do, be sure to grab this recent build: https://ci.appveyor.com/project/michel-iwaniec/tilificator/builds/43394978/artif...

(I still need to make a newer official release that has some of the new features / bugfixes... but some OS-specific regression with multi-select kept me from cleaning that up)

There's also a quick tutorial here: http://retrocoder.epizy.com/tilificator_tutorial/?i=1

Host (1 edit) (+2)

It's not much to look at, but I have "meta tiles" (collections of tiles in 2x2 layout) loading in now with proper attributes (color). This is using a similar workflow to what I used in Witch n' Wiz, which is a collection of python scripts which parse NESST nametable files (*.nam), and additional data from a TiledEditor "tileset" (collision info, etc).


I had implemented a bit of scrolling, but it wasn't using the metatiles, so it was a bit of a dead end. I was able to do batch copies to VRAM that I won't be able to do with MetaTiles most likely, so I removed that scrolling code and will start with a "proper" implementation tomorrow.

Host (1 edit) (+2)

Proper horizontal scrolling is now in place. It is updating both the tiles graphics as well as the attribute table (colors) dynamically as the player walks.


I'm debating if I want to implement backtracking or only allow moving left to right. Currently it allows you to backtrack to the edge of the currently visible nametable, and to go beyond that would require more complex tile streaming logic.

I also haven't decided if I want to take on vertical scrolling as well. That is notoriously difficult on the NES, and I think it might not be worth the effort for this compo entry. I would probably do something more like Mega Man, where there are some vertical sections, but they are only one screen high.

As you may have noticed, there isn't actually any collision yet, and in reality the player has no logic at all (beyond playing a walking animation). I'll be getting her moving around for real next, and hopefully start on world collision too.

Host (2 edits) (+2)

Player movement, jumping and collision are now implemented!


To make the game easier to program I'm using 32bit numbers for the positions, with fixed point math breaking that up into 2 parts. 

The first 16 bits are the whole number: the actual position on screen, and the second 16 bits are used as a fractional value. The pseudo-floating point number allows for smoother, "sub-pixel" movement, like gravity pulling on the player when they jump. 16 bits is overkill for the floating point, but I wanted to have 16 bits for the whole part of the position so that I can fully represent the player's position in world space. This makes all other calculations much easier to understand, because I do all calculations in world space, and only rendering cares about nametables, and screen position offsets.


This features the obvious things like animation, jumping and collision, but there are some more subtle things going on as well like "coyote time" (allowing you to jump for a few frames after falling off a platform) and "jump buffering" (allowing you to press the jump button a few frames before landing, and still jumping).

The code for this is more or less a port of what was going to be my 3rd project (and may still be) after finishing Witch n' Wiz. I just haven't had a chance to get back to it yet. Here is what it looks like. Blades of the Lotus is actually already well beyond what that project was doing!


Host (2 edits) (+1)

Tonight was mostly focused on cleaning up collision detection and adjusting hitboxes to feel better after I create a more varied level layout. I also finally prevented the player for exiting out the left and right side of the map.


The most obvious change in the build is the addition of the title screen! This is just a first pass, but it's already looking pretty bad ass!


Host(+2)

Death Comes for us All

And what's an action game without death! So I've added pits and spikes to kill the player. And along with that comes a game over screen, and a proper flow in and out of the game back to the title screen, and back to gameplay again.

Clipping Sprites

You may have noticed in that last gif the strip of black tiles down the left side of the screen. This is a little trick of the NES to help with sprites "wrapping around" to the other side of the screen. 

Take a look at this old clip of the game. Notice how when the player walks into the left side of the screen, you can actually see their hand and foot popping out the right side of the screen.

The reason is a little technical but basically you can image the the sprite rendering loops at the edges, so when you try to draw a pixel off screen, it actually shows up on the opposite side of the screen. This happens in all directions, but is more pronounced in horizontal plane.

One way to fix this, and something that I have decided to do, is to use the hardware trick mentioned earlier to turn off the left 8 pixels of the screen. This gives me a little buffer to hide sprites in before the wrap around. The downside is that I lose 8 pixels of screen width, and it looks a little weird on a non-CRT (it's hidden beneath the bezel on most CRTs).

For the top and bottom, there is a similar issue. However, in the vertical plane there is already a 16 pixel buffer built into the rendering, so for that case I simply detect if the object is offscreen more than 16 pixels and if they are, I hide the whole meta-sprite. Ideally I would do this on an 8x8 sprite basis, rather than the entire object, but for my use cases, it works fine as is.

Here's the results:

What's Next?

I think next I'll work on pass-through floors (jump up through, but can walk on) and maybe breakable floors. The breakable case is interesting because currently all level data lives in ROM (Read Only Memory), and breakable floors would imply that the level changes (Writable), so I'll need to figure out something there.