A Few Various Questions

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

A Few Various Questions

Post by FinalZero »

(1) In this thread ( viewtopic.php?f=2&t=12831 ), tokumaru said:
I just tested in my crappy JavaScript implementation and guess what resulted in the smoothest movement? Adding 157 AND reversing the bits. That's with a velocity of 0.25, at least.
I don't understand what "adding 157 and reversing the bits" means. If I understand correctly, 157 is the bias, which is added to the subpixel velocity, and if the result exceeds 256, then the pixel position is incremented. I don't understand when the reversing is done.
(2) In an rpg like Dragon Warrior or Final Fantasy, or any game that has tile-based movement, how is movement between tiles made smooth? (If anybody remembers the game "Chip's Challenge", it's a tile-based puzzle game that doesn't have transitions between tiles at all. I don't wish to copy it's jerky movement.)
(3) Again, in an rpg like Dragon Warrior or Final Fantasy (and all their sequels), (a) how is a map stored? (b) How would it *ideally* be stored? I assume you have one grid (an array of arrays) of tiles (grass, forest, desert, water, etc), but what about chests? Are they stored in the same grid? or a different grid? or an array? How do you store whether they've been looted or not? What about people that wander around? Are they in an array or a grid? If they're in an array, that'd mean you'd have to iterate the array when you press A to try to talk to whoever's in front of you (to find the one with the right location), but if they're in a grid, that'd mean you'd have to test each tile if it has a person so you can make them wander. I suppose the first sounds like the lesser of two evils.
User avatar
dougeff
Posts: 2875
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: A Few Various Questions

Post by dougeff »

I'm pretty sure the Dragon Quest games store treasure chest status in the SRAM (so when you save the game, it persists).

Every object will be given a relative X and Y position on the map. Each moving object (people in towns) will have to be kept track of in the RAM. Their 'state' will go from an 'auto-move to next tile over' state, to a 'decide where can I go next' state. Since the player controls the dragon warrior, the decision part will be a 'wait for controller input' state...then immediately into a 'auto-move to next tile over' state.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A Few Various Questions

Post by tokumaru »

FinalZero wrote:I don't understand what "adding 157 and reversing the bits" means. If I understand correctly, 157 is the bias, which is added to the subpixel velocity, and if the result exceeds 256, then the pixel position is incremented. I don't understand when the reversing is done.
I think I was explaining how I changed the fake global sub-pixel position each frame, but it's been a while. I'll take a look at the test code I write for this later today and I'll clarify this.
In an rpg like Dragon Warrior or Final Fantasy, or any game that has tile-based movement, how is movement between tiles made smooth?
I don't know if this is related to the first question, but let me get something out of the way: this normally doesn't have anything to do with sub-pixel movement, seeing as movement in grid-based RPGs doesn't use acceleration.

Anyway, the basic idea is that you move the characters pixel by pixel every frame, but only allow them to change directions or stop moving when they're perfectly aligned to the grid. If you want to allow diagonal movement, you need vertical and horizontal speed variables, which can have values -1, 0 or 1, which you add to the character every frame (if you don't want diagonal movement, just allow one of the speed variables to be non-zero). After moving, you check whether the character is aligned to the grid. This test consists in isolating the lower bits of the character's position to see if they are in the exact position necessary for the character's to be centered in a square of the grid.

For example, if the grid and the character's are 16x16 pixels large, and their coordinates represent their top left corners, you'd need to AND the vertical and horizontal coordinates with %00001111 and only when both results are 0 is the character aligned to the grid. This is when you'd check the controller and modify the speed variables accordingly.
Again, in an rpg like Dragon Warrior or Final Fantasy (and all their sequels), (a) how is a map stored? (b) How would it *ideally* be stored?
That varies a lot from game to game, since each game has different requirements.
I assume you have one grid (an array of arrays) of tiles (grass, forest, desert, water, etc), but what about chests? Are they stored in the same grid? or a different grid? or an array? How do you store whether they've been looted or not?
It depends. If the maps are stored in RAM, it's common to have these kind of items be part of the map. RPGs can have numerous large maps though, so even if you have a lot of extra RAM you won't be able to store every map.

