ios - How to add physicsBody to tiles generated by JSTileMap and change them into one physicsBody -
i use jstilemap draw level. changed little bit add skphysicsbody every tile when apply impulse main character , hits wall/ground/ceiling acting weird. reflects surfaces way contrary principles of physics. think happens because player hits point 2 physics bodies (for example 2 physics bodies of ground) connects. skphysicsbody class provides method create 1 physics body different physics bodies + (skphysicsbody *)bodywithbodies:(nsarray *)bodies; can use method create 1 physics body ale tiles physics bodies?
here's method jstilemap add physics bodies:
+(id) layerwithtilesetinfo:(nsarray*)tilesets layerinfo:(tmxlayerinfo*)layerinfo mapinfo:(jstilemap*)mapinfo { tmxlayer* layer = [tmxlayer node]; layer.map = mapinfo; layer.tilesbycolumnrow = [nsmutabledictionary dictionary]; // basic properties layerinfo layer.layerinfo = layerinfo; layer.layerinfo.layer = layer; layer.maptilesize = mapinfo.tilesize; layer.alpha = layerinfo.opacity; layer.position = layerinfo.offset; // recalc offset if 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 tiles (nsinteger col = 0; col < layerinfo.layergridsize.width; col++) { (nsinteger row = 0; row < layerinfo.layergridsize.height; row++) { // gid nsinteger gid = layerinfo.tiles[col + (nsinteger)(row * layerinfo.layergridsize.width)]; // mask off flip bits , remember 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; // tileset passed gid. allow support multiple tilesets! tmxtilesetinfo* tilesetinfo = [mapinfo tilesetinfoforgid:gid]; [layer.tileinfo addobject:tilesetinfo]; if (tilesetinfo) // should never 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 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 correct node tileset sknode* layernode = layernodes[tilesetinfo.name]; if (!layernode) { layernode = [[sknode alloc] init]; layernodes[tilesetinfo.name] = layernode; } //adding physicsbody 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 tilesets used in layer (sknode* layernode in layernodes.allvalues) { if (layernode.children.count > 0) { [layer addchild:layernode]; } } [layer calculateaccumulatedframe]; return layer; }
after adding physics bodies every tile , adding physics bodies nsmutablearray assign copy of nsmutablearray nsarray , try create 1 physics body out of this:
//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]; //-----||------
in result, 1 physics body height , width of 1 tile added.
if want use [skphysicsbody bodywithbodies:array], need make sure bodies in array relative parent node.
sprite.physicsbody = [skphysicsbody bodywithrectangleofsize:sprite.frame.size];
means physics body position relative sprite node. need body relative parent node.
the way know how center:
sprite.physicsbody = [skphysicsbody bodywithrectangleofsize:sprite.frame.size center:sprite.position];
this should place skphysicsbody
@ location of sprite when added parent node.
Comments
Post a Comment