Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single sprite covering a composite body? #153

Closed
erzahurak opened this issue Sep 12, 2015 · 13 comments
Closed

Single sprite covering a composite body? #153

erzahurak opened this issue Sep 12, 2015 · 13 comments
Labels

Comments

@erzahurak
Copy link

I'm experimenting with importing shapes from SVG, and that's working pretty well, but I'd like to apply a single sprite over top of the composite body that's created. (See the svg demo stuff; Bodies.fromVerticies).

Is there an easy way to do this? Currently, it applies the same sprite to all composite shapes.

Thanks!

@liabru
Copy link
Owner

liabru commented Sep 16, 2015

Currently the function copies all of the options to all of the body parts, looks like I need to add an exception so that sprites don't get copied.

In the meantime, after you create your body, can you try loop through body.parts from index 1 (important) and then set each part.sprite = null?

@erzahurak
Copy link
Author

Been working on this here, too. Looping through body.parts isn't enough,
because the sprite is still tied to a component, rather than the body, and
that makes for some alignment issues. And there's some fun, fun issues
with aligning the sprite and the body because the bounds and position
aren't equivalent in the sprite and the body. Slowing working through the
trigonometry to make that work, too. I'll be happy to share my ugly
solution with you when it's done, but you may want to pretty it up. :)

On Wed, Sep 16, 2015 at 6:58 AM, Liam notifications@github.com wrote:

Currently the function copies all of the options to all of the body parts,
looks like I need to add an exception so that sprites don't get copied.

In the meantime, can you try loop through body.parts from index 1 and
then set each part.sprite = null?


Reply to this email directly or view it on GitHub
#153 (comment).

@liabru
Copy link
Owner

liabru commented Sep 16, 2015

Please do share an example that demonstrates the issues. Compound bodies are a relatively new feature and support for rendering is pretty limited right now.

looping through body.parts isn't enough, because the sprite is still tied to a component, rather than the body

This is correct, I assumed earlier that you only wanted one sprite for the whole body.

If you actually do want different sprites for each part, then things will be trickier to set up initially.
But this is to be expected?

@erzahurak
Copy link
Author

No, no, I want to do one sprite per the entire object. I guess my
terminology isn't correct.

Using the SVG demo as a base, I'm able to pull in non-convex polygon shapes
from SVG. Matter does this by breaking the SVG path down into a bunch of
convex polygons, which are treated as a body made up of a whole lot of
parts.

I'm looking to do just one sprite for the entire body and I'm having some
decent success in doing so, except that I can't get the two to align
correctly at the moment, mostly because the body "origin" is its center of
mass (as near as I can tell) and the sprites origin is the top left.
Translating one to the other is proving frustrating. The centering stuff
you used for the circles and squares of the sprites demo would be easy, but
they just don't work here. An irregular shape, like, say, a kitten? It's a
little trying. There's probably a simple way to do it that I'm completely
ignorant of; I'm just not a big math and vectors guy. I expect to
recollect enough of my high school trigonometry classes within the next
couple of days to solve my problem.

Different sprites per body part would be cool, but I'm not looking for that
any time soon. :)

On Wed, Sep 16, 2015 at 9:59 AM, Liam notifications@github.com wrote:

Please do share an example that demonstrates the issues. Compound bodies
are a relatively new feature and support for rendering is pretty limited
right now.

looping through body.parts isn't enough, because the sprite is still tied
to a component, rather than the body

This is correct, I assumed earlier that you only wanted one sprite for the
whole body.

If you actually do want different sprites for each part, then things will
be trickier.
But this is to be expected?


Reply to this email directly or view it on GitHub
#153 (comment).

@liabru
Copy link
Owner

liabru commented Sep 17, 2015

Actually, looks like this is due to an oversight in Render.js line 431.

The offset is assumed to be half the sprite dimension, but this only works when the centre of mass is the same as the centre of the sprite. Doh. Looks like a fix is needed here!

