Xcode Swift Game ( Issue with Collisions ) - ios

I'm trying to get a "Block" to collide with the "ground" instead of the block going through the ground and disappearing!
Here is my code for the block
hero = CSHero()
hero.position = CGPointMake(70, movingGround.position.y + movingGround.frame.size.height/2 + hero.frame.size.height/2)
hero.physicsBody = SKPhysicsBody(rectangleOfSize: hero.size)
hero.physicsBody?.dynamic = true
hero.physicsBody?.contactTestBitMask = heroCategory | groundCategory
hero.physicsBody?.collisionBitMask = heroCategory | groundCategory
addChild(hero)
Here is my Code for the Ground
let ground1 = SKSpriteNode(color: UIColor.blackColor(), size: CGSizeMake(view.frame.size.width, 15))
ground1.position = view.center
ground1.physicsBody = SKPhysicsBody(rectangleOfSize: ground1.size)
ground1.physicsBody!.dynamic = false
ground1.physicsBody!.contactTestBitMask = groundCategory | heroCategory
ground1.physicsBody!.collisionBitMask = groundCategory | heroCategory
addChild(ground1)
Every time I run it the block just disappears if I have dynamic set to true.
Any help?

You are forgetting a very important part of physicsBody collision logic: categoryBitMask. The categoryBitMask property is what tells the system what type of object it is. You are essentially telling the system what you want each object to collide with but you are forgetting to tell the system what types of objects they actually are.
For further clarification, contactTestBitMask is needed only if you actually want to be notified when two things collide but don't want their physics bodies to act off of each other. (Think of when Mario hits a coin. He doesn't bounce off of it, but you need to be notified of said collision when you update the coin count). collisionBitMask tells the system what bodies to actually physically collide with. But this property needs to be paired with categoryBitMask to actually work.
Right now, you have everything you need. Dynamic isn't needed. What you need to do is add these two lines of code:
ground1.physicsBody?.categoryBitMask = groundCategory
hero.physicsBody?.categoryBitMask = heroCategory
I hope this helps!

Related

Xcode Swift Position moving - Collisions

I have just added collisions and now my "hero" will go to where he is suppose to for a split of a second then teleport all the way to the left of the screen and I can only see about 1/8th of him!
Here for Image
Here is my code for adding collisions, this only happens when I set Dynamic to "true" if I set it to false he goes to where he is suppose to be and I can fully see him! But I need Dynamic to be set to true so he can run into the walls I have added to the collisions.
var heroCategory: UInt32 = 1
var wallCategory: UInt32 = 2
hero = CSHero()
hero.position = CGPointMake(70, movingGround.position.y + movingGround.frame.size.height/2 + hero.frame.size.height/2)
hero.physicsBody = SKPhysicsBody(rectangleOfSize: hero.size)
hero.physicsBody?.dynamic = true
hero.physicsBody?.allowsRotation = false
hero.physicsBody?.categoryBitMask = heroCategory
hero.physicsBody?.collisionBitMask = wallCategory
addChild(hero)
wallGenerator = CSWallGenerator(color: UIColor.clearColor(), size: view.frame.size)
wallGenerator.position = view.center
wallGenerator.physicsBody = SKPhysicsBody(rectangleOfSize: wallGenerator.size)
wallGenerator.physicsBody?.dynamic = false
wallGenerator.physicsBody?.categoryBitMask = wallCategory
wallGenerator.physicsBody?.collisionBitMask = heroCategory
How do I get it so he goes in the position I want him to be when I set Dynamic to true?
It looks like your wall is your entire view, how are you making your wall collision box? You may be kicking your hero outside your screen.

Swift edgeLoopForRect physics body not getting categoryBitMask correctly

I have a body with edgeLoopForRect and I'm giving it a categoryBitMask but when I'm debugging the object's categoryBitMask is different than what I assigned it...
self.physicsBody?.categoryBitMask = 1
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
when I'm debugging its showing up as 453453 not ``
You cannot assign physics bodies to self. you have to create a node first and then assign a category bit mask to its physics body.
IE:
let edge = SKNode()
edge.phisicsbody = SKPhisicsbody(edgeloopfromrect: frame)
edge.physicsbody!.restitution = 0
edge.physicsbody!.friction = 0
edge.physicsbody!.angularDamping = 1
edge.physicsbody!.dynamic = false
edge.physicsbody!.categotyBitMask = 2
edge.physicsbody!.collisionBitMask = 1 //The category bit mask of the object you want it to collide with I used 1 as example
addChild(edge)
Remember to follow the same procedure for the node that you want to collide with the edge and make the collision bit mask 2 if you follow this example.
Hope this helps mate.

