![]() |
|
This thread is locked; no one can reply to it.
![]() ![]() |
1
2
|
Bitmap Draw Stacking |
InfiniteLoop
Member #8,434
March 2007
|
Is it possible to draw a rotated, scaled bitmap region? I am looking for functionality similar to DirectX's transforms. Basically, I am doing something like this now 1void Sprite::draw()
2 {
3 //calculate source frame location
4 int fx = (this->curframe % this->animcolumns) * this->width;
5 int fy = (this->curframe / this->animcolumns) * this->height;
6
7 //draw the sprite frame
8 al_draw_bitmap_region(this->image, fx, fy, this->width, this->height, this->getX(), this->getY(), 0);
9 }
I would like to expand the capabilities, but I am coming up short |
Trent Gamblin
Member #261
April 2000
![]() |
Allegro has transforms as well. See http://docs.liballeg.org. You could use the code you have with some added transformations.
|
InfiniteLoop
Member #8,434
March 2007
|
Thanks guys. Edgar, that would work but I need to draw regions. Trent, can you offer any insight on how I would use Allegro transforms to handle scaling and rotation? |
Trent Gamblin
Member #261
April 2000
![]() |
They work exactly like OpenGL transforms, except the first one you specify is applied first not last. Example ALLEGRO_TRANSFORM t; al_copy_transform(&t, al_get_current_transform); al_scale_transform(&t, scaleX, scaleY); al_rotate_transform(&t, someAngle); // scales about Z axis All transforms in Allegro presently are 2D.
|
InfiniteLoop
Member #8,434
March 2007
|
Thanks again guys. After performing scaling and rotating transforms, do I need to apply with al_use_transform? Also, since this is only for a single sprite, how do I prevent the transform from applying to other sprites? How do I reset it? Thanks |
Trent Gamblin
Member #261
April 2000
![]() |
Yes, you have to use al_use_transform. You have to save the old transformation if you want to reset back to it.
|
InfiniteLoop
Member #8,434
March 2007
|
OK, I am using the following code and my image is going nuts: 1
2void Sprite::transform()
3 {
4 ALLEGRO_TRANSFORM T;
5 al_identity_transform(&T);
6 al_scale_transform(&T, this->getScale(), this->getScale());
7 al_rotate_transform(&T, this->getRotation());
8 al_use_transform(&T);
9 }
10
11 void Sprite::draw()
12 {
13 //calculate source frame location
14 int fx = (this->curframe % this->animcolumns) * this->width;
15 int fy = (this->curframe / this->animcolumns) * this->height;
16
17 //draw the sprite frame
18 this->transform();
19 al_draw_bitmap_region(this->image, fx, fy, this->width, this->height, this->getX(), this->getY(), 0);
20 }
Scale is 1 and rotation is based on the system clock. I want to image to spin in place, instead it is flying all around the screen EDIT: actually, I see that it is rotating about the top left corner. How do I make it rotate about the middle? |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You'll have to add a few translate transforms in there. identity My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
InfiniteLoop
Member #8,434
March 2007
|
I am sorry for my density, but I am a little lost at this point. I have no idea how to structure my transform statements. I see where you told my to translate to "origin" and the center of my "region" but I am not sure what that means. Could you help me with some sample code maybe? I tried the following, but it didn't work. 1ALLEGRO_TRANSFORM T;
2 al_identity_transform(&T);
3 al_translate_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2);
4 al_scale_transform(&T, this->getScale(), this->getScale());
5 al_rotate_transform(&T, this->getRotation());
6 al_translate_transform(&T, -this->width / 2, -this->height / 2);
7 al_use_transform(&T);
EDIT: am I assuming the camera is looking right at the center of my screen? Then what, I have to tell the camera to move where? EDIT AGAIN: this is the code I am now using. The image rotates about the center of the screen, but in a wide arc. I would like the image to rotate in place. 1ALLEGRO_TRANSFORM T;
2 al_identity_transform(&T);
3 al_translate_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2);
4 al_scale_transform(&T, this->getScale(), this->getScale());
5 al_rotate_transform(&T, this->getRotation());
6 al_translate_transform(&T, g_engine->getScreenWidth() / 2, g_engine->getScreenHeight() / 2);
7 al_use_transform(&T);
Also, is the following acceptable for resetting the transform? const ALLEGRO_TRANSFORM *current = al_get_current_transform(); //draw the sprite frame this->beginTransform(); al_draw_bitmap_region(this->image, fx, fy, this->width, this->height, this->getX(), this->getY(), 0); al_use_transform(current);
|
SiegeLord
Member #7,827
October 2006
![]() |
Try: ALLEGRO_TRANSFORM T; al_identity_transform(&T); al_translate_transform(&T, -this->width / 2, -this->height / 2); al_scale_transform(&T, this->getScale(), this->getScale()); al_rotate_transform(&T, this->getRotation()); al_translate_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2); al_use_transform(&T);
InfiniteLoop said: Also, is the following acceptable for resetting the transform? No, you need to copy it elsewhere: ALLEGRO_TRANSFORM old; al_copy_transform(&old, al_get_current_transform()); this->beginTransform(); al_draw_bitmap_region(this->image, fx, fy, this->width, this->height, this->getX(), this->getY(), 0); al_use_transform(&old);
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
InfiniteLoop
Member #8,434
March 2007
|
Thank you siege, it is much more tame now, but it is still rotating about some point just past the upper left hand corner of the image. What is doing the "looking"? What do I need to be "looking" at? I get rotation and scaling, but when you throw in translation I am lost. |
SiegeLord
Member #7,827
October 2006
![]() |
Oh, I missed one bit. With the set of transforms I suggested you need to draw like this: al_draw_bitmap_region(this->image, fx, fy, this->width, this->height, 0, 0, 0); Note the 0's in the destination: the transformation takes entirely of the positioning. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
InfiniteLoop
Member #8,434
March 2007
|
My God! You sir are a gentleman and a scholar! That works brilliantly. Would it be too much to ask (and it doesn't have to be now) for you to explain why that worked? I am not sure how I would draw it at 0, 0 and have it appear where I want. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
One question - are your coordinates in real space or screen space? 1
2int cx = this->x + this->width/2;// for screen space coordinates
3int cy = this->y + this->height/2;// for screen space coordinates
4
5int cx = (this->x + this->width)/2 - camera_x;// for real space coordinates
6int cy = (this->y + this->height)/2 - camera_y;// for real space coordinates
7
8ALLEGRO_TRANSFORM t;
9al_identity_transform(&t);
10//al_translate_transform(&t , -cx , -cy);
11al_translate_transform(&t , -this->width/2 , -this->height/2);
12al_scale_transform(&t , scale , scale);
13al_rotate_transform(&t , angle);
14al_translate_transform(&t , cx , cy);
15al_use_transform(&t);
Nevermind - I guess Siegelord is right. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
InfiniteLoop
Member #8,434
March 2007
|
Edgar, I believe they are screen coordinates. I do everything relative to the upper left hand corner (0, 0). |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Okay, well if you ever use a camera, just remember that you need to subtract the camera position from the object position to get its screen coordinates. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Elias
Member #358
May 2000
|
Why don't we have an al_draw_rotated_scaled_bitmap_region function? The function name is long, yes - and you can do the same thing with transformations. But we have all the other variants for doing it in a single function call so why not this? -- |
SiegeLord
Member #7,827
October 2006
![]() |
InfiniteLoop said: Would it be too much to ask (and it doesn't have to be now) for you to explain why that worked? I am not sure how I would draw it at 0, 0 and have it appear where I want. Well, thing is, (0, 0) is the initial pair of coordinates that you specify before they get transformed. The full explanation probably requires pictures, but I don't feel like drawing right now. Let me try to explain in words then. Let's go through the list of transformations and see how it affects the output of al_draw_bitmap(bmp, 0, 0, 0): 1. al_identity_transform(&T); After this call al_draw_bitmap draws like usual, with the top-left corner at (0, 0). 2. al_translate_transform(&T, -this->width / 2, -this->height / 2); After this call the al_draw_bitmap call will be offset, so that the top left corner will now be at (-this->width / 2, -this->height / 2). We do this so that the middle of the bitmap is at (0, 0). Note that this step (and this step alone) can be removed by doing al_draw_bitmap(bmp, -this->width / 2, -this->height / 2, 0). 3. al_scale_transform(&T, this->getScale(), this->getScale()); After this call the top left corner will be at (this->getScale() * -this->width / 2, this->getScale() * -this->height / 2) and the bitmap will also be drawn bigger. The critical bit here (and why we did step #2) is that the center of the bitmap doesn't move with scaling. If the center was not at (0, 0) it would be scaled, and we'd have a mess. 4. al_rotate_transform(&T, this->getRotation()); After this call the bitmap will be rotated about (0, 0). Since we took care to place the bitmap's center at (0, 0) it will be rotated around its center. 5. al_translate_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2); After this call the bitmap's center will move to (this->getX() + this->width / 2, this->getY() + this->height / 2). If we had no rotation and scaling, then we'd just have this: ALLEGRO_TRANSFORM T; al_identity_transform(&T); al_translate_transform(&T, -this->width / 2, -this->height / 2); al_translate_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2); al_use_transform(&T); al_draw_bitmap(bmp, 0, 0, 0); Translations simply add, so if you followed the steps above it should be clear to see how this code is exactly equivalent to: al_draw_bitmap(bmp, this->getX(), this->getY(), 0); Lastly, there is a function to simplify this process a bit: ALLEGRO_TRANSFORM T; al_build_transform(&T, this->getX() + this->width / 2, this->getY() + this->height / 2, this->getScale(), this->getScale(), this->getRotation()); al_use_transform(&T); al_draw_bitmap(bmp, -this->width / 2, -this->height / 2, 0, 0);
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
I don't think al_build_transform would work in this case, because it does the scaling and rotation before the translation (according to the manual). My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
SiegeLord
Member #7,827
October 2006
![]() |
Edgar Reynaldo said: I don't think al_build_transform would work in this case, because it does the scaling and rotation before the translation (according to the manual). Right, except there are two sets of translations. Here's what happens: Original set of transformations | New set of transformations Initial location: 0, 0 Initial location: -w/2, -h/2 Translate(-w/2, -h/2) ---------------------------------^ moved to here Scale \ Rotate |-------------------> combined into al_build_transform Translate /
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
InfiniteLoop
Member #8,434
March 2007
|
Thank you, that helps a lot. After a nights sleep, I went back and looked at the order I was calling the functions you gave me and I figured it out (by drawing on a piece of paper). What you said has confirmed my suspicions. Thank you all again for your help. It is truly appreciated. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
SiegeLord said: Right, except there are two sets of translations. Here's what happens: Fine, except for that's not what your code example shows. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
SiegeLord
Member #7,827
October 2006
![]() |
How not? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
|
1
2
|