Displays and Decimals?

Hey all,

How does the Adruboy make decisions when displaying “uneven” graphics? I’ve created a sketch that loads a bitmap with an uneven width (49 pixels wide) and an uneven height (51 pixels) to the “centre” of the screen.

Firstly, I created this function:

//The drawCentre function.
int drawCentre(int width,int height,int graphic, int colour)
{
//Set up a central display.
int x = 0.5WIDTH - 0.5width;
int y = 0.5HEIGHT - 0.5height;
arduboy.drawBitmap(x,y,graphic,width,height,colour);
}

During the loop, I call it as so:
//Draw the graphic.
drawCentre(uuWidth,uuHeight,uuGraphic,WHITE);

So here’s the thing: 0.5WIDTH is 64, and 0.5width (the sprite’s width of 49 pixels) is 24.5. 0.5WIDTH + 0.5width equals 88.5, meaning that I’m drawing the graphic from the 88.5th pixel on the screen, right? What is actually happening here? I’ve uploaded a photo of the graphic to this thread and you can see that it’s drawn very clearly.

How does the Arduboy choose where to draw a graphic that starts at a position like 88.5 pixels on the x axis? Please keep in mind that I’m a real novice.

Thanks!

As I stated in Part 7 of my tutorial series, whenever you ask the Arduboy to divide a number, you will usually end up with a whole number instead of a fraction. The way you avoid this is by asking for the remainder when dividing or by using a different type of number. There are many kinds of numbers that you can use while programming, so when you work with them, you have to know what kind of numbers you’re using. The drawing functions require integers, which are numbers that do not have decimals. You cannot draw your image at a half of a pixel because the X and Y variables are also integers that do not have decimal places.

That should kinda answer your question… Since it gets rid of the decimal, it’s likely that your picture is being drawn to the left by an extra pixel than you may have thought. :wink:

Okay, but why did I say left? What about vertical centering? It’s the same concept, but you need to realize that most bitmaps are stored in groups of bytes for the Arduboy.

Take a look at this picture. Circuit Dude’s face is 42 pixels wide by 42 pixels tall.

Normally, you may assume that the image is stored by pulling each pixel out, row by row, like in this picture.

But it’s actually not. The image is sliced apart into large rows that are 8 pixels high. Then, those rows are sliced into columns. After that, each column is broken apart into 8 pixels to store. Why do this? Eh, the answer’s a little complex, but it’s faster to draw and stuff. The main reason why you should know this is because if this image has a height that is not a multiple of 8, then the very last row will have a bunch of dummy data pushed into it. Look at the bottom of Circuit Dude’s face! The dark red represents dummy data that isn’t drawn but has to be stored into the image.

Because of the dummy data at the end, Circuit Dude isn’t 42 pixels wide by 42 pixels tall. He’s actually 42 pixels wide, by 48 pixels tall!

Honestly, for what you’re doing, you don’t need to know this! But, anyone else that’s centering an image dynamically may need this information. :smile:

4 Likes

tldr; Integers are truncated to the whole number before the decimal place.

4 Likes

Really interesting, thanks for explaining it. I always work in multiples of 8 when I make pixel art, but I was only doing it out of a sense of tradition for the older games I admire. Now I feel like I understand the reasoning behind that a little bit more? I hope so.

Is there a way to use decimal numbers with the Arduboy? I wanted to try to adapt a decimal-based acceleration/deceleration script that I use in GameMaker: Studio that makes for interesting character/object movement on a screen with limited pixels.

Yeah! That’s pretty much the reason! Multiples of 8 use the memory way more effectively. Anything less than that and there’d have to be dummy data. :wink:

1 Like

So the multiples of 8 concept applies horizontally as well, or only vertically? Sorry to ask another question but I’m unclear on this and really interested.

Not so much on the Arduboy! But smaller systems had memory constraints which was broken up into chunks of 8 bits. :slight_smile:

1 Like

You can use floating point arithmetic by using the float data type, but it will use a fair amount of code and be slow, but still might be suitable for your purpose.

You can also use binary fixed point notation, where you treat some of the lower bits of an integer as a fraction. The Flappy Ball game does this.

1 Like

@GrappleBug the multiple of eight thing I believe only applies to vertical. I haven’t seen efficiency gain in having the width being a multiple of 8. Just like @bateske said, when an integer is divided it is effectively floored (rounded down) to the nearest whole number. 84.9 would just be 84, for example.

1 Like

As @MLXXXp said, simple type float may be enough in your case.

FYI, for my 3d demo test, I writed some fixed point arithmetic based on 16 bits integers for intensive floating computations, with good results.

If you want to use it, just look at/copy the code between the comment block “fixed point” in my zfw header, setup the range/precision that fits your need and use all “fp” functions.

2 Likes

Thanks, I will take a look soon.