How to resolve an unwanted collision in a complicated SpriteKit simulation? - ios

(If you want to cut to the chase go to the bold section).
I am having an unwanted collision in my simulation. My simulation has the following groups:
TeethTop (this is a group of objects)
TeethBottom (this is a group of objects)
Ball (the main object that is moved in the game)
Line (one line that is drawn occasionally only to detect if user swiped to a tooth)
Boundries (boundaries of screen)
Here are the rules I need
I need SKcontacts generated when
ball hits any teeth (top or bottom)
TeethTop hits any teeth
Line hits any teeth
As far as physical contacts and reactions (who can hit who and have physics simulated)
The line can not impede movement or hit the ball
The ball must land on the teeth but never move the teeth
No tooth must ever physically move due to physics
No tooth must ever react to a contact with another tooth
The ball needs to never pass through the boundaries
Ill throw in gravity
The ball is the only thing that reacts to gravity
Things that are dynamic (not in code)
The ball is dynamic because it reacts to gravity and hitting other teeth
Everything else stays put no matter what (however I had to tell the teeth that they were dynamic so I could have SKPhysicsContacts when the top hits the bottom)
Basically what happens is their are two rows of teeth, top and bottom. And they do their thing and become a stage. The walls are the same way. The ball moves around inside the mouth are like a platformer hitting and bounding off teeth.
On swipes a SKPhysicsNode line is created following the swipe and detecting which tooth the user swiped towards (**** MAYBE their is a better way then making a SKPhyiscsNode for the swipe line... I still need to detect if the user swiped in the direction of a tooth). And everything is dandy for awhile, then the mouth closes and stops when a tooth from the top hits a tooth from the bottom.
I had things all fine and dandy with things set as thus
BottomTeethGroup = 10
TopTeethGroup = 31
playergroup = 2
wallgroup = 1
lineleart = 99
Top Teeth
affectedbygravity = false
collisionbitmask = 0
categorybitmask = BottomTeethGroup
contacttTest = TopTeethGroup
dynamic = false
Bottom Teeth
affectedbygravity = false
collisionbitmask = 0
categorybitmask = TopTeethGroup
contacttTest = BottomTeethGroup
dynamic = false
Ball
affectedbygravity = false
the collision bit mask is never set so it collides with everything
categorybitmask = playergroup
contacttTest = playergroup
Dynamic = true
Boundaries
categorybitmask = wallgroup
dynamic = false
Line
collisionbitmask = 0
categorybitmask = lineleart
I have tried setting physics properties to crazy values but I just cant get the ball to pass through
The problem arises when I add the line. Everything with detection works fine until you add the line. Unfortunately the ball collides with the line creating a physical reaction which just isn't good! The ball should not physically collide with the line!
The way I see it their are some options:
Make is to the ball passes through the line, or ignores collisions between the two
Find a different way to detect which tooth the player swiped at (the current method is flawed anyway because the line will detect multiple teeth, just because it has a slope and doesn't stop once it hits the first). I have the coordinates of the start and end and the direction if someone has a better way.
Probably if we could make it so the top teeth and bottom teeth only have physical contact with ones from the other side then things would get easier.
Make it look like the ball is passing through the line
Edit: Perhaps my definitions of things are flawed so here is how I think contacts work:
collisionbitmask: will only collide with other objects that have the number you specify after it. If 0 then it collides with no objects, if not set then it collides with all
categorybitmask: defines what category is, if an object has a category test bit mask with this value then a SKPhysics contact will be created, however their might not necessarily be a physics reaction
contactTest: If it hits and the other object has the same categorybitmask as the one set here a SKphysics contact will be made
dynamic objects have physical reactions when they hit other dynamic objects, or non dynamic objects. SKPhysicsContacts are written up for all collisions
non dynamic objects will not move in any collision, and will only write up SKPhysicscontacts if the other object is static. Two non dynamic objects are not expected to collide.
List of solutions I have tried:
Lines collisionbitmask not set (same problem)
Cavities collisionbitmask set to 0 (falls through random teeth however it doesn't collide with the line but still generates a SKPhysicsContact)
All teeths' collision bit mask set to 4 (A BIIG MESS)
Top teeth collision bit mask set to 2 and bottom to 4 (less of a mess and when cavity hits a tooth it drifts like its in 0 g (it is in 0 g))
Edit:
I have been trying a bunch of things and none of them work. I got fed up and created a new project with four balls. Basically you set each ball to a specific group type and run the simulation. I have it so their are variables at the top for all the categories. If the simulation is set up right (I believe it is) the program WI simulate what would happen if all the values at the top are correct.
You can also find the code below
//
//  GameScene.swift
//  CollisionTesting
//
//  Created on 8/13/15.
//  Copyright (c) 2015 BroccoliPresentations. All rights reserved.
//
 
import SpriteKit
enum type
{
    case _toptooth
    case _bottomtooth
    case _ball
    case _line
    case _boundary
    case _none
}
class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        
        //The physics categories for each of them
        var topteethcategory:UInt32 = (0x01 << 1)
        var bottomteethcategory:UInt32 = (0x01 << 2)
        var ballcategory:UInt32 = (0x01 << 3)
        var boundriesgroup:UInt32 = (0x01 << 4)
        var linegroup:UInt32 = (0x01 << 5)
        
        //When collision reports should be written up
        var topteethcolisionreport:UInt32 = bottomteethcategory
        var bottomteethcollisionreport:UInt32 = topteethcategory
        var ballcollisionreport:UInt32 = bottomteethcategory | topteethcategory
        var boundriescollisionreport:UInt32 = 0
        var linecollisionreport:UInt32 = topteethcategory | bottomteethcategory
        
        //When they should bounce off of eachother
        var topteethphysics:UInt32 = bottomteethcategory
        var bottomteethphysics:UInt32 = topteethcategory
        var ballphysics:UInt32 = bottomteethcategory | topteethcategory | boundriesgroup
        var boundriesphysics:UInt32 = boundriesgroup
        var linecollisionphysics:UInt32 = linegroup
        
        
        //Here you can set what tope of object each color is
        var blue:type = type._toptooth
        var red:type = type._bottomtooth
        var yellow:type = type._ball
        var green:type = type._none
        
        
        var xy = CGRectGetMidX(self.frame) * 1.5
        var ball1 = SKSpriteNode(texture: SKTexture(imageNamed: "Blue"))
        ball1.position = CGPoint(x: xy, y:CGRectGetMidY(self.frame));
        ball1.size = CGSizeMake(100, 100)
        ball1.physicsBody?.affectedByGravity = false
        ball1.physicsBody = SKPhysicsBody(circleOfRadius: 50)
        ball1.physicsBody?.velocity = CGVector(dx: -100, dy: 0)
        
        var ball2 = SKSpriteNode(texture: SKTexture(imageNamed: "Red"))
        ball2.position = CGPoint(x:xy / 2, y:CGRectGetMidY(self.frame));
        ball2.size = CGSizeMake(100, 100)
        ball2.physicsBody?.affectedByGravity = false
        ball2.physicsBody = SKPhysicsBody(circleOfRadius: 50)
        ball2.physicsBody?.velocity = CGVector(dx: 100, dy: 0)
        
        var ball3 = SKSpriteNode(texture: SKTexture(imageNamed: "Yellow"))
        ball3.position = CGPoint(x:((xy / 4) + xy) / 2, y:CGRectGetMidY(self.frame) / 2);
        ball3.size = CGSizeMake(100, 100)
        ball3.physicsBody?.affectedByGravity = false
        ball3.physicsBody = SKPhysicsBody(circleOfRadius: 50)
        ball3.physicsBody?.velocity = CGVector(dx: 0, dy: 100)
        
        var ball4 = SKSpriteNode(texture: SKTexture(imageNamed: "Green"))
        ball4.position = CGPoint(x:((xy / 4) + xy) / 2, y:CGRectGetMidY(self.frame) * 1.5);
        ball4.size = CGSizeMake(100, 100)
        ball4.physicsBody?.affectedByGravity = false
        ball4.physicsBody = SKPhysicsBody(circleOfRadius: 50)
        ball4.physicsBody?.velocity = CGVector(dx: 0, dy: -100)
        self.addChild(ball1)
        self.addChild(ball2)
        self.addChild(ball3)
        self.addChild(ball4)
        
        
        switch (blue)
        {
        case type._toptooth:
                ball1.physicsBody?.categoryBitMask = topteethcategory
                ball1.physicsBody?.collisionBitMask = topteethphysics
                ball1.physicsBody?.contactTestBitMask = topteethcolisionreport
        case type._bottomtooth:
            ball1.physicsBody?.categoryBitMask = bottomteethcategory
            ball1.physicsBody?.collisionBitMask = bottomteethphysics
            ball1.physicsBody?.contactTestBitMask = bottomteethcollisionreport
        case type._ball:
            ball1.physicsBody?.categoryBitMask = ballcategory
            ball1.physicsBody?.collisionBitMask = ballphysics
            ball1.physicsBody?.contactTestBitMask = ballcollisionreport
        case type._boundary:
            ball1.physicsBody?.categoryBitMask = boundriesgroup
            ball1.physicsBody?.collisionBitMask = boundriesphysics
            ball1.physicsBody?.contactTestBitMask = boundriescollisionreport
        case type._line:
            ball1.physicsBody?.categoryBitMask = linegroup
            ball1.physicsBody?.collisionBitMask = linecollisionphysics
            ball1.physicsBody?.contactTestBitMask = linecollisionreport
        case type._none:
            ball1.position = CGPointMake(100000, 10000)
        }
        
        switch (red)
        {
        case type._toptooth:
            ball2.physicsBody?.categoryBitMask = topteethcategory
            ball2.physicsBody?.collisionBitMask = topteethphysics
            ball2.physicsBody?.contactTestBitMask = topteethcolisionreport
        case type._bottomtooth:
            ball2.physicsBody?.categoryBitMask = bottomteethcategory
            ball2.physicsBody?.collisionBitMask = bottomteethphysics
            ball2.physicsBody?.contactTestBitMask = bottomteethcollisionreport
        case type._ball:
            ball2.physicsBody?.categoryBitMask = ballcategory
            ball2.physicsBody?.collisionBitMask = ballphysics
            ball2.physicsBody?.contactTestBitMask = ballcollisionreport
        case type._boundary:
            ball2.physicsBody?.categoryBitMask = boundriesgroup
            ball2.physicsBody?.collisionBitMask = boundriesphysics
            ball2.physicsBody?.contactTestBitMask = boundriescollisionreport
        case type._line:
            ball2.physicsBody?.categoryBitMask = linegroup
            ball2.physicsBody?.collisionBitMask = linecollisionphysics
            ball2.physicsBody?.contactTestBitMask = linecollisionreport
        case type._none:
            ball2.position = CGPointMake(100000, 10000)
        }
        
        switch (blue)
        {
        case type._toptooth:
            ball3.physicsBody?.categoryBitMask = topteethcategory
            ball3.physicsBody?.collisionBitMask = topteethphysics
            ball3.physicsBody?.contactTestBitMask = topteethcolisionreport
        case type._bottomtooth:
            ball3.physicsBody?.categoryBitMask = bottomteethcategory
            ball3.physicsBody?.collisionBitMask = bottomteethphysics
            ball3.physicsBody?.contactTestBitMask = bottomteethcollisionreport
        case type._ball:
            ball3.physicsBody?.categoryBitMask = ballcategory
            ball3.physicsBody?.collisionBitMask = ballphysics
            ball3.physicsBody?.contactTestBitMask = ballcollisionreport
        case type._boundary:
            ball3.physicsBody?.categoryBitMask = boundriesgroup
            ball3.physicsBody?.collisionBitMask = boundriesphysics
            ball3.physicsBody?.contactTestBitMask = boundriescollisionreport
        case type._line:
            ball3.physicsBody?.categoryBitMask = linegroup
            ball3.physicsBody?.collisionBitMask = linecollisionphysics
            ball3.physicsBody?.contactTestBitMask = linecollisionreport
        case type._none:
            ball3.position = CGPointMake(100000, 10000)
        }
        
        switch (green)
        {
        case type._toptooth:
            ball4.physicsBody?.categoryBitMask = topteethcategory
            ball4.physicsBody?.collisionBitMask = topteethphysics
            ball4.physicsBody?.contactTestBitMask = topteethcolisionreport
        case type._bottomtooth:
            ball4.physicsBody?.categoryBitMask = bottomteethcategory
            ball4.physicsBody?.collisionBitMask = bottomteethphysics
            ball4.physicsBody?.contactTestBitMask = bottomteethcollisionreport
        case type._ball:
            ball4.physicsBody?.categoryBitMask = ballcategory
            ball4.physicsBody?.collisionBitMask = ballphysics
            ball4.physicsBody?.contactTestBitMask = ballcollisionreport
        case type._boundary:
            ball4.physicsBody?.categoryBitMask = boundriesgroup
            ball4.physicsBody?.collisionBitMask = boundriesphysics
            ball4.physicsBody?.contactTestBitMask = boundriescollisionreport
        case type._line:
            ball4.physicsBody?.categoryBitMask = linegroup
            ball4.physicsBody?.collisionBitMask = linecollisionphysics
            ball4.physicsBody?.contactTestBitMask = linecollisionreport
        case type._none:
            ball4.position = CGPointMake(100000, 10000)
        }
        
        
        
        physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    }
    
 
    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}
 
