2016-11-10 12 views
0

レベルを描画するのにJSTileMapを使用します。私はSKPhysicsBodyをすべてのタイルに追加するためにそれを少し変更しましたが、時には主人公にいくつかの衝動を適用し、壁/地面/天井にぶつかり、彼が変な動作をしています。彼は物理学の原理に反する方法で表面から反射する。私は、プレイヤーが2つの物理機関(地上の2つの物理機関など)が接続するポイントにヒットするために起こると思います。 SKPhysicsBodyクラスは、異なる物理ボディから1つの物理ボディを作成するメソッドを提供します。+(SKPhysicsBody *)bodyWithBodies:(NSArray *)bodies;このメソッドを使って、タイルの物理学のボディから1つの物理ボディを作成できますか?ここでJSTileMapで生成されたタイルにphysicsBodyを追加して1つのphysicsBodyに変更する方法

は、私は物理学の遺体を追加JSTileMapからの方法です:

+(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のにそれらの物理体を追加した後、私はNSArrayのこのNSMutableArrayののコピーを割り当て、作成しよう

//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]; 
     //-----||------ 

結果として、1つのタイルの高さと幅を持つ物理的ボディが1つ追加されます。

答えて

1

[SKPhysicsBody bodyWithBodies:array]を使用する場合は、配列内のすべてのボディが親ノードからの相対位置であることを確認する必要があります。

sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.frame.size];は、物理ボディの位置がスプライトノードからの相対位置であることを示します。親ノードに相対的なボディが必要です。

私はこれを行う方法を知っている唯一の方法は、中心にある:

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

これは、それが親ノードに追加されたスプライトの場所でSKPhysicsBodyを配置する必要があります。

+0

ありがとう、私はすべてのタイルから作られた1つの物理学のボディを作成することができますが、奇妙な動作は消えませんでした。私はbodyWithBodiesメソッドがどうにかしてすべてのボディを接続し、それらの間の接続を削除すると思ったが、それはあなたがすべてのボディを1つ(移動、配置など)として扱うのに役立ちます。 – mfker

+0

奇妙な行動 – Knight0fDragon

+0

私は主人公にいくつかの衝動を適用し、彼は壁/地面/天井にぶつかり、彼は奇妙な行動をしています。彼は物理学の原理に反する方法で表面から反射する。例えば、彼が右に動いたとき(インパルスが加えられたとき)、彼は時々天井から反射して、時には後ろに移動し始める(左)。 – mfker

関連する問題