Enemy coordinates relative to scrolling map...16 bit coords?

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
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Enemy coordinates relative to scrolling map...16 bit coords?

Post by GradualGames »

Say we wanted an enemy to be able to go "off screen" but still be firing at the main character, etc. It seems to me the best way to represent enemy coordinates then would be with 16 bits...8 bit would imply wraparound (which I suppose occurs in some games, such as Kid Icarus), or that the enemies simply disappear offscreen. I notice in SMB, the player can kick a koopa shell off screen a couple of tiles and have it bounce back. I wonder if it is using 16 bit coordinates? (at least for the X coord)
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

The ideal thing to do in any game that has worlds larger than a single screen (and is shown using scrolling) is giving all the objects 16-bit coordinates. Coordinates should always be relative to the level, not to the screen.

The camera should also be seen as an object, with its own 16-bit coordinates, so that you can calculate the screen coordinates of any object by subtracting the camera's coordinates from their own. If the result is outside of the 0-255 (X) and 0-238 (Y, although you could get away with 0-255 - which is much quicker to check for - as well, if you don't mind wasting a few sprites at the bottom of the screen) ranges, you know the objects are off screen (it's actually a bit more complex than that because you should verify if each sprite of the object is inside the screen or not, not entire objects).

The only case you can safely get away with 8-bit absolute coordinates is in games that show one screen at a time and the objects never go past the edges of the screen.

SMB probably uses 16-bit coordinates, so that objects can go off screen and keep making contact with the level map and continuing to exist even though they are not seen. Since that game only scrolls horizontally, the Y coordinate might be just 8-bit. It has to be 16-bit though if it is possible to jump past the top of the screen, for example. I don't recall if this is possible in this game.
Celius
Posts: 2159
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

I'm pretty sure that any game with physics should not rely on 8 bit coordinates. If you want something to accelerate, you don't want it to just accelerate from 1 to 2 pixels per frame; you'd want it to be able to move like 1.5 pixels per frame, which is possible with precision bits. I would actually recommend using 24 bit coords for things moving off screen, because you'd have 16 bits of absolute pixel values, then you'd have 8 bits of precision. Even if you don't need to use all 8 bits, it's probably faster to dedicate a whole byte to precision than making it a nibble of another variable.

I think precision is only important for movement of objects. For example, if you want to see if two objects are colliding, it's probably not worth the time to deal with their precision values. Just compare their absolute coords; the player will probably never know.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Oh yeah, Celius is right. I forgot to mention fixed-point sub-pixel precision. Like he said, dedicating another byte for that is faster than having to shift bits around. So yeah, in a very versatile engine, coordinates would ideally be 24 bits each.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

You can still get subpixel precision with 16-bit coordinates if you don't need velocity precision lower than 1/16 pixel per frame. This arrangement might even be friendlier to sprite-background collision:

Code: Select all

FEDC BA98 7654 3210
|||| |||| |||| ||||
|||| |||| |||| ++++- Subpixel
|||| ++++-++++------ Whole pixel
++++---------------- Map page

FEDC BA98 7654 3210
|||| |||| |||| ||||
|||| |||| ++++-++++- Sub-metatile
++++-++++----------- Whole metatile

User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post by Bregalad »

Yes, I had to modify my engine do it exactly what tepples is saying, and that is definitely the best ! It's flexible enough for collisions. I'd recommand that over any other system. Using 8-bit coordinates is terrible and should be avoided. The screen is exactly 256 pixles wide, but since most object are more than 1 pixl wide (obviously) you must use more than 8 bits to know if they are on the far left or the far right.
Useless, lumbering half-wits don't scare us.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

tepples wrote:You can still get subpixel precision with 16-bit coordinates if you don't need velocity precision lower than 1/16 pixel per frame.
But then levels can't be very large. Limiting their width and/or height to 16 screens would not be OK for many projects. If this is not a problem, then yes, I agree this is a good idea.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

tokumaru wrote:[With a range of 256 metatiles,] levels can't be very large. Limiting their width and/or height to 16 screens would not be OK for many projects.
Then interpret the coordinates in a 16-screen sliding window centered on the camera. This means you can't track things 8 screens away from the camera, but most commercial NES games appear to kill and respawn enemies that are even 1 screen away.
Celius
Posts: 2159
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

tepples wrote:You can still get subpixel precision with 16-bit coordinates if you don't need velocity precision lower than 1/16 pixel per frame. This arrangement might even be friendlier to sprite-background collision:

Code: Select all

FEDC BA98 7654 3210
|||| |||| |||| ||||
|||| |||| |||| ++++- Subpixel
|||| ++++-++++------ Whole pixel
++++---------------- Map page

FEDC BA98 7654 3210
|||| |||| |||| ||||
|||| |||| ++++-++++- Sub-metatile
++++-++++----------- Whole metatile

That's actually a good idea, like tokumaru said, if you don't mind being limited to 16x16 screens. I could actually benefit from this type of coordinate system, since my game has 8x4 screen rooms. But it might require some shifting to work with in some spots.

This actually will give me some good ideas for making collision detection easier, since lots of enemies will need to check for collision and for 1 collision detection (1 collision point) it costs like 130 cycles since I have to do shifting and bankswitching. So I'll definitely want to rethink this a little.
UncleSporky
Posts: 388
Joined: Sat Nov 17, 2007 8:44 pm

Post by UncleSporky »

I'm looking at this myself now. For me there was never any question of having some amount of subpixel precision since whole pixel speeds are always awkward. But the question is, how much? Right now I use 2 bits just for testing purposes which is sufficient in terms of speed, but other methods listed here make a lot of sense.

I like the way tepples laid out the 4 bit method, it seems quite enough to store a standard sized map and is metatile friendly. But I also like Celius's 8 bit precision, 24 bit coords, for the simpler screen operations and ultimate speed control.

However, 24 bit adds and subtractions get really bad, especially since you need to use 16 bit velocities for pixel movement greater than 1.

Code: Select all

clc		;16 bit add
lda y_coord
adc y_veloc
sta y_coord
lda y_coord+1
adc #0
sta y_coord+1

clc		;24 bit add
lda y_coord
adc y_veloc
sta y_coord
lda y_coord+1
adc y_veloc+1
sta y_coord+1
lda y_coord+2
adc #0
sta y_coord+2
But then again, assuming I'm not missing something simple, your code to pull out the screen position in 16 bit is always annoying:

Code: Select all

	lsr y_coord+1	;Discard subpixel precision...
	ror y_coord
	lsr y_coord+1
	ror y_coord
	lsr y_coord+1
	ror y_coord
	lsr y_coord+1
	ror y_coord
	lda y_coord	;24 bit skips to this step :)
And then there's the fact that every moving object in 24 bit obviously takes up an extra byte, unless a method can be used to treat enemies and such with less precision and remain compatible with the player object.

Any other thoughts on the subject? Any other methods that might work better, intermediate or counter-based?
Post Reply