DEER need for X and Y to be the center of the object instead of top left corner


(Kamelia Jamaati) #1

THIS IS SO URGENT
Hello i am developing a game right now and i am in DEER NEED for tiled to export the real center of the physic objects SPECIALLY ROTATED RECTANGLES instead of x and y of the top left point of the objects .
i really need it . So can someone do that for me ??
or at least give me a clue to change the code myself ???


(Thorbjørn Lindeijer) #2

Why would you need Tiled to write out the center coordinates in the file? No additional information would be added since you can easily derive this position using some trigonometry.

Tiled already stores the position, size and rotation of the object. If you want to know where the center is of the rotated object, first calculate the center (by halving the width and height) and then apply the rotation. Some pseudo code that may help you:

double centerX = width / 2;
double centerY = height / 2;
double cosRotation = cos(toRadians(rotation));
double sinRotation = sin(toRadians(rotation));
double rotatedCenterX = centerX * cosRotation - centerY * sinRotation;
double rotatedCenterY = centerX * sinRotation + centerY * cosRotation;
x = x + rotatedCenterX;
y = y + rotatedCenterY;

Now, I can’t guarantee I got it exactly right because I didn’t test it, but if you have any problems you can Google for some explanations about how the rotation works. Let me know how it goes. Quite likely I did not take the Y axis in the right direction or I got the rotation direction wrong.

Edit: This code has been tested now and is correct.


(pit) #3

Hi Bjorn,

something is wrong for me here, I have this setup on Tiled editor:

Tiled map grid is set to 32x32.

So I placed box on position (32,32) and rotated it manually to 45.92 “degree??”.

Now I need to count center point.

NOTE ! unfortunatelly I am weak on sin and cos… I had something more interesting at school that times…

Anyway, I copied Your code to Java (http://www.tutorialspoint.com/compile_java_online.php) and I got something like this:

public class HelloWorld{

 public static void main(String []args){
    
    double centerX = 16;
    double centerY = 16;
    
    double cosRotation = Math.cos(Math.toRadians(46));
    double sinRotation = Math.sin(Math.toRadians(46));
    
    double rotatedCenterX = centerX * cosRotation - centerY * sinRotation;
    double rotatedCenterY = centerX * sinRotation + centerY * cosRotation;
    
    double x = 32 + rotatedCenterX;
    double y = 32 + rotatedCenterY;
    
    System.out.println("center position is : " + x + "x" + y + " ???");
    
    
 }

}

Console prints this:

sh-4.3# java -Xmx128M -Xms16M HelloWorld                                                                                                                 
center position is: 31.60509712192554x54.62397073276237 ???

Knowing center position before rotate it should be someting close to (48,48).

Where I did mistake ? :bug:

For me ideally could have these properties: centerX, centerY, rotation, width, height, because I parsing json map to box2d :slight_smile:


(Thorbjørn Lindeijer) #4

@winiak Well, the mistake is that I forgot that in Tiled, rotation is in degrees clockwise, whereas radians are counter-clockwise. So the rotation needs to be negated as well:

double centerX = width / 2;
double centerY = height / 2;
double cosRotation = cos(toRadians(-rotation));
double sinRotation = sin(toRadians(-rotation));
double rotatedCenterX = centerX * cosRotation - centerY * sinRotation;
double rotatedCenterY = centerX * sinRotation + centerY * cosRotation;
x = x + rotatedCenterX;
y = y + rotatedCenterY;

Edit: This is wrong, the original code was correct.


(pit) #5

Ok, apologize bjorn, I did mistake with my code …

This is corrected version:

public class HelloWorld{

  public static void main(String []args){
        
    double pos_x = 48.87;
    double pos_y = 25.17;
        
    double centerX = 16;
    double centerY = 16;
    
    double cosRotation = Math.cos(Math.toRadians(46));
    double sinRotation = Math.sin(Math.toRadians(46));
    
    double rotatedCenterX = centerX * cosRotation - centerY * sinRotation;
    double rotatedCenterY = centerX * sinRotation + centerY * cosRotation;
    
    double x = pos_x + rotatedCenterX;
    double y = pos_y + rotatedCenterY;
    
    System.out.println("center position is : " + x + "x" + y + " ???");
  }
}

and output is:

sh-4.3# java -Xmx128M -Xms16M HelloWorld                                                                                                                 
center position is : 48.475097121925536x47.793970732762375 ??? 

Rounded is 48x48 which is indeed center point. I need to implement to my parser and finally verified.

So Your pseudo-code works without negating radians.

Btw, I found something interesting, look:

So Your code just set rotation to 0 and move object to current X,Y position :sunglasses:


(Thorbjørn Lindeijer) #6

Ah, that’s what happens when you go looking for a problem, you end up seeing one… I’ve reverted my code back since indeed as you say, the inverting is not necessary. This is because the Y axis is inverted compared to the direction in which it normally goes in mathematics.

Well, the rotation tool works around the center and this means it has to move the object during the rotation. However the position of the object (around which the rotation property is applied) is not its center, so when you change this property directly its top-left corner stays in the same place (or the bottom-left, in case of a tile object).


#7

Code is wrong. Reason is the y-offset must be negative (pivot is bottom-left).
Here’s a tested, working version (C#/Unity)

     Vector2 CalcCenterPoint(float tiledX, float tiledY, float rotation)
     {
         float centerX = 16;
         float centerY = -16; // here you go
         float cosRotation = Mathf.Cos(Mathf.Deg2Rad * rotation);
         float sinRotation = Mathf.Sin(Mathf.Deg2Rad * rotation);
         float rotatedCenterX = centerX * cosRotation - centerY * sinRotation;
         float rotatedCenterY = centerY * cosRotation + centerX * sinRotation;
 
         return new Vector2(tiledX + rotatedCenterX, tiledY+rotatedCenterY);
     }

(Thorbjørn Lindeijer) #8

That depends on whether you’re dealing with rectangles or tile objects. Rectangles have the pivot in the top-left whereas tile objects have it in the bottom-left.

If we ever get around to a new major map format version, I will make sure to avoid such annoying inconsistencies…