SKSpritenodes stop moving when given physics body - swift

When i give two nodes in my game a physics body, they stop doing what i want them to do. I have two bars at the bottom of the scene,one starts on the left, and the other is on the right, and they continuously go to meet at the middle then move back to there starting spot, like a floor opening up. Without a physics body, they do exactly this, but when i give them a physics body,when they both meet in the middle, they stop there and don't move back out.
Here are the bars:
bar.position = CGPoint(x:-self.size.width * 0.2, y:(self.size.height * 0.03));
bar.physicsBody = SKPhysicsBody(texture: text, size: text.size())
bar.physicsBody?.categoryBitMask = PhysicsCategory.bar
bar.physicsBody?.contactTestBitMask = PhysicsCategory.ball
bar.physicsBody?.collisionBitMask = PhysicsCategory.bar
self.addChild(bar)
bar1.position = CGPoint(x:self.size.width * 1.2, y:(self.size.height * 0.03));
bar1.physicsBody = SKPhysicsBody(texture: text, size: text.size())
bar1.physicsBody?.categoryBitMask = PhysicsCategory.bar
bar1.physicsBody?.contactTestBitMask = PhysicsCategory.ball
bar1.physicsBody?.collisionBitMask = PhysicsCategory.bar
self.addChild(bar1)
And this is how they move. This is in the update method:
if (bar.position.x == -self.size.width * 0.2)
{
let move = SKAction.moveToX(self.size.width * 0.012, duration: 1);
bar.runAction(move);
} else if (bar.position.x == self.size.width * 0.012) {
let move = SKAction.moveToX(-self.size.width * 0.2, duration: 1)
bar.runAction(move)
}
if (bar1.position.x == self.size.width * 1.2)
{
let move = SKAction.moveToX(self.size.width * 0.988, duration: 1);
bar1.runAction(move);
} else if (bar1.position.x == self.size.width * 0.988) {
let move = SKAction.moveToX(self.size.width * 1.2, duration: 1)
bar1.runAction(move)
}
What could be causing them to stick together at the middle when i give them a physics body.

Related

Problem with game area on the new form factor

