This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Level numbering

Level numbering
by on (#61158)
Howdy. This might be a trivial problem, but I wanted to bounce some ideas off you guys.

In my game I have levels and sublevels, numbered in a scheme similar to SMB: 1-1, 1-2, 1-3, 2-1, 2-2, 2-3, 3-1, etc. I'm looking for input on how I should handle the numbering under the hood, considering that levels start from 1, but tables index from 0.

For the record, I use the level number as an index into a table of pointers to level data. The level data itself contains pointers to sublevel data.

I thought of a few solutions:

1) store level # in RAM as-is (ie, level 1 is #$01), and subtract one before indexing into tables
2) store level # in RAM as level-1 (ie, level 1 is #$00), and add one when displaying on the screen
3) store level # in RAM as-is (level1 = #$01), put dummy entries at the beginning of tables.
4) store level # in RAM as-is, and offset the start of the table:

Code:
level_table:
    .word level1, level2, level3 ;pointers to level data

;--in level load routine
    lda level
    asl
    tay
    lda level_table-2, y  ;offset table by 2
    ;blah blah blah


5) create a level 0 and use it as a bonus level or a demo level.

I don't really like solutions 1, 2 or 3 because they seem wasteful. Plus I potentially have a hard-to-find bug if I forget to make the adjustment somewhere. To me #2 seems the lesser of three evils.

Solution 4 isn't wasteful because the adjustment is made by the assembler, but it's still prone to bugs if I forget to offset a table somewhere.

Solution 5 works for levels, but not sublevels.

Any other ideas? How do commercial games usually handle this?

by on (#61160)
Add 1 to the number before you print it to the screen.

by on (#61161)
Well for my game the # of the levels in the computer is not the same as they appear to the player. If I were you I'd make it so that for the computer, level #0 would be the first, level #1 would be the second, etc... and then use a lock up table for displaying numbers of your levels/sub levels. If you don't want to use a lockup table you could do something like :
Sublevel = Level%3 + 1
MainLevel = Level/3 + 1

This will work but you are limited to exactly 3 sublevel per level (except the last one which could be 1 or 2), and I bet unless your game is really big the program doing the division by 3 would be almost as big as a lockup table.

by on (#61175)
Unless your program is absolutely tiny (as in NROM-128 tiny), you probably need division for some other reason and can reuse the subroutine.

by on (#61229)
I would use this scheme to bypass using a look-up table. LevelCounter would start at 1 and the display digits would result from simple math.

FinishLevel:
inc LevelCounter
lda LevelCounter
and #04h
bne @Skip
inc LevelCounter
lda LevelCounter
and #04h
@Skip:
sta SubLevelDisplayDigit
lda LevelCounter
lsr
lsr
sta WorldDisplayDigit

In other words, each world would have a dummy 4th level so you won't have to divide by 3.

edit: minor code change to remove redundant logic

by on (#61239)
tepples wrote:
Unless your program is absolutely tiny (as in NROM-128 tiny), you probably need division for some other reason and can reuse the subroutine.

So far I haven't though of anything in my game that will require division, and it's by no means a tiny project... multiplication, yes, I need it in a couple of places, but never division.

by on (#61240)
My current project requires division to calculate a slope as the first step of an arctangent calculation. Jeroen knows more.

ObTopic: I have gameDay, gameHour, gameMinute, gameSecond, gameTenthSecond, and gameSubTenth. At the start of each level, I form the level number as gameDay * 5 + gameHour.

by on (#61253)
Thanks everyone. I'm going to have levels start from 0 internally and just do a conversion when displaying to the player.