Position sprites with 12 bits instead of 10?

If you have feature requests, this is the place to post them. Please note your idea may already be something we have already discussed and decided against, or something we are working on privately, and we cannot be held responsible for any similarities in such instance. Whilst we cannot respond to every suggestion, your idea will be read and responded to where possible. Thank you for your input!
Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Position sprites with 12 bits instead of 10?

Post by Johan Kårlin »


Well, I don't know if this really is a feature request. It is not at all important, but I think it's something worth to notice at least...

Sprites are positioned with 10-bit value (0-1023). Tilemaps are scrolled with 12-bit values (0-4095). It seems logical because the highest screen resolution is 640x480 pixels and tilemaps are at most 4096 pixels wide or high.

But let's say we're making a game that uses a tilemap that is 2048 pixels wide (128 tiles and a tile size  of 16 pixels). Somewhere on the map is the player in a spaceship represented by a sprite. On different locations on the map are about 10 enemy spaceship sprites. When playing, the screen will act as a window into this "world" centered on the player's sprite. Scrolling the tilemap is easy, you just set the scroll values for the tilemap  based on the player's position. Positioning the sprites are (almost!) as easy. The player's sprite will always be in the middle of the screen. All other sprite positions are easily calculated by subtracting the player's position. You position them by setting each sprite's x- and y-value. If they shouldn't be visible they won't, they will simply end up outside the visible area of the screen.

Now you might think you are doing just fine. But this is not really the case. Because the tilemap wraps at 4096 and sprite positions at 1024. This means for example that an enemy spaceship that holds its position will turn up twice when flying from the left end to the right end of the tilemap. Therefore (if someone is still with me) it seems more logical and consistent to use 12 bits both for scrolling tilemaps and placing sprites.

I absolutely understand that this is not at all hard to compensate for. I also know that in many cases it is wise to let the model have a coordinate system that is completely separated from tilemap and screen coordinates. But still, there are 6 unused bits left in the memory addresses that hold sprite positions, why not use two more of them? 

SlithyMatt
Posts: 913
Joined: Tue Apr 28, 2020 2:45 am

Position sprites with 12 bits instead of 10?

Post by SlithyMatt »


Scrolling doesn't affect sprites, so it's position is always relative to the screen corner, not the corner of any layer. Each sprite is like a layer to itself, and since the maximum screen resolution is 640x480, it makes no sense to use more than 10 bits. Hell, you really only need 9 bits for the Y value.

Anyway, that's just how 2D sprites work. It's not like an independent geometric object in a 3D scene that is subject to the same camera movement as the background.

StinkerB06
Posts: 74
Joined: Tue Jun 30, 2020 12:32 am

Position sprites with 12 bits instead of 10?

Post by StinkerB06 »



24 minutes ago, SlithyMatt said:




Hell, you really only need 9 bits for the Y value.



Actually, it's necessary to have a 10-bit Y value, at least for sprites that are 64 pixels tall. The sprite would be pushed into the bottom of the screen at Y position 480, but at the same time, would also represent a position of 480 - 512 = -32. This would not be suitable if you want to push the whole sprite off the top or bottom edge of the screen, and at 32 pixels cut off, the sprite would appear on the opposite side when you probably don't want it to.

User avatar
StephenHorn
Posts: 565
Joined: Tue Apr 28, 2020 12:00 am
Contact:

Position sprites with 12 bits instead of 10?

Post by StephenHorn »



27 minutes ago, StinkerB06 said:




Actually, it's necessary to have a 10-bit Y value, at least for sprites that are 64 pixels tall. The sprite would be pushed into the bottom of the screen at Y position 480, but at the same time, would also represent a position of 480 - 512 = -32. This would not be suitable if you want to push the whole sprite off the top or bottom edge of the screen, and at 32 pixels cut off, the sprite would appear on the opposite side when you probably don't want it to.



In fact, r37 had a bug because the VERA code was specifically failing to respect all 10 bits of the Y coordinate, causing 64-tall sprites to wrap to the top of the screen before scrolling off the bottom of it. This appears to be fixed with r38 - my Spiral demo was an effective demonstration of the bug, and the program now has correct sprite behavior.

Developer for Box16, the other X16 emulator. (Box16 on GitHub)
I also accept pull requests for x16emu, the official X16 emulator. (x16-emulator on GitHub)
Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Position sprites with 12 bits instead of 10?

Post by Johan Kårlin »



2 hours ago, SlithyMatt said:




