Problems with sprites

Then what is the third value supposed to be?

What does framew stand for?
Why is it only used in the 4bpp version?

That 220 is there because I put it there to try to match framew:

Is framew just a bug in drawBitmap?

No. Framew is just for internal calculation of the offset to get to the frame # requested

Frame on the other hand is the number of the frame you want (0,1,2…)

Then what exactly is framew supposed to do/be for?

The following line bitmap = bitmap + 3 skips the first three bytes of the image.
The first byte is the width, the second is the height, the third is framew.
framew doesn’t appear to be the first byte of the image, so what is it supposed to be?

Hmm… maybe I am mistaken. Wasn’t paying attention.

Lemme check

Yes, you are correct.

And the way you tried to help was correct also.

I need code that reproduces the problem to be able to take a look at it

If you’re happy with C++11 code then here’s a copy of the version with the jumping bug:

I put in 220 for the width because I assumed framew was supposed to be the ‘frame width’, but now I’m back to having no clue what it’s supposed to be for.

Thanks for the code. Your idea of the purpose of framew was correct.

In that case, three more questions arise.

  1. Why are the 1bpp and 2bpp versions not using framew?
  2. Why not just use the image width itself?

And thirdly, something that @sbmrgd brought to my attention earlier:

This code (bitmap += (framew*frame)>>1) implies that framew is trying to be used like (width * height * frame) / (8 / bpp),
in which case should framew actually be width * height instead?

(Even it it were width * height it would have to be widened to accomodate (220 *176 * frame) / 2.)

Sorry to bump this, but I’m still not sure what framew is supposed to achieve.
Why would the frame width be different to the image width?
And why do the 1bpp and 2bpp versions not use framew?

Is it possible that this function is unfinished or needs rewriting?
If so I could possibly have a go at rewriting it.

It might be that a separate framew parameter is there to give flexibility to have the frames horizontally (framew = w) or vertically (framew = h*w). Also in some animation format there might be a visible grid in the bitmap, which can be ignored by giving e.g. (framew = w + 1).

:slight_smile: This is where the documentation would come in handy

2 Likes

I’m still struggling to see how that would work.

The pointer starts at bitmap[3], which is the first item after the 3-byte header, and then it’s offset by (framew * frame) / 2 (with the / 2 obviously being because it’s 2 pixels per byte).

In a traditional frame system, framew would have to be h * w to treat the whole structure like an array,
because that would be equivalent to doing sizeof(imageFrame) * frameIndex.

If framew was only width, that would mean that each frame isn’t actually a frame,
it’s just scrolling the image up one row.
(Granted I can see a small amount of merit in that,
but I don’t think it would be a particularly common animation.)

If framew was width + 1 that would be scrolling the image up one row and one pixel,
which would be a very odd animation and I can’t think why anyone would want that.

To be completely honest, I do not recall when and how that function was added, and more importantly, I don’t remember if it was me.

2 Likes

if the frames were laid out horizontally, (framew * frame) / 2 would move to the start of the frame.

I assume framew is the width of the frame with borders, and w is the width of the actual frame (or vice versa :wink: ). I have only quickly looked at the code so I am not sure.

I do not think there is any vertical animation frame layout support.

Edit: I think there is a one big image that contains the frames, not many tiny images(frames) in series.

In that case I think this function might need revising.

Hrm, that’s possible.
Although I don’t know why someone would want to leave borders in,
it makes more sense to just leave them out.

Edit:
I.e. If you don’t want to display the borders at any point,
just leave them out of the image before encoding.
It’s easy to do, it saves memory, there’s no drawback whatsoever.

Wrong way round I think?

Image data is almost always packed in rows, incrementing x first and then y, which is what allows y * width + x to be used to pick a pixel.

By doing things this way, the frames should be vertical:
(Ignore framew for this.)

SpritesheetVertical

If you try to place frames horizontal, the resulting byte array is inefficient:

SpritesheetHorizontal

Unless you’re storing by column instead of by row:

SpritesheetHorizontalColumn

But it’s less common for screens to write columns before rows.
Historically screens write data by row, so sprites have been packed following that same pattern.


Either way, I think it would be better to just scrap the third argument and only require the width and height to be stored.
That would simplify the encoding+decoding logic.

2 Likes

If we’re going to make changes to the format, may I suggest that we repurpose the third argument instead? It would be good if it could be a set of flags for things like identifying BPP.

1 Like

I think we might need the third argument, but that should be either the number of frames or the total height of the big image.

I think it is really confusing that you have a drawBitmap function that expects a bitmap with a header of 2 and a drawBitmap function that expects a bitmap with a header of 3…
I would only keep 1 of them to avoid confusion…
(this is a beginner speaking :slight_smile: )

3 Likes

Is anyone actually using the third argument?
I’m not sure I’ve seen it in use.

And if it was repurposed it still wouldn’t be backwards compatible, so you’re not really gaining anything.

Having a bpp field is a different matter entirely.
On the one hand it seems useful, but having drawing modes capable of displaying sprites intended for other drawing modes is likely to exponentially increase code size.
It could be useful for saving memory by e.g. displaying 2bpp sprites in a 4bpp mode, but that would make bitmap decoding slower and you’d be limited to just the first 4 colours unless you introduced another field or another variable.

What would that be useful for other than refusing to display an invalid index?

If the code is capable of providing an invalid index that’s a clear program logic error, so you don’t want to be hiding that.

You could use it as a modulo I guess, but that still feels like it’s probably covering up a bug in the code.

Then you’d have to make it two bytes. 220x176 = 38720
(In fact even 2*176 is more than a byte can handle.)

This is one of the reasons I’m in favour of keeping it simple and just having the width and height.
(“Simple”? Oh dear, I’m treading on @drummyfish’s territory. :P)

3 Likes

Reducing a number of parameters if you pass that bitmap to a function that does not know about the correct frame count. The same as with image width and height in the header.

1 Like