//nothing set they collide to eachother
//contactTestbitmask has nothing to do with bumping against eachother
//Category is the most important it gives it a type
//The other two decide when reactions happen, either physical or in code
//Collision bitmask is a list of groups that it actually should collide with
//Contacttestbitmask is list of groups that can trigger the code

I have figured it out! My problem is I was making things much too complicated. I actually didnt need all of these groups! Here is what I did!
var stage:UInt32 = (0x1 << 1)
var player:UInt32 = (0x1 << 2)
var sensors:UInt32 = (0x1 << 3)
//Physics collision bitmask
var p_stage:UInt32 = 0
var p_player:UInt32 = 0 | stage
var p_sensors:UInt32 = 0
//Test bitmask
var t_stage:UInt32 = stage
var t_player:UInt32 = stage
var t_sensors:UInt32 = stage
I actually didnt need as many groups as I thought I did! However I did have to store some data in the nodes name in order to tell wether it was from the top or bottom or which row, but overall it worked awesome!
Thank you guys who looked over everything, it really means a lot!
Something I found odd was that doing
(0x1 << 1)
(0x1 << 2)
(0x1 << 3)
was better then
1
2
3
I guess I really dont know what I am doing with the (0x1 << 1) thingy but I saw it somewhere else and copied it!

Related

