Jump to content
  • 0
Johan Kårlin

Position sprites with 12 bits instead of 10?

Question

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? 

Share this post


Link to post
Share on other sites

10 answers to this question

Recommended Posts

  • 0

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.

Share this post


Link to post
Share on other sites
  • 0
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.

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
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.

Edited by StephenHorn

Share this post


Link to post
Share on other sites
  • 0
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 : ).    

Share this post


Link to post
Share on other sites
  • 0

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.

 

Share this post


Link to post
Share on other sites
  • 0

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.

Share this post


Link to post
Share on other sites
  • 0

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.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0

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.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
On 8/31/2020 at 10:21 PM, Johan Kårlin said:

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 : ).

Far from everything ... to the extent that I am anything, I am a software hand, but I am just a dabbler taking a break from my day job. There are far better programmers than I am on this site. But early last year I did follow the experiments one fellow was doing with the Gameduino, before that design was dropped, and got a bit of a handle on how the linebuffer approach differs from the framebuffers we are so used to today.

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Please review our Terms of Use