Hi there !
My question could be very stupid, but I have no idea of how ags handles that...
Imagine I have a DynamicSprite "f" that is a square ("rectangle" ?) with these attributes : f.Width=30, f.Height=34.
If I do : f.Rotate(90)
It makes : f.Width=34 and f.Height=30.
Right :)
BUT, if I do : f.Rotate(45)
What will be the width and height of f ?
The width and height will be minimal necessary rectangle to accomodate the rotated image.
But why do you need to know how AGS does this? Do you want to know about the algorithm, or do you simply want to know resulting width and height? In the last case you may read DynamicSprite's Width and Height properties after rotation.
OK thanks !
I just wanted to know the formula to calculate the new height/width of the dynamic sprite.
Is the formula well-known ? I have to use it in scripts, with many things that have different heights and widths, so I need the generical approach.
Quote from: Baguettator on Sat 05/02/2022 22:34:51
I just wanted to know the formula to calculate the new height/width of the dynamic sprite.
But why do you need this formula? Are you resizing sprites yourself before rotating?
The manual sais that for DynamicSprite.Rotate "AGS will automatically calculate the new size required to hold the rotated image" if you pass no width and height.
That is, if you write just "f.Rotate(45);" it will be resized itself as necessary.
Because I use a script to calculate coordinates for tokens (to place on maps, like a tabletop game). And I have "stored" the possible coordinates for the different tiles.
So for example I can place my square at the 1st position of the tile A, with a "up" rotation, and it will automatically set it to x and y coordinates according to my script.
But if I rotate the tile, I have to rotate the tokens too. So they change their rotation (up becomes right for a 90° rotation, or becomes down for a 180° rotation, etc), and their coordinates. To change their coordinates, I need to know their width and height. I have to script it during a time when DynamicSprites are NOT created yet. So I can't use DynamicSprite.Width etc
Is the formula too complex ?
Quote from: Baguettator on Sat 05/02/2022 22:44:53
But if I rotate the tile, I have to rotate the tokens too. So they change their rotation (up becomes right for a 90° rotation, or becomes down for a 180° rotation, etc), and their coordinates. To change their coordinates, I need to know their width and height. I have to script it during a time when DynamicSprites are NOT created yet. So I can't use DynamicSprite.Width etc
Is the formula too complex ?
Oh, sorry. I was wondering if you are doing some unnecessary work for sprite rotation.
Formula is this (math):
new_width = (cos(angle) * old_width + sin(angle) * old_height);
new_height = (sin(angle) * old_width + cos(angle) * old_height);
In AGS script that would be:
new_width = FloatToInt(Math.Cos(angle) * IntToFloat(old_width) + Math.Sin(angle) * IntToFloat(old_height));
new_height = FloatToInt(Math.Sin(angle) * IntToFloat(old_width) + Math.Cos(angle) * IntToFloat(old_height));
The angle above is in radians. If you have angle in degrees, you need to first convert it using Maths.DegreesToRadians.
That said, but I still wonder if this is necessary.
Could you save positions of the token centers instead of top-left corners? Then you won't have to calculate these coordinate changes, and realign the sprites only after they change.
This depends on what kind of map you have though.
Thanks a lot Crimson !
I already scripted all the tokens with their top-left corner coordinate (which is the way AGS works for buttons, and tokens are represented by buttons), and it should be very long to change it now... Maybe one day :) Surely it should be better, but it works perfectly for now.
I'm working on the rotation of the tile, will see if it works with the new formula.
I presume that if I only talk about 45° multipliers (45, 135, 225 and 315), these dynamicsprites should have the same width/heights ?
Quote from: Baguettator on Sat 05/02/2022 23:13:12
I presume that if I only talk about 45° multipliers (45, 135, 225 and 315), these dynamicsprites should have the same width/heights ?
That should be correct, all mirror angles should result in the same size.
Quote from: Baguettator on Sat 05/02/2022 23:08:24
I already scripted all the tokens with their top-left corner coordinate (which is the way AGS works for buttons, and tokens are represented by buttons), and it should be very long to change it now...
I made a mistake. You do not have to use center positions. You may keep existing top-left positions (non rotated), and then adjust tile's position after it is rotated like this:
new_x = old_x + (old_width - new_width) / 2;
new_y = old_y + (old_height - new_height) / 2;
EDIT: fixed by /2
This will work generally if the tile is resized for any reason.
Shouldn't you divide those widths and heights by 2, CW?
Quote from: Snarky on Sun 06/02/2022 06:43:32
Shouldn't you divide those widths and heights by 2, CW?
Right.
Hmm I didn't follow you in your thoughts... I used your formula (with cos and sin) to calculate the width/height of the token after rotating (45° or multipliers), then I simply do that :
//34=width when it's not rotated, 30 is the height when not rotated
int l=FloatToInt(Maths.Cos(Maths.DegreesToRadians(45.0))*IntToFloat(34) + Maths.Sin(Maths.DegreesToRadians(45.0))*IntToFloat(30));
int h=FloatToInt(Maths.Sin(Maths.DegreesToRadians(45.0))*IntToFloat(34) + Maths.Cos(Maths.DegreesToRadians(45.0))*IntToFloat(30));
int x, y; // x is the original x position for the top leftcorner of the token, y is the y position of the top leftcorner
int xporte, yporte; // Also the original coordinates of the token
// The tile width and height are equal to 250
if (nouveau==right) // the tile rotates to right, so 90°
{
xporte=250-y-h;
yporte=x;
}
else if (nouveau==down) // the tile rotates to down, so 180°
{
xporte=250-x-l;
yporte=250-y-h;
}
else if (nouveau==left) // the tile rotates to left, so 270°
{
xporte=y;
yporte=250-x-l;
}
Hmm Khalibri, what are you talking about ? What do you want to do ?
Hi here, I continue this thread with a new math problem I need help to solve :
let's say I have a square (same width and height). Into this square, I have a point at (x,y) coordinates (the coordinates are from square's size, so the top left corner coordinates are 0,0).
If I rotate the square by "a" degrees, how can I calculate the new coordinates for the point ? (the point rotates with the square, as if they were the same thing). Is there a formula that works generally for any "a" value ? I guess there is, but I don't know which :(
You need a 2D rotation matrix:
(https://wikimedia.org/api/rest_v1/media/math/render/svg/d4a02e6b5990244f4427309f6732239b9633d62d)
int[] RotatedPoint(int xi, int yi, int deg) {
float x = IntToFloat(xi);
float y = IntToFloat(yi);
float r = Maths.DegreesToRadians(deg);
float c = Math.Cos(r), s = Math.Sin(r); // cosine and sine
int r[] = new int[2];
// matrix times vector
r[0] = FloatToInt(c * x - s * y, eRoundNearest);
r[1] = FloatToInt(s * x + c * y, eRoundNearest);
return r;
}
This function rotates a 2D point around the origin, so if your square is supposed to rotate around its center, you need to subtract half the side length from your coordinates before calling it, then add it back.
Example code:
// square size s
// shift origin to square's center
x -= s / 2;
y -= s / 2;
int p[] = RotatedPoint(x, y, 5); // 5 degrees clockwise
// shift origin back to top left
x = p[0] + s / 2;
y = p[1] + s / 2;