Swift Spritekit - Only collide sprites when they are in certain positions?

Hi go easy on me as I'm still pretty new to swift. I'm creating a game in which your character (on the left of the screen) must swipe up or down to change lanes (4 lanes) or jump by tapping the right side of the screen, in order to dodge obstacles coming from the right side of the screen. This has presented the problem that when the character sprite is in one lane, some of it's pixels are in the lane above, so being in a different lane doesn't shield the character from collision. (This problem also exists for when the character jumps) Is there a way to program it so the character and obstacles only collide if they are in the same lane?
I've tried to make it so the .collisionBitMask and .categoryBitMask change depending on the position of either the obstacle or character but I can't figure out how to code it correctly. I'm pretty lost to be honest. Here is some code:
runningDoggo.physicsBody = SKPhysicsBody(texture: doggoTexture, size: runningDoggo.size)
runningDoggo.physicsBody?.affectedByGravity = false
runningDoggo.physicsBody?.isDynamic = true
runningDoggo.physicsBody?.collisionBitMask = 0x1 << 2
bush.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "8-bit bush"), size: bush.size)
bush.physicsBody?.isDynamic = true
bush.physicsBody?.affectedByGravity = false
bush.physicsBody?.categoryBitMask = 0x1 << 1
And then I have a set of switch cases in a function for randomly selecting which lane the bush comes in
switch randomLane{
case 1:
bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.07*UIScreen.main.bounds.height)
if(bush.position.y < runningDoggo.position.y) {
bush.zPosition = 6
}
self.addChild(bush)
case 2:
bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.18*UIScreen.main.bounds.height)
if(bush.position.y < runningDoggo.position.y) {
bush.zPosition = 6
}
self.addChild(bush)
case 3:
bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.29*UIScreen.main.bounds.height)
if(bush.position.y < runningDoggo.position.y) {
bush.zPosition = 6
}
self.addChild(bush)
case 4:
bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.4*UIScreen.main.bounds.height)
if(bush.position.y < runningDoggo.position.y) {
bush.zPosition = 6
}
self.addChild(bush)
default:
print("How is this not 1,2,3, or 4?")
}
bush.run(moveAndRemoveBush)
I want it to only collide (EDIT: Not to collide but to contact) the runningDoggo sprite with the bush sprite if they were in the same lane and pass by without colliding if the character isn't in the obstacle's lane.
Firstly, that complicated switch could be simplified to something like this (anytime you write the same code more than once, think if you can simplify it):
bush.position.x = 0.40 * UIScreen.main.bounds.width
bush.position.y = 0.07 * randomLane * UIScreen.main.bounds.height) // 0.07, 0.14, 0.21 or 0.28 for lanes 1-4
if (bush.position.y < runningDoggo.position.y) bush.zPosition = 6
self.addChild(bush)
bush.run(moveAndRemoveBush)
OK - I know that the y values of 0.07, 0.14, 0.21 and 0.28 don't match up with your values of 0.07, 0.18, 0.29 and 0.40 but maybe that's some thing you can tweek, or define an offset array as a property:
let bushYOffset = [0.07, 0.18, 0.29, 0.40]
and then just pick the offset corresponding to the lane
bush.position.x = 0.40 * UIScreen.main.bounds.width
bush.position.y = bushYOffset[randonLane-1] * UIScreen.main.bounds.height)
if (bush.position.y < runningDoggo.position.y) bush.zPosition = 6
self.addChild(bush)
bush.run(moveAndRemoveBush)
To address your main problem, you could create a bitmask for each lane in an array:
let laneMask: [UInt32] = [1<<1, 1<<2, 1<<3, 1<<4]
When Doggo moves to a new lane, give Doggo's physicsBody corresponding to collisonBitmask the lane it has just moved into:
runningDoggo.physicsBody?.collisionBitMask = laneMask[doggoLane - 1] // Arrays start at 0
When you spawn an obstacle, also give it the collision bitMask for the lane it is in:
bush.physicsBody?.collisionBitMask = laneMask[randomLane - 1] // Arrays start at 0
Now Doggo and the bush will only collide if they are in the same lane. If they are in different lanes they won't, even if some of their pixels overlap.
You may have to adjust this if there are other sprites on screen that doggo and the bush need to interact with.
NOTE:
Are you sure you want them to collide and not contact? Collisions occur when sprites collide and bounce off each other and fly around the screen; contacts are where 2 sprites touch and your code gets called and you can make one explode, or losee a life, or increase a score etc.
Edit: my step-by-step guide for collisions and contacts:
https://stackoverflow.com/a/51041474/1430420
And a guide to collision and contactTest bit masks:
https://stackoverflow.com/a/40596890/1430420
Manipulating bit masks to turn individual collision ans contacts off and on.
https://stackoverflow.com/a/46495864/1430420

