Making images, buttons and backgrounds

14/01/2010

In need of a nice glossy button? A background, a circular text on a marble texture?

Just found this site: http://www.grsites.com/

where you can easily generate all you need for a game…

lots of choices with examples readily available…

just made this button: (it even comes with a mouse_over highlight)

so we just need a nice struct for an image and a struct which extends this struct to a button struct 🙂

for example:

typedef struct{

char* imageTitle; // a string

u16* imageArrayBin; // pointer to the image_bin

u8 posX;

u8 posY;

u8 width;

u8 height;

} ImageView;

…..and…..

typedef struct{

ImageView* imageView;//pointer to the image of your button

u8 posX;

u8 posY;

FunctionPointer* buttonPushed;

} ButtonView;

oh yes, what was all that about pointers to functions????

It is just an easy way to implement what to do when the button is pushed…

look here: http://www.cprogramming.com/tutorial/function-pointers.html


Bitmap rotation2

13/01/2010

In the post Bitmap rotation1 we saw a bitmap rotating but till leaking at the corners. This meant that the background was still not covered totally. Fooling around with the boundaries did the trick:

in the drawRotatedBitMap method: we have a double loop

for(  y = miny  ; y <  maxy ; y++ )
{
for(  x = minx  ; x <  maxx  ; x++ )
{

//drawing from destination to source

}}

I added the small idea of looking if the pixel to be drawn was in the rectangle of the bitmap or not (using two triangle methods), if not, draw the pixel from the background (using the hidden background layer).

This left the corners not drawn and this amounted to leaking:

This leaking was removed later during the rotation … but still not good!

So fiddling a bit with the limits solved the problem:

for(  y = miny – 1  ; y <=  maxy + 1  ; y++ )
{
for(  x = minx – 1  ; x <=  maxx + 1  ; x++ )
{

No the image rotates without leaving pixels:

the nds movie can be found here:
not leaking rotation, nds file

source files:
not leaking rotation, zip file


Bitmap rotation1

07/01/2010

(for the not leaking version see Bitmap rotation2)

When working with tiles and sprites  you can rotate the sprite easily, because rotation is a property of the sprite. But we are working in the bitmapmode.

We can copy images to a background without a problem, but rotating the image is somewhat complicated.

The first solution is to do a simnple rotation of points:

within the loop of the pixels of the image:

//minus point of rotation
float x = (float)j – height/2.0;
float y = (float)i – width/2.0;
//rotating matrix
float newX = x*cosine-y*sine;
float newY = x*sine+y*cosine;
//plus point of rotation
int newIntX = (int)newX + height/2.0;
int newIntY = (int)newY + width/2.0;

but the you notice that some pixels due to approximations are not drawn. Some pixel locations are not reached:


The trick is to work from the destination bitmap and ask for the pixel color of the source…

see this link:

http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/

but here the rotation is done from the corner point (0,0) and the use of the double buffer has to be considered for nds programming.

we solve these problems in this way:

float cosine = cos(angle);
float sine = sin(angle);

// Compute dimensions of the resulting bitmap, but now using four points and transforming these

int cx = width/2; //point of rotation
int cy = height/2;

int x0 = (int)(0 – cx); //four points minus point of rotation
int y0 = (int)(0 – cy);
int x1 = (int)(width – cx);
int y1 = (int)(0 – cy);
int x2 = (int)(width – cx);
int y2 = (int)(height – cy);
int x3 = (int)(0 – cx);
int y3 = (int)(height – cy);
int x0N = (int)(x0 * cosine – y0 * sine) + cx; //transform the points of rotation
int y0N = (int)(y0 * cosine + x0 * sine) + cy;
int x1N = (int)(x1 * cosine – y1 * sine) + cx;
int y1N = (int)(y1 * cosine + x1 * sine) + cy;
int x2N = (int)(x2 * cosine – y2 * sine) + cx;
int y2N = (int)(y2 * cosine + x2 * sine) + cy;
int x3N = (int)(x3 * cosine – y3 * sine) + cx;
int y3N = (int)(y3 * cosine + x3 * sine) + cy;

int minx = min(x0N,min(x1N, min(x2N,x3N))) ; //find the limiting bounding box
int miny = min(y0N,min(y1N, min(y2N,y3N))) ;
int maxx = max(x0N,max(x1N, max(x2N,x3N))) ;
int maxy = max(y0N,max(y1N, max(y2N,y3N))) ;

//then we do the trick:

int x,y;
for(  y = miny; y < maxy; y++ )
{
for(  x = minx; x < maxx; x++ )
{ //same as in the link
int sourcex = (int)(( x – cx )*cosine + ( y – cy )*sine) + cx; //only consider the point of rotation
int sourcey = (int)(( y – cy )*cosine – ( x – cx )*sine) + cy;


//now find out if point is in the original rectangle using a method finding out if a point is in a triangle

//we use this 2 times to get the point in the rectangle

int intBool1 = pointInTriangle ( x0N,x1N,x2N,y0N,y1N,y2N,x, y) ;
int intBool2 = pointInTriangle ( x2N,x3N,x0N,y2N,y3N,y0N,x, y) ;

//now if point is in triangle1 or triangle 2:

if ( intBool1 == 1 || intBool2 == 1 )
{
if ( bufferX + x>0 && bufferX + x < 256  && bufferY + y>0 && bufferY + y < 192) //if in field
{
index = ((bitmapY + sourcey) * width) + bitmapX + sourcex;
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, PIXEL(bitmap[index]));
}
}
else //if not in the rectangle restore the old pixel coming from the hidden double buffer
{
u16 backColor = getPixel(video_buffer_Source, bufferX + x, bufferY + y);
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, backColor );
}
}
}

