Animating the background & Scripting

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
bleubleu
Posts: 108
Joined: Wed Apr 04, 2018 7:29 pm
Location: Montreal, Canada

Animating the background & Scripting

Post by bleubleu »

This is kind of 2 unrelated questions, so answers are probably going to be all over the place. Apologies in advance.

1) I was adding things like doors that open and closes with an animation, but are part of the BG. Kind-of like in river city ransom when you enter the shops. How do other games usually handle this? Do they hardcode everything? Do they store a series of update to apply the background? I was thinking of generalizing this a "background animation" that has a start/end state and some sprite updates in between. What are some games that animates the BG like that? Ideas, thoughts?

2) But doing that send me down the rabbit hole of "scripting". Let's say I want to have a button that opens a door. And once the door is open it stays open if come back to this room. Of course, from a software engineering standpoint, these are *very* simple problem, one option is to make special case for each of these, but I was wondering how NES games generalizes this idea of "scripting". Ex: When you talk to someone, the musics changes and it triggers a boss fight, when you collect 3 items, a door unlocks, when you kill a certain ennemy, a dialog starts, etc. RPGs do a lot of that. I was thinking of series of "commands" (which would probably be pointers in a jmp table) that are applied when an action is performed, that would kind of be like a mini-scripting engine. Suggestions?

Thanks guys.

-Mat
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Animating the background & Scripting

Post by Kasumi »

For 1: Have an object for every door. When the door object is created, it's initialized with a frame length as a timer, and the current frame, and where the door should go.
When the player touches the door object, destroy the player. Then push the tiles for the columns of the door to the PPU stack (with math based on the door's position so the right part of the background is updated). Next frame, the object logic runs again, decrements the timer. If the timer is 0, the object adds one to the current frame. The object pushes the tiles for the columns for this frame of the door. When animation frame > animation length, jmp to the new area. The columns of tiles don't even necessarily need to be hard coded. You could create some format for an arbitrary update and give the address for that data to the generic door object on creation as well. (Not unlike how you have to pass position to each object that's created.)

For 2: The tool for one of my games automatically assigns a bit to each object placed (say the game starts with all of them set). The object can do what it likes with this bit. Most clear it when they're killed, but you can get creative. On initialization, most objects check the bit they're assigned and destroy themselves immediately if their assigned bit is clear. 32 bytes of RAM is a bit for 256 objects. Assuming the game needed more, I'd tie the bit to each area. (So the first object in every area would get bit 0 in byte 0.)

But then each area would have an "offset" in the global RAM assigned to it, and then another byte which specifies the first bit that doesn't need to be saved in global RAM.
So...
A new area is loaded. It looks at that area's offset byte. Say it's 60. It copies 256 bits starting from the global RAM's bit 60 to some local RAM. Object's modify this local RAM as they like.Then the player leaves the room, it copies every bit to global RAM to 60 until it reaches the first number that doesn't need to be saved. (So you can have changes that reset every time you enter a room, and changes that don't.) If you've got a tool, you can just place enemies as either local or global and let the tool reorder their numbers (so local objects always get the higher bits in a room tied to them.)

Equinox on SNES basically ties room state to a collectible. Earlier, I mentioned how objects usually check the bit they're assigned, and destroy themselves immediately if their own bit is clear. Equinox enemies seem to not create themselves based on a bit for the whole room. (If you get a collectible, the collectible sets the room as completed and then enemies aren't created in it anymore.)

This only really covers single rooms. When the King needs to check if the dragon is defeated, you need... METAGLOBAL RAM! :lol: But realistically you won't need that much of it. In Indivisible I actually just manually assigned bytes to things like "boss defeated". And the king could just check this outside the concept of the local/global room bits.

Supposing you REALLY wanted go full scripting, again, I'd handle things on the tool level. I'd add names for the things I want to be global, reference their names in the scripts, and have the tool export the bytecode and numbers.

I don't have much more condensed advice for scripting. But maybe check out Earthbound's control codes to get an idea of a way to lay things out: https://datacrystal.romhacking.net/wiki ... trol_Codes

The text dump for the game on this page: https://starmen.net/mother2/gameinfo/script/ (the first one, which has the control codes included)
may help understand how some of that stuff is used in practice.
Post Reply