SKSpriteNode slows down but shouldn't

I am trying to get my "word" to float across the screen; constant velocity, no impacts, no gravity, no friction. Everything works except the word slows down.
Code for creating word:
func createWordNode (word: String, atPos: CGPoint) -> SKSpriteNode {
let doneSize = CGSize(width: 50, height: 50)
let wordSprite = SKSpriteNode()
wordSprite.size = CGSize(width: doneSize.width * CGFloat(word.len()), height: doneSize.height)
wordSprite.position = atPos
wordSprite.blendMode = .replace
wordSprite.zPosition = zlvlBG + 1
let ltrs = Array(word.uppercased().characters)
for i in 0 ... ltrs.count - 1 {
let done = SKSpriteNode(imageNamed: "LetterTiles/Tile" + String(ltrs[i]) + ".png")
done.size = doneSize
done.position = CGPoint(x: doneSize.width * CGFloat(Double(i) - 1.5), y: 0)
done.blendMode = .replace
done.zPosition = zlvlBG + 1
wordSprite.addChild(done)
}
wordSprite.physicsBody?.restitution = 1
wordSprite.physicsBody?.friction = 0
wordSprite.physicsBody?.linearDamping = 0
wordSprite.physicsBody?.angularDamping = 0
wordSprite.physicsBody?.mass = 2000
wordSprite.physicsBody = SKPhysicsBody(rectangleOf: wordSprite.size)
wordSprite.physicsBody?.collisionBitMask = 0
wordSprite.physicsBody?.contactTestBitMask = 0
wordSprite.physicsBody?.categoryBitMask = categoryWords
wordSprite.physicsBody?.fieldBitMask = 0
wordSprite.physicsBody?.isDynamic = true
wordSprite.physicsBody?.affectedByGravity = false
wordSprite.physicsBody?.allowsRotation = false
var velocity = CGVector()
velocity.dx = 100
velocity.dy = 0
wordSprite.physicsBody?.velocity = velocity
wordSprite.physicsBody?.applyImpulse(velocity)
wordSprite.name = "Word:" + word
return wordSprite
}
I call function like:
addChild (createWordNode(word: "Done", atPos: CGPoint(x:-500, y:450)))
Any ideas why word slows down?
Thanks.
It looks like you are creating an object that doesn't need to be in the physics simulation. So you may want to reconsider simply dropping the physics related code and update the nodes position manually.
That being said if you wish this node to remain in the Physics simulation. You need to add the SKPhysicsBody to the SKSpriteNode before you start trying to modify properties. e.g.
wordSprite.physicsBody = SKPhysicsBody(rectangleOf: wordSprite.size)
wordSprite.physicsBody?.restitution = 1
wordSprite.physicsBody?.friction = 0
wordSprite.physicsBody?.linearDamping = 0
wordSprite.physicsBody?.angularDamping = 0
wordSprite.physicsBody?.mass = 2000
I worked with sprite a little bit. But, I am not an expert. Does it work for you to use an action instead of velocity as the following for example:
var moveRight = SKAction.moveTo(CGPointMake(400, 0), duration:2.0)
wordSprite.runAction(moveRight)
One thing to point out too. Why do you use applyImpulse. velocity should be enough. Did you try to remove it?