without blanks, but you see the rotation effect on the paperclip

Ok, eating is the proof of the pudding: (a sketch just showing the rotation of a rather big bitmap to get a good view of the effect)

http://cid-58814201e79976dd.skydrive.live.com/self.aspx/iepro/bitmapRotation%5E_DB.zip

You can see the image is somewhat leaking at the corners, which can possible be solved by restoring from a slightly bigger range from the hidden buffer.

Also looking at the method parameters (far too much!), you see this is crying for a struct “around the image”, having members like

  • imagename (start array of pixels
  • imageWidth
  • imageHeight
  • posX
  • posY
  • rotationAngle
  • rotationPosX
  • rotationPosY



Alternative way of converting images

24/12/2009

step1. Download grit at http://www.coranac.com/projects/

step2. Place the image in the grit folder

step3. Create a batch file

step4. Edit the batch file and insert the following text: grit <image.ext> -m! -gB8

image.ext can be img1.png or img2.gif

The -m! and -gB8 are possible options to convert the image. All options can be found in the help file wingrit.chm located in the grit folder.

step 5. Execute the batch file and a .h and .s file will be created.

step 6. Copy these files the nintendo nds project folder.

step 7. Include the .h file in the source code of you’re application.

step 8. The image is now included and can be used.


Interesting link for learning about maps, tiles and pallets

24/12/2009

http://ekid.nintendev.com/bouncy/supplies.php


Images on the nds

24/12/2009

You can prepare images with

  • wingrit for WINDOWS
  • jgrit for MACOS

the settings for the bitmapmode are:

under gfx

  • gfx
  • bpp 16
  • cprs off

under file:

  • filepath is indicated if you drag an image in the gba exporter window
  • type: binary
  • h file: none and at the right of this u16

hit ok and the binary file can be found in the folder of th source file

after that: say you have the file called :  click.img.bin

put this bin file in the data folder of your project

include the header file like this using underscores: #include “click_img_bin.h”

and use it like this:

  • dmaCopy(click_img_bin, pointerToStartMem,   2*256*256     );// if background
  • a copy pixels method in case of a smaller image somewhere on the screen

example of a copy pixels function:

inline void drawPixel(u16 *video_buffer, u16 x, u16 y, u16 color) {

u32 index = (y * SCREEN_WIDTH) + x;
video_buffer[index] = color;
}

in combination with:

void drawPartOfBitmap(u16 *buffer, u16 destX, u16 destY, u16* bitmap, u16 startX, u8 startY, u8 widthD, u8 heightD, u16 widthP, u8 heightP) {
u16 i, j, index;
for(i = 0; i < heightD; i++) {
for(j = 0; j < widthD; j++) {

index = startX + j + i * widthP;

if (PIXEL(bitmap[index]) != COLOR_WHITE) //the transparent color
drawPixel(buffer, destX + j, destY + i, PIXEL(bitmap[index]));
}
}
}