For this reason, sometimes it makes more sense to store collectible items as objects, and use bits of RAM to indicate whether they've been collected or not. Each item should have an ID that you'd use to locate its state bit.
What about people that wander around? Are they in an array or a grid? If they're in an array, that'd mean you'd have to iterate the array when you press A to try to talk to whoever's in front of you (to find the one with the right location), but if they're in a grid, that'd mean you'd have to test each tile if it has a person so you can make them wander.
Moving objects should not be part of the map. The map might even contain "clues" indicating when/whete to spawn the objects (although having a separate list just for objects is the norm), but once they're "alive" they definitely shouldn't be considered part of the map.
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

Re: A Few Various Questions

Post by FinalZero »

Moving objects should not be part of the map. The map might even contain "clues" indicating when/whete to spawn the objects (although having a separate list just for objects is the norm),
Okay.
but once they're "alive" they definitely shouldn't be considered part of the map.
So, they'd be part of a separate list instead. Thus, talking would require iterating through the list of actors and checking whether the actor's location is in front of the player's location, (and if so, then triggering the dialog), right?
Anyway, the basic idea is that you move the characters pixel by pixel every frame, but only allow them to change directions or stop moving when they're perfectly aligned to the grid
Ah, that would make sense. But, I watched DW3's ram while playing a bit, and it seems to store the location of the current tile that the player is on! (at 0x0100 and 0x0101) Maybe it stores the pixel too, but if it does, I couldn't find where.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A Few Various Questions

Post by tokumaru »

FinalZero wrote:So, they'd be part of a separate list instead. Thus, talking would require iterating through the list of actors and checking whether the actor's location is in front of the player's location, (and if so, then triggering the dialog), right?
Yes, talking would be a matter of checking for collisions between a point slightly in front of the player and any actors that talk.
Ah, that would make sense. But, I watched DW3's ram while playing a bit, and it seems to store the location of the current tile that the player is on! (at 0x0100 and 0x0101) Maybe it stores the pixel too, but if it does, I couldn't find where.
If the characters move pixel by pixel, this information has to be stored somewhere, not necessarily close to the tile coordinates. One way to find where the pixel information comes from is to put a breakpoint in the OAM page and see how the sprite coordinates are being calculated.

EDIT: I took a quick look at the game (DWIII) and in the first room you can see the high nibble of the byte at $0116 change whenever the old guy walks, horizontally or vertically, so that appears to be the pixel counter for that object. I don't know if the main character has anything like that, since he's always at the center of the screen.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: A Few Various Questions

Post by AWJ »

tokumaru wrote:
FinalZero wrote:So, they'd be part of a separate list instead. Thus, talking would require iterating through the list of actors and checking whether the actor's location is in front of the player's location, (and if so, then triggering the dialog), right?
Yes, talking would be a matter of checking for collisions between a point slightly in front of the player and any actors that talk.
Ah, that would make sense. But, I watched DW3's ram while playing a bit, and it seems to store the location of the current tile that the player is on! (at 0x0100 and 0x0101) Maybe it stores the pixel too, but if it does, I couldn't find where.
If the characters move pixel by pixel, this information has to be stored somewhere, not necessarily close to the tile coordinates. One way to find where the pixel information comes from is to put a breakpoint in the OAM page and see how the sprite coordinates are being calculated.

EDIT: I took a quick look at the game (DWIII) and in the first room you can see the high nibble of the byte at $0116 change whenever the old guy walks, horizontally or vertically, so that appears to be the pixel counter for that object. I don't know if the main character has anything like that, since he's always at the center of the screen.
IIRC the Dragon Warrior games run on a schedule where you can only initiate movement on frames divisible by 16. The player's sub-tile position (= the scroll position of the screen) can be (and probably is) calculated from the direction he's moving and the global frame counter mod 16. Remember, the Japanese versions of the first two games in the series ran on cartridges without on-cart CPU RAM, so they had to pull every trick to minimize RAM usage.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A Few Various Questions

Post by tokumaru »

AWJ wrote:IIRC the Dragon Warrior games run on a schedule where you can only initiate movement on frames divisible by 16.
That would explain the unresponsive controls.
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

Re: A Few Various Questions

Post by FinalZero »

Remember, the Japanese versions of the first two games in the series ran on cartridges without on-cart CPU RAM, so they had to pull every trick to minimize RAM usage.
Could you explain what "on-cart CPU RAM" is?
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A Few Various Questions

Post by tokumaru »

FinalZero wrote:Could you explain what "on-cart CPU RAM" is?
An extra RAM chip inside the cartridge, so the game has more to play with than just the 2KB of RAM the NES ordinarily has. In most cases, that's 8KB of extra RAM, but some mappers are able to use more through bankswitching.
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