Have two of the same nodes on the screen at once Swift SpriteKit

I am creating a space shooter game. I have created an enemy node. What I want to do is have 4 of those nodes in each corner of the screen. In other words, I want to spawn multiple copies of the same node at the same time. When the game loads, I want there to be four nodes, that are all the same. How can I do this?
Thanks
Here's a section of code I use to generate a row of 4 space invaders. I reuse the same SKSpriteNode() variable as once the node has been added to the scene, the variable is no longer required:
for invaderPosition in 100.stride(to: 500, by: 120) {
invader = SKSpriteNode(texture: texturesA[0])
invader.position = CGPoint(x: CGFloat(invaderPosition), y: 200)
invader.xScale = 8
invader.yScale = 6
invader.color = SKColor.redColor()
invader.colorBlendFactor = 1.0
invader.name = "InvaderA"
invader.texture = texturesA[1]
invader.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(texturesA, timePerFrame: self.timePerMove)))
addChild(invader)
}
invader is defined as an SKSpriteNode property. texturesA is just an array of SKTextures; timePerMove is just a time interval after which the invader should move (in Update) and change shape(texture).
var invader = SKSpriteNode()
var texturesA:[SKTexture] = []
let timePerMove: CFTimeInterval = 1.0
So you could do something similar except the invader's positions would be the 4 corners rather than a row.
Just use the copy command,
let newNode = originalNode.copy() as! SKSpriteNode;

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.

