Reputation: 1155
I'm building a platform game that has an SKSpriteNode character who jumps onto moving platforms.
When the platform moves the character doesn't and it ends up falling off the platform. If I tap the move button the character moves along nicely, but I want the character to 'stick' to the platform as it moves.
I haven't posted code as the code is working as expected. I have a feeling its a property that I can set?
EDIT:
I have a solution - just not sure it's how people should do it so I'll post below and wait for feedback. It's long and complex and probably doesn't need to be.
When the user presses the left or right directional button I move the scene from GameScene.swift by:
func moveGround(direction: String) {
if direction == "left" {
[snip...]
// move the platforms
self.enumerateChildNodesWithName("platform") {
node, stop in
if let foundNode = node as? PlatformSprite {
node.position.x += Helper().kMovingDistance
}
}
// move all other nodes
self.enumerateChildNodesWithName("*") {
node, stop in
if let foundNode = node as? SKSpriteNode {
node.position.x += Helper().kMovingDistance
}
}
[snip...]
} else if direction == "right" {
[snip...]
// move the platforms
self.enumerateChildNodesWithName("platform") {
node, stop in
if let foundNode = node as? PlatformSprite {
node.position.x -= Helper().kMovingDistance
}
}
// move all other nodes
self.enumerateChildNodesWithName("*") {
node, stop in
if let foundNode = node as? SKSpriteNode {
node.position.x -= Helper().kMovingDistance
}
}
[snip...]
}
This moves the scene along nicely. Then when the character lands on top of a platform I initiate the platform movements using SKAction sequence AND initiate the scene movements by sending the reverse sequence to GameScene:
func startMoving() {
if !self.isMoving {
[snip...]
// get the platform actions and initiate the movements
let actions = self.getMovements()
let seq:SKAction = SKAction.sequence(actions)
// move the platform
self.runAction(seq, completion: { () -> Void in
self.completedPlatformActions()
})
// get the reverse actions and initiate then on the scene / ground
let reverseActions = self.getReverseMovements()
let reverseSeq:SKAction = SKAction.sequence(reverseActions)
delegate!.moveGroundWithPlatform(reverseSeq)
self.isMoving = true
}
}
Then I have a function for moving the ground with a platform and add a key to the runAction so I can stop just that action and not the platforms actions if the user ceases to be in contact with the platform:
func moveGroundWithPlatform(seq: SKAction) {
[snip...]
self.enumerateChildNodesWithName("platform") {
node, stop in
if let foundNode = node as? PlatformSprite {
node.runAction(seq, withKey: "groundSeq")
}
}
[snip...]
}
Then I stop moving the scene, but let the remaining actions of the platform continue using:
func stopMovingGroundWithPlatform() {
[snip...]
self.enumerateChildNodesWithName("platform") {
node, stop in
if let foundNode = node as? PlatformSprite {
node.removeActionForKey("groundSeq")
}
}
[snip...]
}
Ugly I know - if others have suggestions about how better to do this I'd love to know :)
Upvotes: 1
Views: 930
Reputation: 12753
If you want friction to move your character along with the platform, you will need to move the platform with a force, impulse, or by settings its velocity. I suspect it's easier to control a platform by settings its velocity. You can do that in the update
method by
platform.physicsBody?.velocity = CGVectorMake(dx,dy)
where dx
and dy
control the platforms speed in the x and y directions, respectively. You should also set the friction property of the platform's physics body as well.
Upvotes: 1