For my studies, I have to create a game on iOS (like a space invaders). Actually, I'm stucked for the game area : I need that the bullet can be pulled from the maximum value of the x position no matter the form factor.
Indeed, my code works perfectly on the old form factor (as iPhone 8). However, on the new form factor (iPhone X, XS..), the planet can disappear of all the screen.
(I'm a beginner about Swift, so I know there is a lot of mistake in my code). But I think that the problem is from the fact that I divide by an int.
First picture : what I want (which works on iPhone 8)
Second one : My problem.
Thanks for you help (and sorry for my bad english, french people ahaha).
translate :
zone_de_jeu = game_area
largeur_jouable = width_playable
marge_largeur = width_margin
hauteur_jouable = height_playable
marge_hauteur = height_margin
enter code here
var zone_de_jeu: CGRect
override init(size: CGSize) {
let max_ratio_aspect: CGFloat = 16.0 / 9.0
let largeur_jouable = size.height / max_ratio_aspect
let marge_largeur = (size.width - largeur_jouable) / 2
let hauteur_jouable = size.width / max_ratio_aspect
let marge_hauteur = (size.height - hauteur_jouable) / 2
zone_de_jeu = CGRect(x: marge_largeur, y: marge_hauteur, width: largeur_jouable, height: hauteur_jouable)
super.init(size: size)
let initialisation_mouvement_planete = touch.location(in: self)
let mouvement_planete = touch.previousLocation(in: self)
let arrive_final_planete_x = initialisation_mouvement_planete.x - mouvement_planete.x
planete.position.x += arrive_final_planete_x
if planete.position.x > zone_de_jeu.maxX - planete.size.width / 6.5 {
planete.position.x = zone_de_jeu.maxX - planete.size.width / 6.5
}
if planete.position.x < zone_de_jeu.minX + planete.size.width / 6.5 {
planete.position.x = zone_de_jeu.minX + planete.size.width / 6.5
}
Should I modify, my divider by something more general ?

SKAction not executing

let bag = SKSpriteNode(imageNamed: "Content/bag")
holder.addChild(bag)
bag.name = "bag"
bag.zPosition = 5
bag.position = CGPoint(x: -3, y: (holder.size.height / 2) + (bag.size.height / 2) - 6)
bag.setScale(0.5)
print(bag.parent)
bag.runAction(SKAction.playSoundFileNamed("Content/wrap.wav", waitForCompletion: true))
bag.runAction(SKAction.scale(to: 1.0, duration: 1.0, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 0)) {
bag.physicsBody = SKPhysicsBody(rectangleOfSize: bag.size)
bag.physicsBody!.dynamic = false
bag.physicsBody!.categoryBitMask = CollisionTypes.Bag.rawValue
bag.physicsBody!.collisionBitMask = CollisionTypes.Ingredients.rawValue
}
print(bag.parent)
The above code gets executed whenever the user taps the "holder" which is just a sprite already on the scene. It should create a new "bag" sprite, add it to the holder, and scale it up from 0.5 to 1.0 after running a sound effect.
The problem is that neither the sound effect or the scale action are being run. I searched this problem and it seems like the case is that the node hasn't been added but that's not the case here. I print the bag's parent before and after the actions and neither is nil. Also, the bag IS being added because I see it on the screen at 0.5 scale. How are neither of these actions being ran?

table top gaming: how make character walk from one house to another, passing through every house in between?

I just start to learn coding with Swift last month. This is my second personal project.
I'm creating a table top game like "Monopoly" or something. Here an image of my prototype:my table top board game
I'm using a arc4random for the dices and moving the character/player with this code:
if positionPlayer1 == 1 {
let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 1 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
player1.runAction(SKAction.moveByX(-66, y: 0, duration: 1))
}
} else if positionPlayer1 == 2 {
let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 1 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
player1.runAction(SKAction.moveByX(-44, y: 0, duration: 1))
}
I also tried :
player1.runAction(SKAction.moveByX(-66, y: 0, duration: 1))
sleep(1)
The problem is: the character waits the total time e runs directly to the final position. Let's say the dice give an 6, the character waits for 6 seconds and runs to the last position. This is not a problem on a straight line, but if the movement pass through a corner, the character cuts in diagonal directly to the final position instead of pass through every house as intended.
Any help will be appreciated.
Edit: I decided to try physics. I created a lot of SKSpriteNode "walls". To all nodes I'm using:
squareBlock02.physicsBody?.allowsRotation = false
squareBlock02.physicsBody?.pinned = true
squareBlock02.physicsBody?.dynamic = false
The result is that the player hits those walls and move them. I tried mass, density... nothing prevents the player from push all walls from its way.
Thank you all people that try to help.
I finally found the answer at this site: http://www.gamefromscratch.com/post/2014/07/02/Game-development-tutorial-Swift-and-SpriteKit-Part-4-Actions.aspx
import SpriteKit
// Solution found: http://www.gamefromscratch.com/post/2014/07/02/Game-development-tutorial-Swift-and-SpriteKit-Part-4-Actions.aspx
class GameScene: SKScene {
let player = SKSpriteNode(imageNamed: "Player_01-2.png")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
player.anchorPoint = CGPoint(x:0.5,y:0.5)
player.position = CGPoint(x:view.bounds.midX,y:view.bounds.midY)
self.addChild(player)
doStuff()
}
func doStuff(){
var actions = Array<SKAction>()
actions.append(SKAction.moveTo(CGPoint(x:300,y:300), duration: 1))
actions.append(SKAction.rotateByAngle(6.28, duration: 1))
actions.append(SKAction.moveBy(CGVector(dx: 150,dy: 0), duration: 1))
actions.append(SKAction.colorizeWithColor(SKColor.redColor(), colorBlendFactor: 0.5, duration: 1))
let sequence = SKAction.sequence(actions)
player.runAction(sequence)
}
}

Does Sprite Kit SKAction with time duration Slow Function Execution?