The sprite kit nodes can't actually be removed from parent

I have made 30 bullets with a mutableArray to reuse them.
for var i = 0; i < 30; i++ {
var bulletTmp = SharedAtlas.getInstance().getSpriteNode(SKSpriteType.bullet)
bulletTmp.physicsBody = SKPhysicsBody(rectangleOfSize: bulletTmp.size)
bulletTmp.physicsBody.dynamic = true
bulletTmp.physicsBody.categoryBitMask = bulletCategory
bulletTmp.physicsBody.contactTestBitMask = enemyCategory
bulletTmp.physicsBody.collisionBitMask = enemyCategory
moveBulletToTop = SKAction.moveToY(self.frame.height, duration: NSTimeInterval((self.frame.height - plane.position.y) / 400.0))
bulletGroup.addObject(bulletTmp)
}
The bullets is their parent SKNode
bullets.runAction(SKAction.sequence([SKAction.waitForDuration(1.5), (SKAction.repeatActionForever(SKAction.sequence([SKAction.waitForDuration(0.05),SKAction.runBlock({
var newBullet:MGSpriteNode!
if self.bulletIndex < 29{
self.bulletIndex++
}else{
self.bulletIndex = 0
}
newBullet = self.bulletGroup.objectAtIndex(self.bulletIndex) as MGSpriteNode
newBullet.removeAllActions()
newBullet.removeFromParent()
print(self.childNodeWithName("bullets").children.count)//max value keeps 30
newBullet.runAction(self.moveBulletToTop)
newBullet.position = self.plane.position
newBullet.position.y += self.plane.size.height * 0.5
self.childNodeWithName("bullets").addChild(newBullet)
})])))]))
The question is: I have remove from parent after the bullet moves for a while. But the nodes number on the screen is keep increasing. The children of bullets always be 30 . If I move all of the bullets, everything will be OK. But where are the nodes? Had they actually been removed?

Resources