@erzahurak
Copy link
Author

I've sort of got one, but at the moment it requires me to pass in the
min/max bounds of the body at 0 radians rotation to use to later calculate
an offset. I'm thinking of moving those values into the Body itself, and
having them created/stored with a new body.

My codes in no shape to just push it to the project. If you want to email
me your contact info, I'll email you what I have so far.

It's pretty fast, but I've noticed an odd behavior in the process. If I
render all shapes, my frame rate stays right about 60fps. If I render just
sprites, it stays around 60fps. If I render sprites AND shapes, my fps
drops dramatically to about 20fps. Some I'm trying to figure that out
first.

On Thu, Sep 17, 2015 at 2:11 PM, Liam notifications@github.com wrote:

Actually, looks like this is due to an oversight in Render.js line 431
https://github.com/liabru/matter-js/blob/master/src/render/Render.js#L431-L432
.

The offset is assumed to be half the sprite dimension, but this only works
when the centroid is the same as the centre of the sprite. Doh. Looks like
a fix is needed here!


Reply to this email directly or view it on GitHub
#153 (comment).

@lanewinfield
Copy link

I would love to see an example of this code. Currently attempting to do the same thing—applying a texture to a concave composite body.

@erzahurak
Copy link
Author

Hi Brian, I have it, but it's ugly. I'm quite hesitant to put it in the
project officially. If you want to email me directly (erzahurak@gmail.com)
I'll zip up what I've got and send it to you.

Ed

On Sun, Jan 24, 2016 at 2:12 PM, Brian Moore notifications@github.com
wrote:

I would love to see an example of this code. Currently attempting to do
the same thing—applying a texture to a concave composite body.


Reply to this email directly or view it on GitHub
#153 (comment).

@scottglz
Copy link

scottglz commented Feb 6, 2016

I took a stab at a pretty simple solution to this, where I modified the renderer to render the main body and not the parts when it has a sprite. See my pull request.

@majman
Copy link

majman commented Apr 29, 2016

You might be able to use fillstyle = canvas pattern to achieve something similar:
http://codepen.io/majman/pen/reqzBW?editors=0010

@liabru
Copy link
Owner

liabru commented Apr 29, 2016

@majman Awesome! Love it.

@willmcl
Copy link

willmcl commented Sep 30, 2022

Anyone coming across this. I had some success with creating a rectangle that has a collision filter of 0 (to not collide with anything) that would serve to hold the sprite. Then I attached it to the body using 2 constraints. It can sometimes be slightly jittery, but for my purposes it achieved what I needed:

let body = Bodies.fromVertices(x, y, vertexSets, {
            render: {
              fillStyle: 'none',
              strokeStyle: 'none',
              lineWidth: 1,
              slop: 0,
            },
          }, true)
          let spriteHolder = Bodies.rectangle(
            body.bounds.min.x,
            body.bounds.min.y,
            (body.bounds.max.x - body.bounds.min.x),
            (body.bounds.max.y - body.bounds.min.y),
            {
              collisionFilter: {
                mask: 0,
              },
              render: {
                fillStyle: 'none',
                strokeStyle: '#ffffff',
                sprite: {
                  texture: './texture.png',
                  xOffset: 0,
                  yOffset: 0,
                }
              }
            }
          )
          let constraint = Constraint.create({
            bodyA: body,
            pointA: {x: 0, y: 10},
            bodyB: spriteHolder,
            pointB: {x: 0 y: 10},
            length: 0
          });
          let constraint2 = Constraint.create({
            bodyA: body,
            pointA: {x: 0, y: -10},
            bodyB: spriteHolder,
            pointB: {x: 0, y: -10},
            length: 0
          });

          let group = Composite.create({label: `group`});
          Composite.add(group, [body, spriteHolder, constraint, constraint2])
          Composite.add(world, group)

@Samgeven
Copy link

@willmcl Awesome solution! Works even better, if constraints have slightly increased stiffness. I tried 1.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants