How to get correct frame of `Skeleton`
W3xly opened this issue · 8 comments
Hello, first of all I want to thank you for trying to keep this library up to date.
Has anyone tried to solve the missing frame of a Skeleton
character? I also tried calculateAccumulatedFrame()
but it return values that make no sense (for Golbin it's it's more width than height)
And the second question that is related to this, has anyone tried to set the correct physicsBody
for a character so that it corresponds to its actual size.
Everything can be solved through some magic number, but I don't like this solution very much..
Thanks a lot for answer!
Has anyone tried to solve the missing frame of a
Skeleton
character? I also triedcalculateAccumulatedFrame()
but it return values that make no sense (for Golbin it's it's more width than height)
Yes, I see the problem:
![drawing](https://private-user-images.githubusercontent.com/6514571/303995688-f0784c34-63d4-4bae-9fc7-2899cb2ee6c6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTkwMzgzNDAsIm5iZiI6MTcxOTAzODA0MCwicGF0aCI6Ii82NTE0NTcxLzMwMzk5NTY4OC1mMDc4NGMzNC02M2Q0LTRiYWUtOWZjNy0yODk5Y2IyZWU2YzYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA2MjJUMDYzNDAwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OWI2MDRjMGNmMjdiNTFiMDg3NjQxODdlMzBjYjg5YjVkMTg5OTAzNDk0ZDliM2IxODk5YThkZmM1NTcxMGFhMiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.6gacUUZp8bWurzf07bteQZZeBF6tY-6nG2rbmuqaDv4)
class GameScene: SKScene {
override func didMove(to view: SKView) {
do {
let character = try Skeleton(json: "goblins-ess", folder: "goblins", skin: "goblin")
character.name = "character"
character.position = CGPoint(x: self.size.width / 2, y: (self.size.height / 2) - 200)
addChild(character)
for child in character["//*"] {
let frameOrigin = convert(child.frame.origin, from: child)
let outline = SKShapeNode(rect: CGRect(origin: frameOrigin, size: child.frame.size))
outline.strokeColor = .red
addChild(outline)
}
let outline = SKShapeNode(rect: character.calculateAccumulatedFrame())
outline.strokeColor = .green
addChild(outline)
} catch {
print(error)
}
}
}
This is because of all transitions, rotations and scale changes of child nodes performed by SKAction, and there is no actual frame change:
class GameScene: SKScene {
override func didMove(to view: SKView) {
let atlas = SKTextureAtlas(named: "goblins/default")
let texture = atlas.textureNamed("shield")
let shield = SKSpriteNode(texture: texture)
shield.size = CGSize(width: 100, height: 100)
shield.position = CGPoint(x: size.width / 2, y: size.height / 2)
addChild(shield)
let moveAction = SKAction.move(by: .init(dx: 50, dy: 50), duration: 0)
shield.run(moveAction)
let outline = SKShapeNode(rect: shield.frame)
outline.strokeColor = .green
addChild(outline)
}
}
Thanks a lot for such a fast answer, I understood the rotation offset, it shouldn't be a big problem.
Thank you especially for this character["//*"]
, I did not know that I could access individual atlases this way. I was hoping to be able to pass these SKShapeNode
outlines that u created as bodies
to Characters physicsBody
. But so far no luck.
I am sorry for possibly stupid questions, this is one of my first experiences with SpriteKit..
And the second question that is related to this, has anyone tried to set the correct
physicsBody
for a character so that it corresponds to its actual size.
physicsBody
adjust it's position on transition, rotation and scale changes with SKAction:
class GameScene: SKScene {
override func didMove(to view: SKView) {
let atlas = SKTextureAtlas(named: "goblins/default")
let texture = atlas.textureNamed("shield")
let shield = SKSpriteNode(texture: texture)
shield.size = CGSize(width: 100, height: 100)
shield.position = CGPoint(x: size.width / 2, y: size.height / 2)
addChild(shield)
let physicsBody = SKPhysicsBody(circleOfRadius: 55)
physicsBody.isDynamic = false
physicsBody.affectedByGravity = false
shield.physicsBody = physicsBody
let moveAction = SKAction.move(by: .init(dx: 50, dy: 50), duration: 0)
let scaleAction = SKAction.scale(to: 1.5, duration: 0)
shield.run(SKAction.group([moveAction, scaleAction]))
let outline = SKShapeNode(rect: shield.frame)
outline.strokeColor = .green
addChild(outline)
}
}
so u basically can attach physicsBody
to any Slot
of the Skeleton
you need (or to the all of them):
![drawing](https://private-user-images.githubusercontent.com/6514571/304014243-4f338e73-d021-48c9-a83f-9b50c0776a1a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTkwMzgzNDAsIm5iZiI6MTcxOTAzODA0MCwicGF0aCI6Ii82NTE0NTcxLzMwNDAxNDI0My00ZjMzOGU3My1kMDIxLTQ4YzktYTgzZi05YjUwYzA3NzZhMWEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA2MjJUMDYzNDAwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YzYyODZjZTRmYWIxMWI4NmY3OGJlNTgxYzc4ODBiM2U0YjkzOWJjOTEzNjNkNDBjOGFmNGUwODFkOWFhZDg1OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.WmFpDHuj3i-KqdWH27JcaAnChmwBAPQdFc3FKz7kqgg)
class GameScene: SKScene {
override func didMove(to view: SKView) {
do {
let character = try Skeleton(json: "goblins-ess", folder: "goblins", skin: "goblin")
character.name = "character"
character.position = CGPoint(x: self.size.width / 2, y: (self.size.height / 2) - 200)
addChild(character)
let torso = character.slotNode(named: "torso")
let physicsBody = SKPhysicsBody(rectangleOf: .init(width: 100, height: 50), center: .init(x: 30, y: 0))
physicsBody.isDynamic = false
physicsBody.affectedByGravity = false
torso?.physicsBody = physicsBody
}
}
Thanks a lot for such a fast answer, I understood the rotation offset, it shouldn't be a big problem.
Thank you especially for this
character["//*"]
, I did not know that I could access individual atlases this way. I was hoping to be able to pass theseSKShapeNode
outlines that u created asbodies
to CharactersphysicsBody
. But so far no luck.I am sorry for possibly stupid questions, this is one of my first experiences with SpriteKit..
This is not a stupid question. But as I can see, there is no easy way to adjust SKNode'a frame after it was moved, scaled or rotated with SKAction (if it even possible). So, looks like you have to forget about Skeleton's frame and work with it's individual slots (I showed how you can it do earlier).
Thank you especially for this
character["//*"]
, I did not know that I could access individual atlases this way.
https://developer.apple.com/documentation/spritekit/sknode/searching_the_node_tree
I understand where you're going with that, but I don't think it's possible to give a physical body in individual slots.. At the moment when I give the physical body into individual slots and simulate gravity, my whole skeleton falls apart. 😁 I'm sorry for the late answer and thank you for all your responses..
At the moment when I give the physical body into individual slots and simulate gravity
Of course, if you need to simulate gravity this is not working solution. It looks like create physical body with manually calculated dimensions and attached it o Skeleton node - this is the best choice for now, until we are figure out how to calculate correct frame automatically.