Is the interaction between scaling and rotation intended?

70 views
Skip to first unread message

Shu Sam Chen

unread,
Nov 20, 2016, 2:11:13 PM11/20/16
to excaliburjs
Experimenting with scale vectors on Actor objects seems to indicate that scaling is being done after rotation, which leads to unexpected results. I rather expected scaling to be applied before rotation.

Consider the following scenario:
I have a square actor of size (10, 10) set to scale (1, 2). This results in a stretched-out actor 20 high and 10 wide. I rotate the actor by 90 degrees, expecting it now to be 20 wide and 10 high, but instead it remains 20 high and 10 wide because the rotation is applied before the scale.

Have I got the wrong idea? Am I expected to compute my own rotations of the scale vector (this seems to be non-trivial)?

Erik Onarheim

unread,
Nov 20, 2016, 6:55:45 PM11/20/16
to excaliburjs
Hi Shu,

The reason this doesn't work the way you expect is because the Actor represents a player, enemy, or item on the screen. The design decision we made a long time ago followed this reasoning: "Just because a actor is rotated does not change how tall it is intrinsically, the top edge of the actor is just rotated". However, I feel we may need to revisit this design decision because this seems like it can be very confusing. Thoughts?

I've opened an issue on this because it is completely reasonable to get the current width or height of the runtime bounds of an actor. I wanted to say the actor.getBounds().getWidth() and actor.getBounds.getHeight() would work to calculate this but it doesn't, which feels like a bug. https://github.com/excaliburjs/Excalibur/issues/692

It is technically possible to calculate but is pretty gnarly to look at, I've come up with 2 work arounds until actor.getBounds() works properly

Sorry about the confusion and hassle,
Erik

Shu Sam Chen

unread,
Nov 21, 2016, 4:47:06 AM11/21/16
to excaliburjs
Hi Erik,

Thanks for the reply. I'm minded to say the order of operations should always be the classical order of scale, rotation, translation (or variants thereof because Excalibur supports rotating around a point). This ensures that any operation conducted on any actor has the same result independent of any other operations that might be applied.

However, I do in some way understand the design decision. For instance, if you needed a UI element to always occupy a certain space, that seems suited to the current system. Could there be a way to specify this order of operation?

I haven't had a chance to look at your code yet, but will reply again when I have :)

Thanks again,
Sam

Kamran Ayub

unread,
Nov 21, 2016, 12:12:02 PM11/21/16
to excaliburjs
Drawing does follow this logic which is why visually you see the result you expect. But getWidth() and getHeight() only take into account scale and ignore rotation (since physically, the actor's dimensions haven't changed). It may make sense to split the "physical" width and height into separate properties (what we have now) and modify getWidth and getHeight to use the bounding box dimensions (which should take into account rotation).

I would be interested to know what other engines do, if "width" and "height" are always considered to be the bounding box width and height or if they are the physical dimensions of the sprite/object.

Shu Sam Chen

unread,
Mar 11, 2017, 6:36:15 PM3/11/17
to excaliburjs
Other things happened, sorry for letting this drop. Re-reading the thread, it seems that we dropped down a level of abstraction and started to talk about getWidth() and getHeight(), which seems to be linked into the drawing logic?

I can understand the logic behind the design decision that says "just because the actor is rotated, don't change its width and height", but I don't really agree. If I set the rotate an object, I expect its bounding box to change.

(This issue is still present in 0.9.0)

Erik Onarheim

unread,
Mar 12, 2017, 12:00:42 PM3/12/17
to excaliburjs
Hi Sam, 

No worries, we all get busy with stuff :) 

I agree about bounding boxes, the physical bounding box of a rotating object should and does change now in actor.getBounds().getWidth() or actor.getBounds().getHeight() when actors are rotated. However, to expand on Kamran's point, think of Actors as a higher abstraction, more like a person, no matter a person's orientation, it doesn't change how tall or wide they are. This is the reason Actor.getHeight() and Actor.getWidth() do not change with orientation, it provides a nice way to know the height or width that is intrinsic to an actor (like a player character) regardless of orientation.

Actor.getBounds() operates on the physical object and will return the updated rectangular bounding box that the actor currently occupies, taking into account all transformations.