How to make sprites respond to contact events but not collision events (SpriteKit)?

Is it possible to make sprites in Swift respond only to contact events, ignoring collision events? We set the dynamic property to false for one of the sprites, but it didn't trigger the didBeginContact method when another sprite contacted it.
In other words, we want to get notified in didBeginContact when another sprite contacts an object, but we don't want the sprite to experience physics (e.g., no bouncing or moving on collision).
Set collisionbitmask to 0 on both sprites. But set the contacttestbitmask to the opposite sprites categorybitmask
heres an example
heres the setup for my Power Up this is a physics body that doesnt exhibit physics behavior
self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
self.physicsBody!.categoryBitMask = CategoryPowerup
self.physicsBody!.contactTestBitMask = CategoryShip
self.physicsBody!.collisionBitMask = 0
self.physicsBody!.dynamic = false
heres the setup for my Ship that gets the powerup
let physicsBodyInset = CGRectInset(CGRectMake(0, 0, self.size.width, self.size.height), 2, 2)
self.physicsBody = SKPhysicsBody(rectangleOfSize: physicsBodyInset.size)
self.physicsBody!.restitution = 0
self.physicsBody!.categoryBitMask = CategoryShip

How to stop a sprite from bouncing off a specific surface

Hi I am making a endless scrolling game where the character basically avoids obstacles as they come and he can jump over them. I got everything to work pretty well but I see that the character texture will bounce slightly after hitting the ground. I want the sprite to stop immediately after touching down. I tried setting the .restitution property to 0 but i still see it bouncing. Here is the setup code for my stickman character and the edge physics category in question
stickman.physicsBody?.dynamic = true
stickman.physicsBody?.allowsRotation = false
stickman.physicsBody?.usesPreciseCollisionDetection = true
stickman.physicsBody?.categoryBitMask = PhysicsCategory.Stickman
stickman.physicsBody?.collisionBitMask = PhysicsCategory.Edge
stickman.physicsBody?.contactTestBitMask = PhysicsCategory.Obstacle | PhysicsCategory.Edge
stickman.physicsBody?.restitution = 0
self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
physicsBody = SKPhysicsBody(edgeLoopFromRect: playableRect)
physicsWorld.contactDelegate = self
physicsBody?.categoryBitMask = PhysicsCategory.Edge
Where playable rect is just the screen boundary for universal deployment purposes.
Has anyone run into this problem. I couldn't quite find the same issue in other posts.
Set the restitution of the physics body your sprite is running into to 0 as well. Both physics bodies in a physics collision need to have a restitution of 0 to result in no bounciness.

If Statement to stop character falling through ground

I'm making a platform and want to stop the character (a ball) from going through the ground.
Can I write an if statement similar to if (Ball.center.y == 463) Ball.center.y = 463;?
463 is the y position that the ground is in the game.
While that approach is certainly possible, typically you want to abstract away the details (such as the 463 y-position of the ground) so that your code is more robust. For example, if you changed the y-position of the ground, you would have to change the 463 value everywhere you use it!
But fundamentally, yes you would use an if statement somewhat like what you provided. One thing to note is that if the ground is at 463, your ball will be half-way through the ground (since you are looking at the y-position of the centre of the ball.
Moreso, you want a check that is not so absolute... what if the position of the ball somehow becomes lower than the ground? Say 462? What should the behavior be now?
Without getting into the physics and design of your program, you would at the very least want to change your statement to something like:
int ball_lower_bound = Ball.center.y - Ball.height/2;
int ground_bound = 463;
if (ball_lower_bound < ground_bound) {
ball_lower_bound = ground_bound;
}
Since you are using sprite kit you should use physics body to handle that.
This is in swift:
variables of your class:
let balCategory:UInt32 = 1 << 0
let groundCategory:UInt32 = 1 << 1
Then when you define your ball sprite:
ball.physicsBody.categoryBitMask = ballCategory
ball.physicsBody.collisionBitMask = groundCategory
ball.physicsBody.contactTestBitMask = groundCategory
Then when you define your ground sprite (hopefully you have a image for your ground, if not make a very thin transparent or have something just below the screens edge):
ground.physicsBody.categoryBitMask = groundCategory
ground.physicsBody.collisionBitMask = ballCategory
ground.physicsBody.contactTestBitMask = ballCategory
Hopefully you can translate it to objective C if you are using that.

Resources