Reputation: 443
I am making an iOS game(swift xcode).
there is a car that moves constantly(SKAction) and a player which you can move with swipe gestures.
All good, but now I want that if the player touches the car, it will move the same with the car(it gets sticked to the car)
Now how do I do this?
I tried many things but none of them worked Smoothly..
I tried to use
if (CGRectIntersectsRect(car.frame, player.frame)) {
car.position = player.position
}
this works, but the player gets kicked to the middle of the car, I do not want this. What I want is that if the player touches the bottom of the car, it gets sticked to the bottom of the car.
How do I do that??
for the collision detecion I also tried to use:
func didBeginContact(contact: SKPhysicsContact!) {
var firstBody:SKPhysicsBody
var secondBody:SKPhysicsBody
if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask){
firstBody = contact.bodyA
secondBody = contact.bodyB
}else{
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if((firstBody.categoryBitMask & CarCategory) != 0 && (secondBody.categoryBitMask & playerCategory) != 0)
{
}
}
But I Do not know what to put between the brackets to make it function smoothly like I want.
Upvotes: 3
Views: 1172
Reputation: 12773
You can connect the two nodes with a fixed physics joint. Physics joints, in general, connect two physics bodies that are in the scene. The fixed version, SKPhysicsJointFixed
, joins two bodies such that they act as a single body.
Here's an example of how connects two physics bodies with a fixed joint:
First, add this to your SKScene
subclass (e.g., GameScene.m)
func joinPhysicsBodies(bodyA:SKPhysicsBody, bodyB:SKPhysicsBody, point:CGPoint) {
let joint = SKPhysicsJointFixed.jointWithBodyA(bodyA, bodyB: bodyB, anchor: point)
self.physicsWorld.addJoint(joint)
}
and add this in the if
statement in didBeginContact
self.joinPhysicsBodies(firstBody, bodyB:secondBody, point:contact.contactPoint)
where contact.contactPoint
is the point of the contact.
Upvotes: 3
Reputation: 673
There are two ways to do this.
You can use joints, as detailed here How to create joints in Sprite Kit (Xcode)?
Or you can just remove the player node from the world and add it as a child of the vehicle node, in which case the vehicle node and player node will be linked and will move together. Do this with removeChildWithName()
and addChild()
.
Upvotes: 0
Reputation:
A simpler way to do this without physics is to use constraints:
if (CGRectIntersectsRect(car.frame, player.frame)) {
player.constraints=[SKConstraint.distance(SKRange(upperLimit: 100), toNode: car)]
}
This will ensure the player is at most 100 points away from the car (you can change this number to make it more realistic)
And when you want to detach the player:
player.constraints=[]
Upvotes: 2
Reputation: 5461
Implement the SKPhysicsContactDelegate protocol:
class GameScene: SKScene, SKPhysicsContactDelegate
Set the delegate at the end of didMoveToView
override func didMoveToView(view: SKView) {
...
self.physicsWorld.contactDelegate = self
}
Create global variables to store the collision categories:
let collisionCar: UInt32 = 0x1 << 0
let collisionPlayer: UInt32 = 0x1 << 1
Create a physics body for car and player:
car.physicsBody = SKPhysicsBody(rectangleOfSize: car.size)
car.physicsBody?.affectedByGravity = false
car.physicsBody?.dynamic = false
car.physicsBody?.categoryBitMask = collisionCar
car.physicsBody?.contactTestBitMask = collisionPlayer
car.physicsBody?.collisionBitMask = 0x0;
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody?.affectedByGravity = false
player.physicsBody?.dynamic = false
player.physicsBody?.categoryBitMask = collisionPlayer
player.physicsBody?.contactTestBitMask = collisionCar
player.physicsBody?.collisionBitMask = 0x0;
Implement didBeginContact:
func didBeginContact(contact: SKPhysicsContact) {
...
}
Upvotes: 0