In 0.8.0 we corrected the behavoir of actor.getBounds() to operate as described above to solve this problem (https://github.com/excaliburjs/Excalibur/issues/692). 

You can see this in the codepen https://codepen.io/eonarheim/pen/JWNwov?editors=0012 it will do what you need.

Shu Sam Chen

unread,
Mar 30, 2017, 7:59:41 AM3/30/17
to excaliburjs
Hi Erik,

I think there's been a little bit of confusion, which is mostly down to me asking an question that may have been too abstract. Here's a better description of my problem, with a few screenshots.

I'm using Actors to handle the graphics of sprites in my scene through actor.addDrawing(). This is where I'm not seeing things rotate as they should - while I would also expect actor.getBounds() to correlate with the rotation, the problem here is purely graphical (I've handed off physics to P2, which provides its own AABB system).

Screenshots! Apologies for the poor contrast, they were taken quickly. In both screenshots, I have two actors. Both are formed from the same sprite base, but the left one is scaled on a 6:1 aspect ratio to illustrate my point better. The left actor is "pointing at" the right one - that is, its angle is a vector from the centre of the left crosshair to the centre of the right crosshair. I would have expected, in the second screenshot, that the left crosshair should now be stretched vertically - since it's turned 90 degrees from the first screenshot. But it hasn't, and it still maintains an X that is 6 times wider than Y.

(Interesting, and possibly related note, that this effect seems much less pronounced when I use a source image that isn't square).






Shu Sam Chen

unread,
Mar 30, 2017, 8:00:39 AM3/30/17
to excaliburjs
And because I'm not very familiar with Google Groups' WYSIWYG editor, you'll have to expand the quoted text to see the screenshots. Sorry!

--
Sam

Kamran Ayub

unread,
Mar 30, 2017, 9:09:34 AM3/30/17
to Shu Sam Chen, excaliburjs
Just to clarify, this is using the latest stable release? Scaling/coordinates/bounds were all sorts of messed up before one of the recent releases.

--
You received this message because you are subscribed to the Google Groups "excaliburjs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to excaliburjs...@googlegroups.com.
To post to this group, send email to excal...@googlegroups.com.
Visit this group at https://groups.google.com/group/excaliburjs.
To view this discussion on the web visit https://groups.google.com/d/msgid/excaliburjs/d08b9366-3d51-4165-97eb-d25e20421a7e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shu Sam Chen

unread,
Mar 30, 2017, 9:12:08 AM3/30/17
to excaliburjs, research....@gmail.com
That's a fair question. I'm using the following:

Excalibur 0.9.0
Electron 1.6.2
Typescript 2.1.6

It's a fairly exotic combination of tools, but very functional :)

Kamran Ayub

unread,
Mar 30, 2017, 9:16:34 AM3/30/17
to Shu Sam Chen, excaliburjs
No that's pretty awesome, I wonder if it'd be possible to share your example on CodePen (sans Electron) or in a zip package we could look at to take a closer look? It would be hard for me to figure it out just by looking.

Kamran Ayub

unread,
Mar 30, 2017, 9:21:14 AM3/30/17
to Shu Sam Chen, excaliburjs
Oh sorry, one other thing you could take a capture of is Debug mode (game.isDebug = true) since that should draw the centers and bounding boxes of the Actors.

Perhaps this is just that bug occurring too?

Kamran Ayub

unread,
Mar 30, 2017, 9:24:48 AM3/30/17
to excaliburjs, research....@gmail.com
Sorry, added an extra sentence mistakenly at the end. I thought it might be a known bug but that was fixed in 0.8 I think

Shu Sam Chen

unread,
Mar 30, 2017, 9:27:28 AM3/30/17
to excaliburjs, research....@gmail.com
I could zip up my compiled project without electron if you'd like, but it's also on GitHub. I've cut out a lot of unrelated, semi-working garbage (ah, side projects eh?) and put a working example on a branch here:

Most of the relevant code is here:

I have to apologise in advance, I did a lot of wrapping so you'll need to tease your way through an abstraction layer or two.

Let me know if you'd like the zip, that's only about 300kb of raw text. Should compress well.

Thanks for your time!
--
Sam

Erik Onarheim

unread,
Mar 30, 2017, 10:48:12 PM3/30/17
to excaliburjs, research....@gmail.com
Hi Sam,

I can definitely reproduce your issue, I've opened up an issue on excalibur to fix this https://github.com/excaliburjs/Excalibur/issues/770 and opened a PR on your repo with a workaround https://github.com/HSAR/Caldwell/pull/1/files

This is definitely not the way I would expect scaling+rotation to work :(

There is a work around that will work for you, by setting the sprite scale directly and not the actor scale, things draw as expected.


Also, when you add sprites to actors with same base texture you'll want to clone them to prevent scaling effects like this workaround from propagating to anything using that texture.




Also would you be interested in a Google Hangouts call sometime? We'd like to gather your thoughts on Excalibur, improvements/points of confusion/features/bugs/etc.


Let us know,
Erik

Shu Sam Chen

unread,
Mar 31, 2017, 5:10:16 AM3/31/17
to excaliburjs, research....@gmail.com
Thanks Erik and Kamran, I really appreciate you both taking time to look into this.

I'm not sure I have all that much to offer you in terms of feedback - this is a much-neglected personal project with perhaps a few dozen man-hours spent on it. But sure, more than happy to spend some time talking about it.

--
Sam
Reply all
Reply to author
Forward
0 new messages