It is currently Wed Oct 23, 2019 7:22 pm

All times are UTC - 7 hours

Post new topic Reply to topic  [ 18 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: Backtracking
PostPosted: Wed Aug 01, 2018 9:46 am 

Joined: Sun Jun 25, 2017 3:32 pm
Posts: 18
Well, definitely not as dense as World 4-2.

I'm thinking maybe up to two chests, plus some breakable blocks, like 7 or 8 max, plus coins (well, ears of corn for the collectible, actually). So maybe 24 objects per screen max? That would be three bytes of status bits, per screen. Not really sure how big I'll go as far as screens per level, maybe as many as 6 to 10. So 32 bytes might be enough. That doesn't include enemies, but I'm kicking around the idea of having the enemies respawn if you backtrack.

 Post subject: Re: Backtracking
PostPosted: Wed Aug 01, 2018 1:54 pm 
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1289
Here's how... I think... Indivisible works. For keeping dead enemies dead. (It's probably slightly different in practice.)

I build the levels in some tool (like tiled) and place enemies, then export it. Then, a program I wrote builds the level data for the game.

A counter starts at zero. Every time an enemy is encountered, it puts the value of the counter in the game's data with the type and position of the enemy, then increases the counter.

Now every enemy has a unique number (a destroy number). When the enemy is created (scrolled to), that number is stored in the enemy's RAM (just like its position is).

The object loop starts. The enemy divides its destroy number by eight (three lsr instructions). That gives it which byte in the "alive state" RAM to check. It does a modulus eight (and #7), which gives it which bit within that byte corresponds to it.
lda destroyNumber,x;X is the enemy's index
lsr a
lsr a
lsr a;Divide it by 8
sta temp

lda destroyNumber,x
and #7;Anding by  (power of 2-1) is like modulus by the power of 2 number.
lda bytetable,y;This gives us which bit corresponds to our destroy number from within the alive state RAM
sta temp2

ldy temp;This lets us load the byte our bit is in in the alive state RAM
lda alivestate,y
and temp2;This will be non zero if we are alive, and zero if we are not alive.
beq destroyobject;If we're not alive, don't run or initialize the object. The player will never see it.
eor alivestate,y;This effectively "kills" us, by flipping the bit that says we're alive
sta alivestate,y;And storing it
;This prevents the same object from being created twice while one is still on screen.
;If the player kills the enemy/opens the chest/whatever, you destroy the object, but don't set the bit to one again.
;If the object simply scrolls of screen, set the bit again before you destroy it.
jmp endobjectinitialization
.db %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001

(That code may not be 100% right... I'll check it a bit later, and fix if so.) Edit: It's probably cool now.

With 256 destructible objects, you need only need 32 bytes as has been stated before. Even for things that you might want only as part of the background, you can still create invisible objects for them that update the screen conditionally.

You might also find this post interesting: viewtopic.php?f=2&t=17355&p=218452&hilit=script#p218452

Edit: That post covers a way you might store the bits on a screen to screen basis. But basically, it's that on screen load, you copy that screen's alive state RAM to a temporary 32 bytes from a larger block of it, then copy any changes back on level unload. (Each screen knows where it's alive state RAM starts within the larger buffer, because the offset is stored as part of the screen data.) So you have "only" 256 bits per screen/level, but your buffer can basically be as large as your total RAM.


 Post subject: Re: Backtracking
PostPosted: Wed Aug 01, 2018 2:47 pm 
Formerly WheelInventor
User avatar

Joined: Thu Apr 14, 2016 2:55 am
Posts: 2025
Location: Gothenburg, Sweden
Slightly inspired by metroid* (even though it applies this to a whole world), you could separate object data (always in ROM) from ”has been manipulated bits” (naturally in ram). The list details everything else we need to know.

4 bytes per object. TypeID, WhichScreen, Ypos, Xpos. Which objectID is implied by its place in the array. Lets say we use a page of ROM per stage, so 64 items per what you define as a stage could either be the whole level or a section.

or if you’re fine with lowered position granularity (which makes sense if all these objects are represented on the BG layer), you can bake X and Y into a single byte, and if you only have max 16 types and max 16 screens per stage, you can bitpack those as well. So, either 85 or 128 mauipulable background objects in that case. The one with the 85 is a bit of a problem since you can’t easily index into the right position as quick as possible with a simple power of two.

Then you have the list of toggle bits for your object. They’re bitpacked, so you need 8, 11, or 16 bytes of RAM to be overwritten next level. Assuming you only need one toggle state per object.

Maybe you can imply which are on which screen of the stage by their order in the array. Con: locks you to an evenly distributed number of manipulable objects per screens’ worth of data, rather than placing all of them freely. Pro: actually ought to make the code more straightforward. (If we’re looking up an object on screen n, use index (n*object size*objectsperscreen)+whichobject And you’d get even more objects or additional data (special properties?) per object; your choice.

Lastly, you could lower the X and Y granularity not to bitpack them both, but to imply which screen in a nybble, and which coarse position in the other (another bitpacking scheme).

That’s all the techniques i can think of on top of my head.

*note that metroid is only using this for obtainable items; not breakable blocks... which are overwritten by the scroll seam. The amnesia It works in metroid because it an alien planet that is kind of living. They even regenerate blocks with a timer which provides a rationale for blocks being reset when you backtrack.

_________________ - personal NES blog

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours

Who is online

Users browsing this forum: No registered users and 2 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group