Search code examples
ioscocos2d-iphonebox2dscalegame-physics

GB2ShapeCache Shape Scale? (Physics Editor) [Box2D]


There is a class associated with the program Physics Editor called GB2ShapeCache that loads shapes that I make in the program. I noticed that it is not currently possible to change the scale of the shapes on the fly so I would like to be able to scale the fixtures for the shapes that I made in Physics Editor. Now the scale of my CCSprite in my app can be random so currently in the addShapesWithFile method, I do this for polygons:

vertices[vindex].x = (offset.x * sprite.scaleX) / ptmRatio_;
vertices[vindex].y = (offset.y * sprite.scaleY) / ptmRatio_;

and this for circles:

circleShape->m_radius = ([[circleData objectForKey:@"radius"] floatValue] / ptmRatio_) *sprite.scale;

I also changed the method so that I can pass in my sprite so I can get the scale to:

-(void) addShapesWithFile:(NSString*)plist forSprite:(CCSprite*)sprite

so that I can pass in my sprite so I can get the scale.

HOWEVER, I find this to be inefficient because I should not have to reload ALL my shapes in my plist since they are already added.

So is there any way to do what I am doing now but in the addFixturesToBody method? This way I do not re-create the already added plist shapes and I only scale the fixtures when it is ready to be added to my body.

If anyone needs to see more code or needs more info, feel free to ask. I know this issue must be simple!!!

Thanks!


Solution

  • I would recommend implementing it in the addFixturesToBody method. (see https://github.com/AndreasLoew/GBox2D/blob/master/GBox2D/GB2ShapeCache.mm)

    Try this method below, this should scale the shapes accordingly to the sprite's they are for. Just pass in your CCSprite and this method will handle the rest.

    - (void)addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape forSprite:(CCSprite*)sprite {
        BodyDef *so = [shapeObjects_ objectForKey:shape];
        assert(so);
    
        FixtureDef *fix = so->fixtures;
    
        if ((sprite.scaleX == 1.0f) && (sprite.scaleY == 1.0f)) {
            // simple case - so do not waste any energy on this
            while(fix) {
                body->CreateFixture(&fix->fixture);
                fix = fix->next;
            }
        } else {
            b2Vec2 vertices[b2_maxPolygonVertices];
            while(fix) {
                // make local copy of the fixture def
                b2FixtureDef fix2 = fix->fixture;
    
                // get the shape
                const b2Shape *s = fix2.shape;
    
                // clone & scale polygon
                const b2PolygonShape *p = dynamic_cast<const b2PolygonShape*>(s);
                if(p)
                {
                    b2PolygonShape p2;
                    for(int i=0; i<p->m_vertexCount; i++)
                    {
                        vertices[i].x = p->m_vertices[i].x * sprite.scaleX;
                        vertices[i].y = p->m_vertices[i].y * sprite.scaleY;
                    }
                    p2.Set(vertices, p->m_vertexCount);
                    fix2.shape = &p2;
                }
    
                // clone & scale circle
                const b2CircleShape *c = dynamic_cast<const b2CircleShape *>(s);
                if(c) {
                    b2CircleShape c2;
                    c2.m_radius = c->m_radius * sprite.scale;
                    c2.m_p.x = c->m_p.x * sprite.scaleX;
                    c2.m_p.y = c->m_p.y * sprite.scaleY;
                    fix2.shape = &c2;
                }
    
                // add to body
                body->CreateFixture(&fix2);
                fix = fix->next;
            }    
        }    
    }