tzachshabtay / MonoAGS

AGS (Adventure Game Studio) reimagined in Mono
https://tzachshabtay.github.io/MonoAGS/
Artistic License 2.0
27 stars 8 forks source link

Suggestion: properties for getting absolute position of an entity #267

Closed ghost closed 6 years ago

ghost commented 6 years ago

Currently ITranslateComponent only lets you know one set of coordinates, which is in fact parent-relative coordinates (although comments tell they are room coordinates, but that's true only when object has no parent). At the same time API does not provide a way to get absolute (room) coordinates of an entity.

When that may be useful: many kind of situations - collision checking for instance, - but most easy example is camera targetting. By the way, right now default camera has a related bug: it does not take object's parents into account (which may be also added as a separate ticket).

My suggestion is to add following properties:

Common implementation would be to sum up current entity's XY coords with each parent along the tree upwards (if anchors are implemented (#245), this should also take them into account).

I was in doubts what interface to put these though. ITranslate is the first that comes to mind, but then, it does not necessarily belong to something that may have parent. OTOH maybe that's not a big deal (we may assume that in enviroment where you don't have entity trees local and absolute coordinates always match). The only alternative that comes to mind is IInObjectTreeComponent, or even IInTree. But that not necessary something that may have location, so could be even worse option.

Finding a place to implement it seem also a bit complicated. If these properties are in ITranslate , then AGSTranslateComponent is again the first option, but the issue is that it should bind to IInTree somehow, and idk if it's possible to do that without knowing actual end type of an entity. And IInObjectTreeComponent seem too specific to put into ITranslate implementation.

tzachshabtay commented 6 years ago

Isn't this a duplicate of #149 ?

At the same time API does not provide a way to get absolute (room) coordinates of an entity.

GetBoundingBoxes(viewport).HitTestBox gives you the absolute room coordinates. Note that the API here is not ideal- you don't really need to pass the viewport as the hit test box is the same for all viewports, it's just that the bounding boxes also contain the render box which is unique to the viewport.

I was in doubts what interface to put these though.

I was thinking of having a separate component for this.

ghost commented 6 years ago

Isn't this a duplicate of #149 ?

In #149 you say:

I was thinking of adding a boolean value that would tell engine how the position should be interpreted (local or absolute).

Which means that child object's X,Y could be either local or absolute?

What I propose is a way to get absolute coordinates regardless of whether childrens position is interpreted as local or absolute.

I think another solution, maybe temporary, is to make extension methods for IObject.

tzachshabtay commented 6 years ago

Well, that was the original thinking, but then you mentioned in your comment the absolute position property, which is the same as what you suggest here, and I find it's a duplicate in the sense that we'll either do this or that, but not both, they aim to solve pretty much the same problem.

Anyway, if it's just about getting the absolute position (as opposed to setting it, which #149 aims to give a solution to), then GetBoundingBoxes has you covered, with the exception that you get a complete rectangle and not a single point. And if you want to apply the pivot to get a single point from the box, then I think interpolating along the edges of the bounding boxes should do the trick, and no reason to do it in an IObject extension method when we can do it in a component which can be applied to more entities.

I guess we can keep this issue open just to do the getter, and leave the setter for the other issue (the setter is much more complicated to implement, we basically need to invert all of the matrices up the chain).

ghost commented 6 years ago

These properties may have setters too. It's just that I was not sure what you may want the boolean switch for, because it seem to have different effect. Since most code will probably work with just X and Y properties, switching the meaning of these may change the looks of the game a lot. Then again, maybe I don't understand the meaning of the #149.

AbsoluteX/Y properties are more explicit, so you can use them when you're sure you want to get or change absolute position regardless of what the object is attached to.

Anyway, if it's just about getting the absolute position (as opposed to setting it, which #149 aims to give a solution to), then GetBoundingBoxes has you covered,

Uhhh, to be frank, I don't like to use this API to just get two coordinates, that's all. As a temporary solution I could make a helper methods in my game which just return X and Y from a bounding box. It just needed a fix for camera to keep character in the center of screen.

And yes, I completely forgot about taking parent rotation into account...

ghost commented 6 years ago

Hmm... realized that bounding box may be actually more convenient for camera centering and other things than position. For camera you may get center of the box. Position is less reliable here, because of the pivot.

Hmm... weird, I did not think about this earlier for some reason. Guess this makes properties for getting absolute position less important then.

tzachshabtay commented 6 years ago

Ok, so I'm closing this issue in favor of #149 which will cover that property with both a getter and a setter. If you end up feeling that you do want a getter soon, comment and I'll re-open (as coding the getter will be much easier than the setter). Otherwise this will probably sit in the backlog for a while, as I don't consider it a high priority.

ghost commented 6 years ago

Question, would it be acceptable to modify AGSCamera to get target x,y as following:

AGSBoundingBox hitBox = target.GetBoundingBoxes(viewport).HitTestBox;
float targetX = (hitBox.MaxX + hitBox.MinX) / 2;
float targetY = (hitBox.MaxY + hitBox.MinY) / 2;

From the looks of it, that fixes camera issue when target object is a child of another object.

tzachshabtay commented 6 years ago

Yes, definitely (just test to make sure it still works as expected in the demo game). Also, might be worth to add a GetCenterPoint function to AGSBoundingBox and use that.