Re: A Few Various Questions

Post by FinalZero »

An extra RAM chip inside the cartridge, so the game has more to play with than just the 2KB of RAM the NES ordinarily has. In most cases, that's 8KB of extra RAM, but some mappers are able to use more through bankswitching.
How do you watch/monitor such RAM in an emulator? (I'm using FCEUX.)
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: A Few Various Questions

Post by tepples »

In FCEUX for Windows, open the Hex Editor and scroll to $6000. Work RAM on the cartridge lies between $6000 and $7FFF.
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

Re: A Few Various Questions

Post by FinalZero »

In FCEUX for Windows, open the Hex Editor and scroll to $6000. Work RAM on the cartridge lies between $6000 and $7FFF.
Thank you.
I think I was explaining how I changed the fake global sub-pixel position each frame, but it's been a while. I'll take a look at the test code I write for this later today and I'll clarify this.
Are you able to clarify this yet?

Another question (not really NES-related): If you were to program Pacman (on any system), how would you classify the dots and pills that pacman eats? Would they be part of the map? or actors? I'm writing such a game, and I've already classified them as part of the map, but the more I think about it now, they ought to be actors, because the advantage of having an unchanging map is that you never have to update/edit it. I worry a bit about checking 100+ actors for collisions, but I suppose if a space shooter can do it, a pacman-like game can too.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A Few Various Questions

Post by tokumaru »

Totally forgot about the sub-pixel thing. I'll check in an hour or so.

As for map vs. actors, my advice is to always separate the map from interactive objects, provided the platform can handle the amount of actors needed.

EDIT: Here's my JavaScript test in its entirety:

Code: Select all

<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
	</head>
	<body>
		<div class="sprite" style="background: #000000; height: 50px; position: absolute; top: 80px; width: 50px;"></div>
		<script>
var $sprite = $(".sprite");
var numCount = 0;
var numSpriteX = 0;
var numVelocity = Math.floor(2 * 256);
var numTimer = window.setInterval(function () {
	var numBias = 0;
	numCount = (numCount + 157) & 255; //numCount = (numCount + 1) & 255;
	numBias |= (numCount & 0x01) << 7;
	numBias |= (numCount & 0x02) << 5;
	numBias |= (numCount & 0x04) << 3;
	numBias |= (numCount & 0x08) << 1;
	numBias |= (numCount & 0x10) >> 1;
	numBias |= (numCount & 0x20) >> 3;
	numBias |= (numCount & 0x40) >> 5;
	numBias |= (numCount & 0x80) >> 7;
	numBias += numVelocity;
	numSpriteX += numBias;
	$sprite.css({ "left": Math.floor(numSpriteX >> 8) + "px" });
	if (numSpriteX <= 0) window.clearInterval(numTimer);
	numVelocity -= 1;
}, 1000 / 60);
		</script>
	</body>
</html>
So yeah, the bias in this case calculated by mirroring the bits of a counter that's incremented by 157 every frame. I haven't actually used this for anything, I just made this one test program, so I can't comment on the effectiveness of this in an actual game.
User avatar
FinalZero
Posts: 152
Joined: Thu Dec 03, 2009 7:27 am
Contact:

Re: A Few Various Questions

Post by FinalZero »

So yeah, the bias in this case calculated by mirroring the bits of a counter that's incremented by 157 every frame. I haven't actually used this for anything, I just made this one test program, so I can't comment on the effectiveness of this in an actual game.
Ah, so the counter is incremented by 157 instead of 1. That makes sense.

I may use this in my pacman game; I'll first get it working without the "dithering", and then assess whether the movement is smooth enough.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: A Few Various Questions

Post by rainwarrior »

FinalZero wrote:Another question (not really NES-related): If you were to program Pacman (on any system), how would you classify the dots and pills that pacman eats? Would they be part of the map? or actors? I'm writing such a game, and I've already classified them as part of the map, but the more I think about it now, they ought to be actors, because the advantage of having an unchanging map is that you never have to update/edit it. I worry a bit about checking 100+ actors for collisions, but I suppose if a space shooter can do it, a pacman-like game can too.
When you want to have 100+ of a thing on screen, my advice is to stop trying to fit that thing into some generic category and just make it something special. Make a "dot" system, don't try to shoehorn them into something else. Every game has its own unique demands, generic containers and frameworks usually aren't good enough.
Post Reply