Reputation: 791
I seem to have a poor understanding of something related to collision detections, actions or positions in SpriteKit
.
I have a player and bricks and when a player lands on any brick, he jumps of it and then all bricks move down for a certain distance. I have the player added as a child of the scene and the bricks as children of a node (SKNode
) containing them. When I want to change their y-position, I just use a moveBy
action on that node and the bricks do indeed move how I want them to.
The problem is, when they are moving or even when they stop, the player can't land on them anymore (collision between them and the player is not detected anymore), so the player just falls through them.
This is my code in GameScene.swift
:
func moveBricksDownFor(movedForY: CGFloat) {
let moveAction = SKAction.moveBy(CGVectorMake(0, -movedForY), duration: 1.0)
brickNode.runAction(moveAction)
for _ in 0...4 {addBrick(0.7)}
}
func playerCollidedWithBrick(brick: Brick) {
if player.position.y > brick.position.y {
player.physicsBody?.velocity.dy = player.maxVelocityY
}
if player.yChangedFor() > 70 {moveBricksDownFor(player.yChangedFor())}
}
Is it possible that physics body isn't attached to visual representations of the bricks or something like this?
Here is also the Player
class (the parts used in the above code):
let maxVelocityY: CGFloat = 900
var startPositionY: CGFloat!
init(position: CGPoint) {
let texture = SKTexture(imageNamed: "doodler.png")
super.init(texture: texture, color: UIColor.blackColor(), size: CGSizeMake(60, 60))
self.zPosition = Layer.player.rawValue
self.position = position
self.startPositionY = position.y
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.affectedByGravity = true
self.physicsBody?.allowsRotation = false
self.physicsBody?.dynamic = true
self.physicsBody?.categoryBitMask = PhysicsCategory.Player
self.physicsBody?.contactTestBitMask = PhysicsCategory.Brick
self.physicsBody?.collisionBitMask = PhysicsCategory.None
self.physicsBody?.usesPreciseCollisionDetection = true
}
func yChangedFor() -> CGFloat {
return (self.position.y - startPositionY)
}
I did google similar topics but didn't find any similar problems so I guess I am missing something fundamental here or am making a stupid mistake.
UPDATE (added the Brick
class and initialization of worldNode
(SKNode
)):
class Brick: SKSpriteNode {
init(position:CGPoint) {
let texture = SKTexture(imageNamed: "brick.png")
super.init(texture: texture, color: UIColor.clearColor(), size: CGSizeMake(70, 10))
self.position = position
self.zPosition = Layer.brick.rawValue
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody?.affectedByGravity = false
self.physicsBody?.allowsRotation = true
self.physicsBody?.dynamic = false
self.physicsBody?.categoryBitMask = PhysicsCategory.Brick
self.physicsBody?.contactTestBitMask = PhysicsCategory.Player
self.physicsBody?.collisionBitMask = PhysicsCategory.None
self.physicsBody?.usesPreciseCollisionDetection = true
}
}
Setting the brickNode
and adding bricks to it as its children:
func setupBrickNode() {
brickNode.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
brickNode.physicsBody?.affectedByGravity = false
}
func addBrick(minXPercantage: CGFloat) {
let randomX = random(min: size.width*0.25, max: size.width - 100)
let randomY = random(min: size.height*minXPercantage, max: size.height)
let brick = Brick(position: CGPointMake(randomX, randomY))
brickNode.addChild(brick)
}
func setupBricks() {
for _ in 0...10 {addBrick(0.25)}
}
Updated the part where I move the brickNode
(now with setting its velocity):
func moveBricks() {
brickNode.physicsBody?.velocity = CGVectorMake(0, -player.maxVelocityY/4)
let waitAction = SKAction.waitForDuration(1.0)
let setBrickNodeVelocityToZero = SKAction.runBlock({self.brickNode.physicsBody?.velocity = CGVectorMake(0, 0)})
runAction(SKAction.sequence([waitAction, setBrickNodeVelocityToZero]))
}
func playerCollidedWithBrick(brick: Brick) {
if player.position.y > brick.position.y {
player.physicsBody?.velocity.dy = player.maxVelocityY
moveBricks()
}
}
Upvotes: 1
Views: 312
Reputation: 112
Example code
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var world: SKNode!
var player: SKSpriteNode!
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
physicsWorld.gravity = CGVector(dx: 0, dy: -10)
// World
world = SKNode()
addChild(world)
// Player
player = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 50, height: 50))
player.position.x = size.width / 2
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody!.categoryBitMask = 2
player.physicsBody!.contactTestBitMask = 4
player.physicsBody!.collisionBitMask = 0
player.physicsBody!.mass = 1
player.physicsBody!.velocity = CGVector(dx: 0, dy: 2000)
player.physicsBody!.usesPreciseCollisionDetection = true
world.addChild(player)
// Bricks
for index in 0...50 {
// Player
let brick = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 100, height: 25))
brick.position = CGPoint(x: size.width / 2, y: 300 + CGFloat(index) * 200)
brick.zPosition = -1
brick.physicsBody = SKPhysicsBody(rectangleOfSize: brick.size)
brick.physicsBody!.categoryBitMask = 4
brick.physicsBody!.contactTestBitMask = 2
brick.physicsBody!.collisionBitMask = 0
brick.physicsBody!.dynamic = false
world.addChild(brick)
}
}
func didBeginContact(contact: SKPhysicsContact) {
// Is the player falling?
guard player.physicsBody!.velocity.dy <= 0 else {
return
}
player.physicsBody!.velocity = CGVector(dx: 0, dy: 1000)
}
override func didFinishUpdate() {
guard player.position.y > 200 else {
return
}
world.position.y = -player.position.y + 200
}
}
Upvotes: 1
Reputation: 112
Because particular brick position is always the same. You are moving it's parent not the brick itself.
let realBrickPosition = convertPoint(brick.position, toNode: self)
Upvotes: 0
Reputation: 35392
If you want to land to a dynamic involved object probably you must set this.
self.physicsBody!.restitution = 0
Also, it's not the best attitude using SKAction
's moveBy instead of correct motion by velocity or force vectors, this can be change your physics object values and you lost their directions.
Upvotes: 1