Progress Thread - Metroid-esque

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Progress Thread - Metroid-esque
by on (#183975)
As Windjammers has been announced for modern systems in 2017, I'm even less interested in building a clone of it. For a hackathon last weekend, I threw together a simple platforming game engine:

https://github.com/mikejmoffitt/famiplat

Image Image

The graphics are placeholders right now. Once I got it working to the extent it does now, I realized it would be satisfying to make a Metroid-type game.

I've re-used the animation engine from my Windjammers clone, so getting metatiles created and having the player animated was not a problem.

Here are my next tasks in order that I need to consider:

    * Better plan how to store nametables for rooms - NT compression? 16x16 metatiles? 32x32 metatiles? Description-style storage (like SMB)?
    * Create an object list format for rooms
    * Create structures representing arrangement of rooms
    * How does the player attack? Does the player attack?
    * What kinds of skills can the player gain, and how do they open up new areas?
Re: Progress Thread - Metroid-esque
by on (#183976)
CHR-RAM utilization is not too bad right now. Obviously the player is facing some serious fragmentation, but I can deal with that without too much trouble. For 12 unique animation frames, many of them larger than 16x32, I think the utilization of the space is reasonable.

Image
Re: Progress Thread - Metroid-esque
by on (#183984)
I really like that sprite. It does stand out in its new environment. So, maybe athletic/acrobatic powerups? That would be cool together with avoiding enemies. Slide through/under stuff, somersault for a different trajectory, stop jump trajectory for a quick fall-down (or up?!), cliff/rope hang and pull up/let go, you can probably come up with a lot within that theme.

If just avoiding enemies proves to be too plain (hard to know) in itself but you like it to be a feature somehow, how about that the only weapons you get are sub weapons? One at a time, and/or expendable, or timed.

Is there a reason for the two very similiar grays?
Re: Progress Thread - Metroid-esque
by on (#183994)
Sprite reminds me of Demon Sword (it's the "angled" running stance -- look at the legs).
Re: Progress Thread - Metroid-esque
by on (#184000)
WheelInventor wrote:
I really like that sprite. It does stand out in its new environment. So, maybe athletic/acrobatic powerups? That would be cool together with avoiding enemies. Slide through/under stuff, somersault for a different trajectory, stop jump trajectory for a quick fall-down (or up?!), cliff/rope hang and pull up/let go, you can probably come up with a lot within that theme.

If just avoiding enemies proves to be too plain (hard to know) in itself but you like it to be a feature somehow, how about that the only weapons you get are sub weapons? One at a time, and/or expendable, or timed.

Is there a reason for the two very similiar grays?


Acrobatic things are definitely good choices. I have trouble justifying things like wall-jumping, sliding, or somersaulting as a powerup (because why can't a humanoid character do these things anyway??) but I would still favor including them because good gameplay >>>>> story-justifiable powerups. Definitely these sorts of things add a lot to exploration, regardless.

It would be interesting to create a good metroid-like where the character does not actually directly have a weapon. I like the idea of weapons being a product of the environment, or limited use, in support of that idea. I am presently also working on Lyle in Cube Sector's Genesis / MD port, which (up until later in the game) the player's only means of attacking are throwing chunks of the environment at enemies.

As for the grays, I did almost all of my testing on my NES, where they were more distinguishable. In YY-CHR's palette they are distinguished too. I noticed that they are kind of crap in the emulator, but didn't bother to change it in time, in favor of more pressing things. I probably won't use much of the environment I drew for this, as it's just stuff I came up with for proof of functionality.
Re: Progress Thread - Metroid-esque
by on (#184005)
Just by eyeball, I guessed the palette in question was 0F 00 00 10. If they are actually distinct then one of those colors is an xD color. Column D is problematic for three reasons:
  • FCEUX shows $1D as dark gray, when it's actually the same voltage as $xE/$xF (except subject to emphasis, unlike $xE/$xF). This causes things drawn in $1D to be visible on an emulator but not on hardware. This discrepancy seriously confused the background artist for Haunted: Halloween '85.
  • The RGB PPU, used in Vs. System, PlayChoice, Famicom titler, Famicom TV (but not NES TV), and older NES RGB mods before the PPU's color index output mode was fully characterized, treats column $0D as all black.
  • Many fade routines work by subtracting multiples of $10. Hitting $0D causes some TVs to distort the image or even lose sync.

main.asm#sample_palette_data confirmed my suspicion: the palette is 0F 2D 00 10. On NES, $2D is close to 30% luma, with $00 at 40% and $10 at 70%. But even though a difference of 10% in luma is clear on a good composite connection, some TVs have a coax input but no composite input. (My first guess is that 1995-2015 was the sweet spot for a guarantee of working composite input.) RF is more likely to smear fine details like this.

So if you do use $2D, remember these caveats: It'll be black on older RGB mods, and you'll need to special-case it in your fade routine.
Re: Progress Thread - Metroid-esque
by on (#184007)
tepples wrote:
Just by eyeball, I guessed the palette in question was 0F 00 00 10. If they are actually distinct then one of those colors is an xD color. Column D is problematic for three reasons:
  • FCEUX shows $1D as dark gray, when it's actually the same voltage as $xE/$xF (except subject to emphasis, unlike $xE/$xF). This causes things drawn in $1D to be visible on an emulator but not on hardware. This discrepancy seriously confused the background artist for Haunted: Halloween '85.
  • The RGB PPU, used in Vs. System, PlayChoice, Famicom titler, Famicom TV (but not NES TV), and older NES RGB mods before the PPU's color index output mode was fully characterized, treats column $0D as all black.
  • Many fade routines work by subtracting multiples of $10. Hitting $0D causes some TVs to distort the image or even lose sync.

main.asm#sample_palette_data confirmed my suspicion: the palette is 0F 2D 00 10. On NES, $2D is close to 30% luma, with $00 at 40% and $10 at 70%. But even though a difference of 10% in luma is clear on a good composite connection, some TVs have a coax input but no composite input. (My first guess is that 1995-2015 was the sweet spot for a guarantee of working composite input.) RF is more likely to smear fine details like this.

So if you do use $2D, remember these caveats: It'll be black on older RGB mods, and you'll need to special-case it in your fade routine.

Good notes on the palette choice. Fortunately, I have no plans on applying any automated fade routines (or maybe fade routines at all). Much of my testing was done with the NESRGB, where some palettes gave different results. I acknowledged early that the color I used was problematic, but I chose to keep it just for the sake of the hackathon demonstration (where it looked good). I'll be sure to be more prudent about palette choices going forwards.

I have a few game design decisions as well: Do I want to have many non-scrolling 32x30 tile rooms, 64x30 two-screen H scrolling rooms, 32x60 two-screen V scrolling rooms, or longer variants? The advantages to the first three is that the room has only to be drawn once, on room entry. I know rainwarrior's Lizard uses the second approach, of small two-screen H scrolling sections, while Metroid switches mirroring schemes between areas to have flexibility with the shape of the room. Of course, one tiny advantage of the 32x30 room choice is that the player's position only needs to be 8 bits. I may change my fixed point positioning format to a 12.4 format, from the 8q8 I have now.
Re: Progress Thread - Metroid-esque
by on (#184100)
I thought a little more about storage. I think uncompressed nametables might actually be okay, if I use all 16 UNROM banks.

Each nametable is 1024KB, or 4 pages. For each nametable (from here on, a room) I need to store some metadata, so the total structure for each room can be:
Code:
* Nametable data (960 bytes)
* Attribute data (64 bytes)
* Room ID (2 bytes)
* Object List: for (max_objects = 30):
* -->Object type (byte)
* -->Object data/flags (byte)
* -->Object X pos (byte)
* -->Object Y pos (byte)
* World Map X pos (byte)
* World Map Y pos (byte)


With this, each room is 1280 bytes. That means I can fit 25 rooms per UNROM bank, with 768 bytes to spare. So, that means I can dedicate a large chunk of UNROM banks to just storing level data. With 12 banks, I can fit 300 rooms.

Alternatively, I could store only 28 rows of a 30 row nametable. That would make me lose the top 2 rows of tiles, but I would be able to fit an entire level structure within 1024KB, which would allow my UNROM banks to be very neatly divided (32 rooms per bank). Losing the upper 16px isn't a big deal, as many TVs overscan most of it anyway. I may go with this in the end.

A 100% dense 20 x 15 room world map would be the max size, but many games of this type don't fill 100% of a square area. So, I think I can create a sufficiently large world this way using just uncompressed nametables. If I felt super-constrained, I could A) implement the most basic compression, or B) use UNROM_512 for 32 banks, like Battle Kid does. Bankable CHR could let me do some simple environmental animation without eating NMI time, which would be appealing.

I may be able to forego the Room ID, but as I plan on having over 256 rooms I'd like to ensure I can access rooms without relying on a lookup table.
Re: Progress Thread - Metroid-esque
by on (#184109)
Quote:
while Metroid switches mirroring schemes between areas to have flexibility with the shape of the room.


There's a lot of unlocked potential in the switching approach of Metroid. False corridor stops, enable/disable scroll events, switch flip flop trigs (through player positioning, events, timing). Downside: more code and testing needed.

I think the biggest flaw with non-scrolling or h-scrolling only is how jumping from one v-level to the next may cause frustration if not carefully planned in the level design. Same goes for enemy placement, naturally. Otherwise, i can't think of anything else at the moment. It may also be easier to plan out player vs enemy interaction; someting battle kid shows.

Quote:
(because why can't a humanoid character do these things anyway??)

I think this metroid commercial demonstrates a case of the opposite. If the acrobatic skill set is unlikely, there may not be a need for a story other than 'supernatural powerup'. But that is maybe not what you're going after.

Quote:
It would be interesting to create a good metroid-like where the character does not actually directly have a weapon. I like the idea of weapons being a product of the environment, or limited use, in support of that idea.


For what it's worth, i really like this idea! Especially the "product of the environment" part. That sounds like a selling feature.
Re: Progress Thread - Metroid-esque
by on (#184130)
Forgive me if I'm wrong, but I think your math is wonky.

mikejmoffitt wrote:
all 16 UNROM banks

UOROM has 16 banks, UNROM has 8 banks, and IIRC entries wanting to get on the compo cart must use only 4 banks.

mikejmoffitt wrote:
Each nametable is 1024KB, or 4 pages.

1024 bytes, not 1024 kilobytes.

mikejmoffitt wrote:
With this, each room is 1280 bytes. That means I can fit 25 rooms per UNROM bank, with 768 bytes to spare.

Each UNROM bank is 16K = 16384 bytes. 16384 / 1280 = 12.8 rooms per bank.

mikejmoffitt wrote:
Alternatively, I could store only 28 rows of a 30 row nametable. That would make me lose the top 2 rows of tiles, but I would be able to fit an entire level structure within 1024KB, which would allow my UNROM banks to be very neatly divided (32 rooms per bank).

1024 bytes, not 1024 kilobytes, and 16 rooms per bank.
Re: Progress Thread - Metroid-esque
by on (#184141)
You're correct, I meant to put bytes. I suppose I mean UOROM then. The only real difference is the routing of one address line anyway. That's a bummer about the compo cart, and the bank capacity though. I think the 1024B format with UNROM_512 might be what I will go with.
Re: Progress Thread - Metroid-esque
by on (#184615)
I've implemented a basic RLE algorithm and made some compression tools to allow more nametables to be fit:
Image

I've played with palettes a little more, and tested my results on both my NESRGB and on the Famicom with composite. The FCEUX palette is rather garish, and I'll probably want to supply a custom one to improve testing.

In decompressing my nametables, that means I can't just point the collision checks at the raw nametable any more, and instead I must store a decompressed copy in RAM (or re-run the RLE, which is not good for performance). Is there any reason UNROM can't have 8KB of WRAM added?
Re: Progress Thread - Metroid-esque
by on (#184617)
No reason it can't, it just costs extra money for production.

Hamtaro126 just successfully petitioned for FCEUX to grow support to enable PRG-RAM on UNROM using a proper NES2.0 header, so.
Re: Progress Thread - Metroid-esque
by on (#184618)
Another is to decompress directly from ROM to VRAM, but keep in RAM enough information to process the collision. If solid and empty are the only collision types for a map of (say) 32x26 cells, this takes (32/8)*26 = 104 bytes of RAM. Some other games may have more collision types but restrict the geometry to 16x16 pixels per cell. This allows storing 16x13 cells in 208 bytes, as seen in Super Mario Bros. which caches a two-screen sliding window.
Re: Progress Thread - Metroid-esque
by on (#184623)
tepples wrote:
Another is to decompress directly from ROM to VRAM, but keep in RAM enough information to process the collision. If solid and empty are the only collision types for a map of (say) 32x26 cells, this takes (32/8)*26 = 104 bytes of RAM. Some other games may have more collision types but restrict the geometry to 16x16 pixels per cell. This allows storing 16x13 cells in 208 bytes, as seen in Super Mario Bros. which caches a two-screen sliding window.

I'm actually decompressing straight to VRAM, and shadowing the decompression to RAM just for storage. I've considered bit-packing several tiles into one as you've mentioned, but I expect I'll want a few more tile types, and I don't want to back myself into a refactoring corner. I have 8x8 geometry, so storing quad-tiles doesn't do much unfortunately. I might use one nybble per tile, to cut the space in half.

It looks like my Everdrive cooperates with 8KB PRG RAM specified in the header (starting at $6000, as it generally does). FCEUX 2.2.3 does not like this, however. I may stick with this solution, which will especially be appealing if I decide to switch to a scrolling setup.
Re: Progress Thread - Metroid-esque
by on (#184664)
I personally use 16x16 metatiles for level data and collision. I store the screens using RLE and decompress when the player enters the room (which may be 2 scrolling screens or 1 screen).

The decompression routine updates both VRAM *and* a metatile buffer in RAM, which I later use for collision. The size of this buffer is pretty manageable in the built-in 2Kb of RAM. I've never run out of RAM.

16x16 metatiles are mapped. They reuse the same patterns once and again so I can have the variety I need while keeping the room size small.