I have a function in my Sprite kit game where the game character dies and has a death animation. In this same method I set some attributes to let my update function know that the game is over so that the score can stop being incremented and some other things. But when this runs, the deathAnimation function seems to slow down the execution of the other variables that are being set. So the score keeps being incremented when it should stop for example. Why is this? is it something to do with my update function or does the animation with a time duration slow the entire method from being executed right away?
Thanks for the help in advance!
Here is my deathAnimation method
func deathAnimation() {
//set shield for death
self.yourDead = true
self.shield.position = CGPointMake(self.frame.maxX * 2, self.frame.maxY + self.ape.size.height * 10)
self.shield.hidden = true
self.shieldActivated = false
//set Ape image to default
self.ape.runAction(SKAction.setTexture(SKTexture(imageNamed: "Ape"), resize: true))
self.ape.zRotation = 0
//changes physicsBody values so He doesn't collide
self.ape.physicsBody?.dynamic = false
self.ape.physicsBody?.categoryBitMask = ColliderType.Asteroid.rawValue
self.ape.physicsBody?.contactTestBitMask = ColliderType.Ape.rawValue
self.ape.physicsBody?.collisionBitMask = ColliderType.Ape.rawValue
self.ape.zPosition = 10 //bring the ape to the front
let death = SKAction.sequence([
SKAction.group([
SKAction.scaleBy(4, duration: 0.5),
SKAction.moveTo(CGPointMake(self.frame.minX + ape.size.width * 2, self.frame.minY - ape.size.width * 2), duration: 2),
SKAction.repeatAction(SKAction.rotateByAngle(CGFloat(M_PI_4), duration: 0.2), count: 8)
]),
SKAction.runBlock({self.moveToGameOverView();})
])
ape.runAction(death) //run the animation sequence
}
Here is my code where I check if the player is Dead or not and this is within the update function. I didn't include all of the update function because it is probably more than you would care to look at.
//take Asteroids off the screen and increment score
enumerateChildNodesWithName("asteroid", usingBlock: {(node: SKNode!, stop: UnsafeMutablePointer <ObjCBool>) -> Void in
//move the asteroids off the screen
node.position = CGPointMake(node.position.x, node.position.y + self.gravity)
//if it is out of screen
if node.position.y > self.frame.size.height + self.largeAsteroid.size.width {
node.removeFromParent()
if !self.yourDead { //if your not dead
self.score++
self.scoreText.text = String(self.score)
//increase Asteroid speed
if self.score > 20 * self.tensCounter {
self.gravity++
self.tensCounter++
}
}
}
})
The code provided looks fine. However you could try checking a few things.
Make sure that you are not calling deathAnimation() over and over again.
Make sure you are not doing your enumerateChildNodesWithName before deathAnimation().
Make sure you aren't incrementing the score somewhere else.
Those are the only reasons I can think that your score would continue to go up after you set self.yourDead = true Hopefully that helps.

Why is my node slowing down when it collects a coin?

My game basically is a jumping game when you tap the screen the heroNode jumps and collects coins coming from the right part of the screen. When it collects the coin the hero node slows down and it goes out of the view. Why does this happen? Heres the code I have.
func coins() {
let moveToLeft = SKAction.moveByX(-self.size.width, y: 0, duration: 2.0)
let repeatMoveToLeft = SKAction.repeatActionForever(moveToLeft)
let removeFromScene = SKAction.removeFromParent()
let sequenceThisMoveAndRemove = SKAction.sequence([repeatMoveToLeft, removeFromScene])
goldCoins.position = CGPointMake(self.size.width / 0.6, self.size.height / 2)
goldCoins.zPosition = 15
goldCoins.setScale(0.9)
goldCoins.runAction(sequenceThisMoveAndRemove)
addChild(goldCoins)
goldCoins.physicsBody = SKPhysicsBody(circleOfRadius: 5)
goldCoins.physicsBody?.affectedByGravity = false
goldCoins.physicsBody?.allowsRotation = false
goldCoins.physicsBody?.categoryBitMask = GoldCoinCategory
goldCoins.physicsBody?.contactTestBitMask = HeroCategory
goldCoins.physicsBody?.collisionBitMask = 0
func addHero() {
let anim = SKAction.animateWithTextures([heroTextureOne, heroTextureTwo], timePerFrame: 0.2)
let run = SKAction.repeatActionForever(anim)
theHero = SKSpriteNode(texture: heroTextureOne)
theHero.runAction(run)
theHero.physicsBody = SKPhysicsBody(circleOfRadius: 50)
theHero.physicsBody?.affectedByGravity = true
theHero.physicsBody?.allowsRotation = false
theHero.physicsBody?.categoryBitMask = HeroCategory
theHero.setScale(0.5)
theHero.position = CGPointMake(self.size.width / 4.0, self.size.height / 2.0)
theHero.zPosition = 15
addChild(theHero)
}
if firstBody.categoryBitMask == HeroCategory && sixthBody.categoryBitMask == GoldCoinCategory {
sixthBody.node!.removeFromParent()
One possibility is that you're making a lot of gold coins that never get removed from the scene graph, and that's bogging down your performance.
Look at your first four lines of coins(). You create a forever-repeating action, and then create a sequence with the forever-repeating action and then the "remove from scene" action. A sequence performs the given actions in order, but a forever-repeating action will never end, so that "remove from scene" action will never be triggered.
So when you addChild( goldCoins ), those coins are never going to go away. And the only other way they can apparently be removed is with a collision. So if you play the game, and if a lot of goldCoins get added, then you're going to have an unbounded number of coins in play. After a while, having enough of those coins, all running actions, could cause your game to slow down.
Another possibility is that all you're removing is the sprite node and not the physics body from the simulation. This is suggested by that last line you included. If you remove the node, the coin will disappear, but the physics body will still be in play, still affecting other physics bodies. If you want to fully remove the coin - and its effect on the physics simulation - you'll need to remove its physics body, too.