J'utilise la fonction suivante pour ajouter des corps physiques sur des tuiles à partir d'un SKTileMapNode:
static func addPhysicsBody(to tileMap: SKTileMapNode, and tileInfo: String){
let tileSize = tileMap.tileSize
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2 * tileSize.width
let halfHeight = CGFloat(tileMap.numberOfRows) / 2 * tileSize.height
for row in 0..<tileMap.numberOfColumns{
for column in 0..<tileMap.numberOfRows{
let tileDefinition = tileMap.tileDefinition(atColumn: column, row: row)
let isCorrectTile = tileDefinition?.userData?[tileInfo] as? Bool
if isCorrectTile ?? false && tileInfo == "wall"{
let x = CGFloat(column) * tileSize.width - halfWidth
let y = CGFloat(row) * tileSize.height - halfHeight
let tileNode = SKNode()
tileNode.position = CGPoint(x: x, y: y)
tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2, y: tileSize.height / 2))
tileNode.physicsBody!.isDynamic = false
tileNode.physicsBody!.restitution = 0.0
tileNode.physicsBody!.categoryBitMask = Constants.PhysicsCategories.wall
tileNode.physicsBody!.collisionBitMask = Constants.PhysicsCategories.player | Constants.PhysicsCategories.npc | Constants.PhysicsCategories.enemy
nodesForGraph.append(tileNode)
tileMap.addChild(tileNode)
}
}
}
}
Cependant, si j'utilise ceci, j'ai un corps physique par tuile. Je veux connecter des corps physiques à des corps plus grands pour obtenir de meilleures performances. Je sais que ça peut être avec init(bodies: [SKPhysicsBody])
. Mais comment faire ça?
Comment puis-je savoir quel corps est à côté d'un autre corps pour les regrouper?
Les corps physiques dans le tileMap ne sont pas tous les suivantsles uns aux autres. Certains sont de gros blocs de corps physiques, certains sont des corps physiques uniques sans corps à côté d'eux. Je ne peux donc pas simplement mettre chaque corps physique dans un tableau et les regrouper.
Voici une image qui montre à quoi elle ressemble en ce moment.
J'espère que l'explication est suffisamment claire. Sinon, je vais essayer de mieux l'expliquer.
Quelqu'un a-t-il déjà fait cela et peut-il m'orienter dans la bonne direction? J'apprécierais toute aide.
ÉDITER: Avant d'essayer ceci:
static var bodies = [SKPhysicsBody]()
static func addPhysicsBody(to tileMap: SKTileMapNode, and tileInfo: String){
let tileSize = tileMap.tileSize
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2 * tileSize.width
let halfHeight = CGFloat(tileMap.numberOfRows) / 2 * tileSize.height
for column in 0..<tileMap.numberOfColumns{
for row in 0..<tileMap.numberOfRows{
let tileDefinition = tileMap.tileDefinition(atColumn: column, row: row)
let isCorrectTile = tileDefinition?.userData?[tileInfo] as? Bool
if isCorrectTile ?? false && tileInfo == "wall"{
let x = CGFloat(column) * tileSize.width - halfWidth
let y = CGFloat(row) * tileSize.height - halfHeight
let tileNode = SKNode()
tileNode.position = CGPoint(x: x, y: y)
tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2, y: tileSize.height / 2))
tileNode.physicsBody!.isDynamic = false
tileNode.physicsBody!.restitution = 0.0
tileNode.physicsBody!.categoryBitMask = Constants.PhysicsCategories.wall
tileNode.physicsBody!.collisionBitMask = Constants.PhysicsCategories.player | Constants.PhysicsCategories.npc | Constants.PhysicsCategories.enemy
//nodesForGraph.append(tileNode)
bodies.append(tileNode.physicsBody!)
tileMap.addChild(tileNode)
}
}
}
tileMap.physicsBody = SKPhysicsBody(bodies: bodies)
}
Mais quand je fais ça, les corps physiques sont totalement foirés ..
Réponses:
0 pour la réponse № 1Comme l'a souligné Knight0fDragon, il n'y a aucun moyen defaites exactement ce que vous avez demandé. Malheureusement, les cartes de tuiles dans SpriteKit laissent beaucoup à désirer. Mais vous pourriez essayer cette technique pour réduire le nombre de corps physiques.
Idée n ° 1 - Dessinez manuellement vos corps physiques
Créez votre carte de tuiles dans l'éditeur. Peignez simplement vos textures de tuile sur la carte; ne leur attribuez aucun corps physique. Continuez à travailler dans l'éditeur pour faire glisser Color Sprites (SKSpriteNodes
) sur des parties de votre carte qui nécessitent un corps physique. Formez les nœuds pour créer le plus grand rectangle possible pour les zones qui nécessitent des corps physiques. Cela fonctionne mieux pour les grandes surfaces planes comme les murs, les planchers, les plafonds, les plates-formes, les caisses, etc. Faire.
Idée n ° 2 - N'utiliser aucun corps physique
Cette idée nécessiterait probablement encore plus de travail,mais vous pourriez potentiellement éviter complètement d'utiliser des corps physiques. Tout d'abord, créez votre carte de tuiles dans l'éditeur. Analysez votre carte pour identifier quelles tuiles marquent une barrière, au-delà de laquelle le joueur ne doit pas traverser. Attribuez un identifiant de données utilisateur à ce type de mosaïque. Vous auriez besoin de différentes catégories d'identifiants pour différents types de barrières, et vous devrez peut-être également concevoir votre œuvre d'art pour l'adapter à cette approche.
Une fois que vos tuiles barrières sont suffisammentidentifié, écrivez un code qui vérifie la valeur des données utilisateur pour la tuile actuellement occupée par l'image-objet du joueur et restreignez le mouvement de l'image-objet en conséquence. Par exemple, si le joueur entre un titre qui marque une limite supérieure, votre code de mouvement ne permettrait pas De même, si le joueur entre dans une tuile qui marque la limite la plus à gauche, votre code de mouvement ne permettra pas au joueur de voyager à gauche.
Vous pouvez vérifier ce post connexe où je propose essentiellement les mêmes idées. Malheureusement, les cartes de tuiles de SpriteKit n'ont pas de solution parfaite à ce problème.