Scrolling doesn't affect sprites, so it's position is always relative to the screen corner, not the corner of any layer. Each sprite is like a layer to itself, and since the maximum screen resolution is 640x480, it makes no sense to use more than 10 bits. Hell, you really only need 9 bits for the Y value.



Anyway, that's just how 2D sprites work. It's not like an independent geometric object in a 3D scene that is subject to the same camera movement as the background.



Thanks for your answer but this is not really what I am talking about. Sorry, it is hard to explain. Take a look at this drawing:

1528717669_defender(Custom).png.9b821997e1d4b4fcd032ce194bc9819c.png

We are just interested in x values for now. This is some kind of Defender clone with a tilemap that is 4096 pixels wide and it wraps around. The player is positioned at x position 100 and there are four enemy ships. How do we calculate the sprites' positions on screen? It seems really easy and consistent. Just take the distance between the enemy ship and the player and add 160. At first it seems to work, ship 4 even wraps nicely and turns up at  x position 14. BUT there is one problem, ship 3 will (maybe surprisingly) appear at x position 236 (in other words be visible). This is because the tilemap wraps at 4096 and the positioning of sprites at 1024. 1260 - 1024 = 236. What I am saying is that if sprites was positioned with 12 bits instead of 10, this easy way above of calculating sprite positions would work. Now, at least less experienced game programmers like myself might find themselves in situations where sprites suddenly appear at random places : ).    

StinkerB06
Posts: 74
Joined: Tue Jun 30, 2020 12:32 am

Position sprites with 12 bits instead of 10?

Post by StinkerB06 »


Do you not know how to code your own double-precision min/max functions?

SlithyMatt
Posts: 913
Joined: Tue Apr 28, 2020 2:45 am

Position sprites with 12 bits instead of 10?

Post by SlithyMatt »


There is no wrapping of sprite positions, they just go off screen. I wrote some simple code for Chase Vault that figures out a sprite position relative to a tile layer. If you are doing something like Defender, you have a tile layer for the terrain as you fly over, and sprites for flying enemies. You scroll the tile layer continuously horizontally until you get to the end of the level. The player sprite can stay fixed at a specific X position, like 100, and just have the tile layer scroll to show horizontal movement, but the sprite goes up and down. Enemies can just fly in at whatever speed you want. If they are hovering over the terrain, then they need to move with it. If they are free flying, then do whatever you want. If you make their X bigger than the screen width, they will simply disappear. If they fly all the way to the left, they will disappear again by having the X position wrap around to 1023 after decrementing from zero.

It seems you are just overthinking it. Simply keep track of the scroll range in the terrain where they show up, make them appear when you get there, and then have them follow a path. You can make that path relative to the scroll position with simple addition or subtraction.

 

Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Position sprites with 12 bits instead of 10?

Post by Johan Kårlin »

If I get you right, that is what I am doing. This thread is not about a problem I have. It is all about something I discovered when I had implemented this and everything worked just fine. I realized that the code for calculating sprite positions could be shorter, more consistent and easier to understand if sprite positions used 12 bits. But I might be confusing things. I suppose I have to give it some more thought. Thanks for taking time to answer.
BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

Position sprites with 12 bits instead of 10?

Post by BruceMcF »


One thing to bear in mind is that the sprites in the row would still have to be processed by Vera to determine where their pixels go. And expanding them in both directions increases the workload in proportion to the square of the increase.

So hardware sprites are ideally located relative to the generated display rather than the logical display screen, with enough leeway to "exit stage left", so that the game programmers simply turn them off when they are virtually "over there", well away from the visible portion of the logical display and the sprite generator doesn't have to process those hypothetical pixels.

Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Position sprites with 12 bits instead of 10?

Post by Johan Kårlin »

I think that’s the answer I am looking for. I see a slight possibility to make it easier for the programmer. But from a hardware perspective it comes with a price that is not really worth to pay. You really seem to know everything about both software and hardware : ). While I am commenting on this - I think the easiest way to explain what I have been trying to say is this: When calculating sprite positions on a scrolling tilemap you are working with 16 bit arithmetics. The calculations are easy but you cannot rely on the fact that just because a position is bigger than the width/height of the screen the sprite will be off screen. You have to bear in mind that the values are wrapped at 1024 (=10 bits) and perhaps take actions in your code for this. I saw it as somewhat more convenient and consistent if 12 bits would be used, same as for tilemaps.
Post Reply