question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Request: Allow for offsetting 2D elements drawing positions relative to their actual positions

See original GitHub issue

Hey, I’ve been looking for a way to modify where sprites are drawn relative to their position, similar to the .origin() feature allowing to change where they are rotated. At first I thought that .shift() is the solution, but It seems that shift doesnt actually shift any internal values, but actually “hard” shifts the position. This feature might not seem like an absolute must if you design your game around the engines way of doing things, but it could for sure be a useful feature for a lot of devs who are used to this. Many game developers are used to having an entities position in the center, as this often works best with how games logic is programmed. Simple example: Have a top down game where you control a spaceship. When you shoot, you want to spawn the projectiles at the center of the ship. Currently this would mean you have to compute the center yourself by taking the ships size as a vector and halve it, add it to the original position… etc.

My proposal for this would be simple; Add a function to the 2D element which takes similar inputs as .origin(). Allow for input such as “center”, “top left” etc, for easy use - or alternatively allow for input as fixed values.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
mucahocommented, Mar 24, 2016

I have been thinking about this for quite some time now and have managed to come up with a proposal. If you’re interested keep on reading, I’d be happy about any comments that anyone has about this proposal (also cc @starwed )


It’d be a pretty fundamental change, so I have considered the ideas as noted in the comments by dekdevy and Sythe2o0.

Any change that is introduced should minimize the impact on:

  • backwards compatibility
  • performance
  • api design bloat

Here’s what I propose:

  • Move w & h from 2D to the Renderable component.
    Reason: Width and height have little to no meaning when talking about a logical anchor (a spatial point in space), they are most closely related to stuff with dimensions like images & sprites. They could be set & changed automatically for Image & Sprite components, in addition to manually changing them for e.g. the Color component.
  • Introduce scaleX & scaleY to 2D and retain the x, y & rotation properties.
    Reason: The x & y properties now serve as aliases to the translation. The rotation property matches the rotation transform syntactically. Additionally, we would still like to scale things, hence the default scale of 1 can be altered to scale the Collision hitbox, the Renderable component, as well as any _children in the scene graph. A negative scale -1 could allow flipping the entity on an axis.
  • Change Collision & Crafty.map logic to consider the newly introduced scale properties, rather than the display related w & h properties. Viewport would still use them, as some viewport’s methods depend on display stuff (like display boundaries of all entities).
    Reason: These functionalities are display agnostic. Collision already works with point coordinates, it should be simple to adapt Crafty.map to work with top-left corner & bottom-right corner coordinates too (see also starwed’s comment on that).
  • Augment origin to also set the origin of the Renderable component and the Collision hitbox.
    Reason: This would serve to specify the offsets from the origin where these components are “attached”, as well as around which point they are rotated around. It’d default to the current “top-left” origin. Setting it to “center” would make a Sprite start at -w/2 and end at w/2.

What are the implications of implementing this proposal?

  • (+) Solves this feature request.
    • The enhanced origin allows to specify this offsets, as suggested by dekdevy.
  • (+) Doesn’t introduce many additional API functions
    • Future code will almost look the same as before. (Unlike the monstrosity I proposed in previous comment).
    • You’d still do something like Crafty.e("2D, Canvas, PlayerSprite").attr({x: 10, y: 20, w: 64, h: 32}) in most cases, with the possibility to omit w & h so that they are set by the sprite dimensions.
  • (+) Logic code becomes even more decoupled from display code.
    • Enables possible further optimizations (like asm.js).
    • Easier integration of 3rd party libraries into custom Crafty components that fill the roles of a 3rd party collision system (e.g. Box2D, PhysicsJS) or a render system (e.g. pixi.js).
  • (-) Not ideal backwards compatibility on user side
    • Changing w & h won’t affect collision hitboxes any more. Slight changes to Crafty.map signatures. Collision’s “automatically”-computed hitbox will require a tad more explicit user interaction.
    • Existing code that sets origin to center would be shifted w/2 to the left and thus cause incorrect display of this entity.
    • Existing code that has rotation applied to entities and does some calculations based on the spatial properties of these properties will cease to work correctly.
    • Rest of code should work fine.
  • (-) To be determined impact on performance.
    • The origin offset and scale have to additionally be considered when calculating final drawing positions.
    • The MBR will now always have to be computed each render frame (see below). Computation can be postponed until MBR is needed - multiple update frames before single render frame won’t trigger unnecessary calculations.
    • This is still more performant than having separate (logical anchor) parent and (renderable / collidable) children that simulate local and world coordinate systems, as described in my previous comment.
  • (-) Maybe tricky to change current Crafty implementation
    • There are more than 300 places (many of them are documentation though), where w or _w are used in the Crafty library. In these (and possibly other places) current code has to be changed.
    • There is a big change to the semantics of x, y - they represent the translation transform in world space. That means they are no longer updated on rotation. Final drawing x and y coordinates won’t match these, that’s why the MBR (and possibly the drawing rectangle) has to be computed each render frame.
    • The drawing rectangle represents the final drawing rectangle in world space, after all transformations (translation, rotation, scale) are applied to a Renderable component’s dimensions and origin offset. This drawing rectangle does not have to be computed in render code at all, since each rendering backend (DOM, Canvas, WebGL) supports supplying the above mentioned transformations. The browser thus calculates the drawing rectangle for us implicitly and our render code can draw in simplified, local space.
      However, the drawing rectangle might be of interest to library users (in addition to performing calculations on the collision hitbox).
    • MBR now represents the final entity minimum bounding rectangle in world space, which is just an axis-aligned minimum bounding rectangle of the drawing rectangle (mentioned in the prior point). Because Crafty supports redrawing only parts of the Canvas, the MBR is used to persist each entity’s drawing area to an indexable spatial map. Calculating the MBR might be based on the same computational steps as for computing the drawing rectangle, however I’ll have to investigate this further.

Last update to this post: 10:18 PM Thursday, March 24, 2016 Coordinated Universal Time (UTC)

0reactions
starwedcommented, Mar 11, 2017

Opened PR #1089 that provides some related functionality.

Read more comments on GitHub >

github_iconTop Results From Across the Web

True Position – Position Tolerance | GD&T Basics
It allows the position of the part to be dependent on the feature's actual size. It does this by allowing a bonus tolerance...
Read more >
What is the difference between position and offset in Konva
In the post I will explain the difference between position (x and y coordinates) and offset (offsetX and offsetY). So x and y...
Read more >
Real mouse position in canvas - javascript - Stack Overflow
It returns an object with x and y for the mouse positions. As the mouse position you are getting is relative to the...
Read more >
Position Constraints - Unity - Manual
Activate saves the current offset from the source GameObjects in Position At Rest and Position Offset, then checks Is Active and Lock.
Read more >
Offsetting Receipts are collections that are credited to general ...
A -136, as revised June 2008.) The Bureau of the Fiscal Service (Fiscal Service) has established new guidance in the Quarterly Receipts by...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found