Torches, Darkness, and Backgrounds?
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Torches, Darkness, and Backgrounds?
Hello,
I have looked around NESDEV and elsewhere, but I have been unable to find any information on this topic so I thought that I would see if anyone here might be able to help. I apologize if this has been brought up before; perhaps I am searching using the wrong terms. Regardless, how would one go about programming a torch-like effect for the NES, like that found in Dragon Warrior or Faria (the cave areas)? Since the NES does not have multiple background layers, how did they accomplish blacking out the entire screen save the area illuminated by the torch/light? I cannot conceptually figure out how to achieve this, and it has been driving me a bit mad for the last day or two. Any help would be greatly appreciated, even if it is only a link to a thread that I might have missed when searching! Thanks.
I have looked around NESDEV and elsewhere, but I have been unable to find any information on this topic so I thought that I would see if anyone here might be able to help. I apologize if this has been brought up before; perhaps I am searching using the wrong terms. Regardless, how would one go about programming a torch-like effect for the NES, like that found in Dragon Warrior or Faria (the cave areas)? Since the NES does not have multiple background layers, how did they accomplish blacking out the entire screen save the area illuminated by the torch/light? I cannot conceptually figure out how to achieve this, and it has been driving me a bit mad for the last day or two. Any help would be greatly appreciated, even if it is only a link to a thread that I might have missed when searching! Thanks.
-
tepples
- Posts: 22993
- Joined: Sun Sep 19, 2004 11:12 pm
- Location: NE Indiana, USA (NTSC)
Re: Torches, Darkness, and Backgrounds?
One way is by rewriting the nametable in invisible areas to all-black tiles. Another way is by making one of the palettes all-black (or at least much darker) and rewriting the attribute table. NetHack does something similar with the single layer of monospaced text that a PC terminal provides.
-
tokumaru
- Posts: 12668
- Joined: Sat Feb 12, 2005 9:43 pm
- Location: Rio de Janeiro - Brazil
Re: Torches, Darkness, and Backgrounds?
I don't see any other options other than the ones tepples mentioned, along with black sprites to make the illuminated areas rounder. If you go with the attribute table solution, you'll end up needing a lot of sprites, because the basic units you can hide/show are 16x16-pixels instead of the 8x8-pixels you can do with the name tables.
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Re: Torches, Darkness, and Backgrounds?
Thanks for the help! I did not know if there might be some trick to doing this effect. I had not thought of using rounded sprites to smooth things out, thanks for the tip.
-
Dwedit
- Posts: 5257
- Joined: Fri Nov 19, 2004 7:35 pm
Re: Torches, Darkness, and Backgrounds?
Ultima IV combines nametable updates with sprites to mask off everything except the 3x3 block area in the middle of the screen.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Re: Torches, Darkness, and Backgrounds?
Oh yeah, if anybody knows of any other examples to study I would be more than appreciative. A nice technical explanation is simply an added bonus (thanks Dwedit!).
-
tokumaru
- Posts: 12668
- Joined: Sat Feb 12, 2005 9:43 pm
- Location: Rio de Janeiro - Brazil
Re: Torches, Darkness, and Backgrounds?
Chip 'n Dale 2 does it right before the title screen, and a level in Bucky O'Hare has the effect as well (BTW, this game is full of these neat little effects/tricks, check the rest of it if you're interested).
Chip 'n Dale uses an interesting (i.e. simple to implement) approach, but it only really works for silhouettes/1bpp images: the brick outlines and the silhouettes are black, but so is color 0, so you can't see anything until the spotlight, which is drawn behind the background (i.e. low priority sprites) overlaps color 0.
Bucky O'Hare is doing exactly the expected (which is harder to program than the trick above): name table stuff with sprites to smooth it out.
Chip 'n Dale uses an interesting (i.e. simple to implement) approach, but it only really works for silhouettes/1bpp images: the brick outlines and the silhouettes are black, but so is color 0, so you can't see anything until the spotlight, which is drawn behind the background (i.e. low priority sprites) overlaps color 0.
Bucky O'Hare is doing exactly the expected (which is harder to program than the trick above): name table stuff with sprites to smooth it out.
-
Gilbert
- Posts: 615
- Joined: Sun Dec 12, 2010 10:27 pm
- Location: Hong Kong
Re: Torches, Darkness, and Backgrounds?
I haven't really checked how it's really done, but I think Ys did this with the sprite thing too:
Skip to 1:00 and beyond.
The LP clip sucks because of those hi-res filters, but I didn't have time to search for better clips.
There are better screenshots here though.
One way to check how stuff are done is to use an emulator that you can toggle between displaying the sprite layer(i.e. pretty much every popular emulator).
Skip to 1:00 and beyond.
The LP clip sucks because of those hi-res filters, but I didn't have time to search for better clips.
There are better screenshots here though.
One way to check how stuff are done is to use an emulator that you can toggle between displaying the sprite layer(i.e. pretty much every popular emulator).
-
Denine
- Posts: 398
- Joined: Wed Feb 17, 2010 5:42 pm
Re: Torches, Darkness, and Backgrounds?
Linus Spacehead's Cosmis Crusade also do this, but the circle is smaller than examples above. Also, the operation in Linus is pretty simple-there's two palettes, one black and one with blue shades. the game updates attributes of name tables and uses sprites to smooth circle appearance(which is a technique explained by tepples in his first post in this thread)
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Re: Torches, Darkness, and Backgrounds?
Thanks! Those examples really help to get an idea of what can be done. I had forgotten about many of them, since they seem to be those difficult parts of games that I have tried to block from my mind
. I will post further questions as I try to get something similar to the nametable/rounded-sprites system working.
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Re: Torches, Darkness, and Backgrounds?
All right. I have had a chance to look into some of these examples a bit more thoroughly and figure out what they are doing, but I am still a bit fuzzy on how they are doing it. How does one change a great quantity of tiles like that on the fly, either using the nametable method or the attribute table method (the NN tutorials seemed to say that only a few could be changed this way without issue). Any help or nudges in the right direction would be great, and thanks again for the examples!
-
tokumaru
- Posts: 12668
- Joined: Sat Feb 12, 2005 9:43 pm
- Location: Rio de Janeiro - Brazil
Re: Torches, Darkness, and Backgrounds?
Do you mean when changing from normal view to spotlight mode and vice versa? I didn't look at all the examples mentioned, but for the most part there seems to be a delay long enough for the necessary updates.SoleGooseProductions wrote:How does one change a great quantity of tiles like that on the fly, either using the nametable method or the attribute table method (the NN tutorials seemed to say that only a few could be changed this way without issue).
In Bucky O'Hare for example, the flashing can be achieved by disabling background rendering (while leaving sprites enabled), which is practically instantaneous. Then later, before the spotlights appear, there's a good second or so where the background remains black, and that's enough time to progressively update the entire background in columns across several VBlanks like normal (you don't see it because background rendering is disabled). I assume the other games will have similar delays if they have to switch between modes on the fly.
Or do you mean updating several small areas (or one big area) of lit tiles? That shouldn't be a problem, because you only have to update the edges of the spotlights, that's not such a large amount of tiles and should fit under normal VBlank time.
-
SoleGooseProductions
- Posts: 29
- Joined: Mon Nov 11, 2013 2:23 pm
Re: Torches, Darkness, and Backgrounds?
I spent a lot of time messing around with this over the last few days, and am plain stuck. I managed to figure out how to do a spotlight with sprites, but what I would like to do is to accomplish a similar feature with the nametable or attribute method. To give some concreteness to the problem, I would like to create a light around the player that moves as he moves. In order to keep this as widely applicable as possible, let us say a 3x3 area, with him in the center. What type of routine would need to be written? The only experience that I have with updating background tiles on the fly is what was covered in the Nerdy Nights lesson on drawing a score to a few background tiles, one at a time (Week 9, I believe). To do a spotlight, I would imagine that a more complex routine would be needed since it will need to adjust to player movement. It will need to check player position, “turn on” the necessary tiles, and then wait for further movement. Once this occurs, the same steps will be repeated, but with the addition of “turning off” the tiles that no longer need to be lit. This seems pretty straight forward, but I do not know of a way to decide what needs to be turned on next without inputting each individual nametable address (and this would only work if the player moved exactly as I wanted him or her to move; not likely!). Additionally, how should the background data be written? Does it follow the same format that I have at the bottom of the file, or is it done differently since it is written on the fly. Initially I had a regular background that I was trying to darken, but it seemed to make more sense to start with a black background and then lighten the needed areas. If that is incorrect, please let me know. I can see it working either way, to be honest. Also, based on how to do these things, another question that comes up is if the method of drawing columns as found in the attached file is the best method (for those that feel like taking a look). Should columns instead be drawn directly onto the present nametable? I am guessing not, but I have no clue at this point. Hopefully this make sense, if not, just let me know. I have gone through several conceptual hurdles to get here, and there may be more in store. Helpful correction is always welcome. To summarize, the big questions are:
-What type of routine to use to update background data?
-How to write background data to the lit areas?
-Where to write background data?
Oh, and let me state that the code is mostly from BunnyBoy’s Advanced NN lesson on horizontal scrolling. I have rearranged it to be more structurally like an actual game (at least as I understand it). I have also replaced the Mario tiles with those done by Drag. Yes it is sloppy (on my part, not BunnyBoy’s), and not how I generally o things, but I wanted to keep it as trim as possible for those that feel like taking a look. If either of these files should not be posted, please let me know and I will figure out a different way to ask my questions. Sorry that there are so many questions, but I am guessing that they are all linked, so hopefully they fall into place. Pardon too the Matrix at the top of the screen, I had to make sure that it was not skipping columns (and it has been known to in other revisions). Thanks a ton for anyone willing to give me a hand with this
.
-What type of routine to use to update background data?
-How to write background data to the lit areas?
-Where to write background data?
Oh, and let me state that the code is mostly from BunnyBoy’s Advanced NN lesson on horizontal scrolling. I have rearranged it to be more structurally like an actual game (at least as I understand it). I have also replaced the Mario tiles with those done by Drag. Yes it is sloppy (on my part, not BunnyBoy’s), and not how I generally o things, but I wanted to keep it as trim as possible for those that feel like taking a look. If either of these files should not be posted, please let me know and I will figure out a different way to ask my questions. Sorry that there are so many questions, but I am guessing that they are all linked, so hopefully they fall into place. Pardon too the Matrix at the top of the screen, I had to make sure that it was not skipping columns (and it has been known to in other revisions). Thanks a ton for anyone willing to give me a hand with this
You do not have the required permissions to view the files attached to this post.
-
tokumaru
- Posts: 12668
- Joined: Sat Feb 12, 2005 9:43 pm
- Location: Rio de Janeiro - Brazil
Re: Torches, Darkness, and Backgrounds?
I haven't looked at the files yet (it's late and I'm about to go to sleep), but I can assure you that this will be somewhat hard if all your experience so far is replicating what you saw in tutorials. I assume you're not dealing with scrolling yet, right?
Well, you said that you couldn't think of a way to do this other than manually writing the addresses of the tiles you want to change, and surprisingly, that's not too far off. You will be making lots of small updates, writing several different addresses to $2006 to update all the tiles you need, but the addresses won't be hardcoded, you'll calculate them from the player's coordinates. Physics and drawing game objects are all about coordinates. All objects have coordinates, tiles have coordinates, the camera (you'll need one if you're making a scrolling game) has coordinates. Sometimes you need to convert coordinates of one kind to another, and this is basically what you need to do here.
You can probably keep treating the attribute tables like you have so far (load it once and forget about it, I'm guessing), since the technique is based on blanking/revealing name table data.
The first thing to do is detect WHEN to draw/clear tiles. Since you're dealing with 8x8 tiles here, it's reasonable to assume that you'll need to update the name table everytime your character moves 8 pixels, no matter the direction. To do this you can compare his old coordinates to his new coordinates everytime he moves. 8 in binary is 00001000, so whenever the 4th bit of a coordinate changes, that coordinate has crossed an 8-pixel boundary. Say that the X coordinate was 23 before he walked right, and it became 25 afterwards. If you look at those numbers in binary (23 = 00010111, 25 = 00011001) you'll see that the 4th bit was 0 and became a one, meaning that an 8-pixel boundary was crossed and it's time to update tiles. BTW, a good way to check if bits changed is to XOR (EOR in 6502 assembly) the values together: whatever bits are different will become 1's while bits that haven't changed will become 0s. Then you can isolate the bit of interest with AND #%00001000 and use BEQ (bit didn't change) or BNE (bit changed) to make a decision.
Once you know you have to update tile, it's a matter of calculating the coordinates of the tiles you'll need to change. Sprite/object coordinates are measured in pixels, background coordinates are measured in tiles, so you'll have to divide the sprite coordinates by 8. You probably know you can do this by shifting the values right 3 times. Then, once you have the X and Y coordinates of the player converted to tile units, you have to combine them using the following formula: NTADDRESS = BASE + Y * 32 + X. BASE is the base address of the name table... for example, $2000 is the first name table. You multiply Y by 32 because each row has 32 tiles, and you add X because that's how far into the row the tile is. This is all you have to do in order to find the address of the tile immediately behind your character. I know this is not the tile you want (you need the edges), but if you know the center you can surely add/subtract from it to find the edges.
Now, if your lit area is reasonably small, I would advise you to completely erase it and redraw it every frame, because the logic would be easier than detecting the direction of the movement in order to know which edges to update... I mean, if you can simply keep a copy of the old player coordinates and use those to clear all tiles around the player, and then use the new coordinates to draw the lit tiles, that would be much simpler.
Well, you said that you couldn't think of a way to do this other than manually writing the addresses of the tiles you want to change, and surprisingly, that's not too far off. You will be making lots of small updates, writing several different addresses to $2006 to update all the tiles you need, but the addresses won't be hardcoded, you'll calculate them from the player's coordinates. Physics and drawing game objects are all about coordinates. All objects have coordinates, tiles have coordinates, the camera (you'll need one if you're making a scrolling game) has coordinates. Sometimes you need to convert coordinates of one kind to another, and this is basically what you need to do here.
You can probably keep treating the attribute tables like you have so far (load it once and forget about it, I'm guessing), since the technique is based on blanking/revealing name table data.
The first thing to do is detect WHEN to draw/clear tiles. Since you're dealing with 8x8 tiles here, it's reasonable to assume that you'll need to update the name table everytime your character moves 8 pixels, no matter the direction. To do this you can compare his old coordinates to his new coordinates everytime he moves. 8 in binary is 00001000, so whenever the 4th bit of a coordinate changes, that coordinate has crossed an 8-pixel boundary. Say that the X coordinate was 23 before he walked right, and it became 25 afterwards. If you look at those numbers in binary (23 = 00010111, 25 = 00011001) you'll see that the 4th bit was 0 and became a one, meaning that an 8-pixel boundary was crossed and it's time to update tiles. BTW, a good way to check if bits changed is to XOR (EOR in 6502 assembly) the values together: whatever bits are different will become 1's while bits that haven't changed will become 0s. Then you can isolate the bit of interest with AND #%00001000 and use BEQ (bit didn't change) or BNE (bit changed) to make a decision.
Once you know you have to update tile, it's a matter of calculating the coordinates of the tiles you'll need to change. Sprite/object coordinates are measured in pixels, background coordinates are measured in tiles, so you'll have to divide the sprite coordinates by 8. You probably know you can do this by shifting the values right 3 times. Then, once you have the X and Y coordinates of the player converted to tile units, you have to combine them using the following formula: NTADDRESS = BASE + Y * 32 + X. BASE is the base address of the name table... for example, $2000 is the first name table. You multiply Y by 32 because each row has 32 tiles, and you add X because that's how far into the row the tile is. This is all you have to do in order to find the address of the tile immediately behind your character. I know this is not the tile you want (you need the edges), but if you know the center you can surely add/subtract from it to find the edges.
Now, if your lit area is reasonably small, I would advise you to completely erase it and redraw it every frame, because the logic would be easier than detecting the direction of the movement in order to know which edges to update... I mean, if you can simply keep a copy of the old player coordinates and use those to clear all tiles around the player, and then use the new coordinates to draw the lit tiles, that would be much simpler.