首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将physicsBody添加到由JSTileMap生成的切片中并将其更改为一个physicsBody

如何将physicsBody添加到由JSTileMap生成的切片中并将其更改为一个physicsBody
EN

Stack Overflow用户
提问于 2016-11-10 21:59:38
回答 1查看 108关注 0票数 0

我使用JSTileMap来绘制一个标高。我稍微修改了一下,将SKPhysicsBody添加到每一块瓷砖上,但有时当我对主要角色施加一些冲动时,他会撞到墙上/地面/天花板上,他表现得很奇怪。他从表面反射的方式与物理学原理相悖。我认为这是因为玩家击中了两个物理体(例如地面的两个物理体)的连接点。SKPhysicsBody类提供了一个方法来从不同的物理体+ (SKPhysicsBody *)bodyWithBodies:(NSArray *) body创建一个物理体;我可以使用这个方法从ale tiles物理体创建一个物理体吗?

这是一个来自JSTileMap的方法,我在其中添加了物理体:

代码语言:javascript
复制
+(id) layerWithTilesetInfo:(NSArray*)tilesets layerInfo:(TMXLayerInfo*)layerInfo mapInfo:(JSTileMap*)mapInfo
{
    TMXLayer* layer = [TMXLayer node];
  layer.map = mapInfo;

    layer.tilesByColumnRow = [NSMutableDictionary dictionary];
    // basic properties from layerInfo
    layer.layerInfo = layerInfo;
    layer.layerInfo.layer = layer;
    layer.mapTileSize = mapInfo.tileSize;
    layer.alpha = layerInfo.opacity;
    layer.position = layerInfo.offset;

    // recalc the offset if we are isometriic
    if (mapInfo.orientation == OrientationStyle_Isometric)
    {
        layer.position = CGPointMake((layer.mapTileSize.width / 2.0) * (layer.position.x - layer.position.y),
                                     (layer.mapTileSize.height / 2.0) * (-layer.position.x - layer.position.y));
    }

    NSMutableDictionary* layerNodes = [NSMutableDictionary dictionaryWithCapacity:tilesets.count];

    //MY CODE
    NSMutableArray *arrayOfSprites = [[NSMutableArray alloc] init];
    SKNode *theSprite;
    //----||----

    // loop through the tiles
    for (NSInteger col = 0; col < layerInfo.layerGridSize.width; col++)
    {
        for (NSInteger row = 0; row < layerInfo.layerGridSize.height; row++)
        {
            // get the gID
            NSInteger gID = layerInfo.tiles[col + (NSInteger)(row * layerInfo.layerGridSize.width)];

            // mask off the flip bits and remember their result.
            bool flipX = (gID & kTileHorizontalFlag) != 0;
            bool flipY = (gID & kTileVerticalFlag) != 0;
            bool flipDiag = (gID & kTileDiagonalFlag) != 0;
            gID = gID & kFlippedMask;

            // skip 0 GIDs
            if (!gID)
                continue;

            // get the tileset for the passed gID.  This will allow us to support multiple tilesets!
            TMXTilesetInfo* tilesetInfo = [mapInfo tilesetInfoForGid:gID];
            [layer.tileInfo addObject:tilesetInfo];

            if (tilesetInfo)    // should never be nil?
            {
                SKTexture* texture = [tilesetInfo textureForGid:gID];
                SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:texture];

                sprite.name = [NSString stringWithFormat:@"%ld",(long)(col + row * layerInfo.layerGridSize.width)];

                // make sure it's in the right position.
                if (mapInfo.orientation == OrientationStyle_Isometric)
                {
                    sprite.position = CGPointMake((layer.mapTileSize.width / 2.0) * (layerInfo.layerGridSize.width + col - row - 1),
                                                  (layer.mapTileSize.height / 2.0) * ((layerInfo.layerGridSize.height * 2 - col - row) - 2) );
                }
                else
                {
                    sprite.position = CGPointMake(col * layer.mapTileSize.width + layer.mapTileSize.width/2.0,
                                                  (mapInfo.mapSize.height * (tilesetInfo.tileSize.height)) - ((row + 1) * layer.mapTileSize.height) + layer.mapTileSize.height/2.0);
                }

                // flip sprites if necessary
                if(flipDiag)
                {
                    if(flipX)
                        sprite.zRotation = -M_PI_2;
                    else if(flipY)
                        sprite.zRotation = M_PI_2;
                }
                else
                {
                    if(flipY)
                        sprite.yScale *= -1;
                    if(flipX)
                        sprite.xScale *= -1;
                }

                // add sprite to correct node for this tileset
                SKNode* layerNode = layerNodes[tilesetInfo.name];
                if (!layerNode) {
                    layerNode = [[SKNode alloc] init];
                    layerNodes[tilesetInfo.name] = layerNode;
                }

                //adding physicsbody to every tile
                //sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(sprite.frame.size.width, sprite.frame.size.height)];
                //sprite.physicsBody.dynamic = NO;
                //sprite.physicsBody.categoryBitMask = mapCategory;

                //[arrayOfSprites addObject:sprite.physicsBody];

                [layerNode addChild:sprite];
                NSUInteger indexes[] = {col, row};
                NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexes length:2];
                [layer.tilesByColumnRow setObject:sprite forKey:indexPath];

                //MY CODE
                sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.frame.size];
                sprite.physicsBody.dynamic = NO;
                [arrayOfSprites addObject:sprite.physicsBody];
                //-----||------

#ifdef DEBUG
//              CGRect textRect = [texture textureRect];
//              NSLog(@"atlasNum %2d (%2d,%2d), gid (%d,%d), rect (%f, %f, %f, %f) sprite.pos (%3.2f,%3.2f) flipx%2d flipy%2d flipDiag%2d", gID+1, row, col, [tilesetInfo rowFromGid:gID], [tilesetInfo colFromGid:gID], textRect.origin.x, textRect.origin.y, textRect.size.width, textRect.size.height, sprite.position.x, sprite.position.y, flipX, flipY, flipDiag);
#endif

            }
        }
    }

    //MY CODE
    NSArray *array = [arrayOfSprites copy];
    theSprite = [SKNode node];
    theSprite.physicsBody = [SKPhysicsBody bodyWithBodies:array];
    theSprite.physicsBody.dynamic = NO;
    theSprite.position = CGPointMake(layer.position.x+16, layer.position.y+16);
    [layer addChild:theSprite];
    //-----||------

    // add nodes for any tilesets that were used in this layer
    for (SKNode* layerNode in layerNodes.allValues) {
        if (layerNode.children.count > 0) {
            [layer addChild:layerNode];
        }
    }

    [layer calculateAccumulatedFrame];

    return layer;
}

在将物理实体添加到每个瓦片并将这些物理实体添加到NSMutableArray之后,我将此NSMutableArray的副本分配给NSArray,并尝试从它创建一个物理实体,如下所示:

代码语言:javascript
复制
//MY CODE
        NSArray *array = [arrayOfSprites copy];
        theSprite = [SKNode node];
        theSprite.physicsBody = [SKPhysicsBody bodyWithBodies:array];
        theSprite.physicsBody.dynamic = NO;
        theSprite.position = CGPointMake(layer.position.x+16, layer.position.y+16);
        [layer addChild:theSprite];
        //-----||------

结果,添加了一个高度和宽度为一个瓦片的物理体。

EN

回答 1

Stack Overflow用户

发布于 2016-11-11 04:49:25

如果要使用数组bodyWithBodies: SKPhysicsBody,则需要确保数组中的所有node都是相对于父节点的。

sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.frame.size];表示您的物理身体位置相对于精灵节点。您需要相对于父节点的body。

我知道如何做到这一点的唯一方法是使用center:

sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.frame.size center:sprite.position];

这将在将精灵添加到父节点时将SKPhysicsBody放置在精灵所在的位置。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40529435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档