Sprite Kit application hangs up - ios

Trying to make my first Swift app using the Sprite Kit.
The app has to create up to 5 objects that have to move across the screen randomly. The speed increases and size decreases every 5 seconds.
The scene setups correctly, objects appear and move but after some time the CPU usage becomes 100%, FPS falls to 0 and app hangs up. Sometimes it continues to work for some seconds, sometimes it doesn't.
What is the reason?
I'm just noob in Xcode - is it possible to find what block of code is working now during the simulation?
Here is the update function. I didn't include didMoveToView and touchesBegan part cause they seem not influencing the problem.
override func update(currentTime: CFTimeInterval) {
if (currentTime-oldTime)>1 {
if arrayofAims.isEmpty==false {
for currentAim in arrayofAims {
repeat {xvelocity=(Int(arc4random())%3 - 1) * aimSpeedX} while xvelocity == 0
repeat {yvelocity=(Int(arc4random())%3 - 1) * aimSpeedX} while yvelocity == 0
currentAim.physicsBody?.applyForce(CGVectorMake (CGFloat(xvelocity), CGFloat(yvelocity)))
}
}
oldTime=currentTime
timecount+=1
}
if timecount>5 {
if aimSpeedX < 5000 {
aimSpeedX+=200
}
if aimSizeRatioX > 0.3 {
aimSizeRatioX -= 0.05
aimSizeRatioY -= 0.05
}
timecount=0
if arrayofAims.count<6 { arrayofAims.append(createAnAim())
currentAim=arrayofAims[arrayofAims.count-1]
addChild(currentAim)
}
}
}

May by its some Sprite Kit collision model bug? A had
aim.physicsBody = SKPhysicsBody(texture: aim.texture!, size: aim.size)
aim.physicsBody?.categoryBitMask = aimCategory
aim.physicsBody?.collisionBitMask = aimCategory | boundCategory
I replaced it with
aim.physicsBody?.collisionBitMask = boundCategory
and freeze disappeared but objects don't interact with each others

Related

SKActions Doesn't works sometimes, but if minimise the game and reopen it, It Works. How that could happen?

I'm having problem with 2 actions both of the actions are move to actions, that moves the pieces to empty node's position(Empty sknodes are added from sks file for). The problem only happens some times not always, in first one when player reaches loc:25 means wins it moves to empty node's position but it some times doesn't moves to there but the game goes on and if I minimise the game and open it they are already there where they should have moved previously.
Second problem this one is more important because with this skaction player moves to next Position. But very few times it doesn't works everything works fine but when it comes to execute that skaction it Stops totally, only touches works. but if I just minimise the game and open it, it moves to position and then game works fine. No issue then, How can this Happen?
I run the second skaction with sequence with 2 other actions and first one with skspritenode.run() action. and I don't have iOS device so I'm testing it on simulator.
Here are the both of SKActions that I use just the same thing nothing new :
for node in children {
if (node.name == String(nextSpace)) {
let moveAction:SKAction = SKAction.move(to: node.position, duration: 0.5)
moveAction.timingMode = .easeOut
let wait:SKAction = SKAction.wait(forDuration: 0.1)
let runAction:SKAction = SKAction.run({
if (self.movesRemaining == 1) {
self.KillHim(self.whosTurn, nextspace: nextSpace)
}
self.movesRemaining = self.movesRemaining - 1
self.setThePlayerSpace(space: nextSpace, player:self.whosTurn)
self.movePiece()
})
if whosTurn == .Player1 {
touchedNode.run(SKAction.sequence([moveAction, wait, runAction]))
} else {
playerPiece.run(SKAction.sequence([moveAction, wait, runAction]))
}
}
}
code for moving when player won :
if (currentSpacePlayer1Piece1 == 25) {
let loc:SKNode = childNode(withName: "c1")!
Player1Piece1.run(SKAction.move(to: loc.position, duration: 0.2))
currentSpacePlayer1Piece1 = 26
OneMoreMove += 1
} else if (currentSpacePlayer1Piece2 == 25) {
let loc:SKNode = childNode(withName: "c2")!
Player1Piece2.run(SKAction.move(to: loc.position, duration: 0.2))
currentSpacePlayer1Piece2 = 26
OneMoreMove += 1
}
is it could be happening because of using it in simulator?
As knightOfDragon said the node was being paused with some logic some times after removing, it works perfectly. If you have same issue search isPaused if you are using it somewhere not intended.

Cocos2d V3.4 Chipmunk RELEASE mode display bug

there seems to be a Cocos2dV3.4 display bug when adding lots of Chipmunk physics bodies quickly in the same spot in RELEASE MODE on a device. If the physics body is a rectangle its happens straight away, if it is a circle it takes longer but does happen. The key point is it always works fine in DEBUG mode but errors occur in RELEASE mode on the device. It always works fine in the simulator. (just Edit Scheme.. to change to release mode for RUN)
Example swift code to replicate. (simply add a dynamic polygon physics body at the same point quickly)
class MainTestScene: CCNode
{
var _rootPhysicsNode : CCPhysicsNode!
var count : CCTime = 0
override init()
{
super.init()
_rootPhysicsNode = CCPhysicsNode()
_rootPhysicsNode.gravity = ccp(0,-100)
self.addChild(_rootPhysicsNode)
}
override func update(delta: CCTime)
{
count += delta
if count > 0.2
{
count = 0
for var i = 0; i <= 10 ; i++
{
let item = CCSprite(imageNamed: "ccbResources/rainbowblinky.png")
item.anchorPoint = ccp(0.5,0.5)
item.scale = 0.3
item.position = ccp(CCDirector.sharedDirector().viewSize().width / 2, CCDirector.sharedDirector().viewSize().height / 2 )
item.physicsBody = CCPhysicsBody(rect: CGRectMake(0, 0, 100, 100), cornerRadius: 1)
_rootPhysicsNode.addChild(item)
}
}
}
}
In DEBUG mode you get sprites falling from a point and pushing each other out. (see picture) In RELEASE MODE on an iOS device the screen flicks every second shows a single sprite and slows down to a crawl.
Can someone help? Am I doing something wrong?
B

iOS Swift SpriteKit - how to detect time elapsed between user touches on sprites

I have set up a match-3 game, and I want to track the number of seconds a user takes to touch valid points (game piece sprites) on the game board:
(1) when a game level is loaded, if the user does not touch a sprite within 5 seconds, track this;
(2) while playing the game, if the time elapsed between the user touching a sprite is greater than 5 seconds, track this.
(I will use these results to provide a hint to the user).
I would like to use a NSTimer/NSTimeInterval for this, but not sure how to implement it.
I wouldn't suggest adding an integer as others suggested.
All you need is delta time. I'm assuming you have that part worked out, but I'll post it just in case
scene properties
// time values
var delta:NSTimeInterval = NSTimeInterval(0)
var last_update_time:NSTimeInterval = NSTimeInterval(0)
your scene's update method (also create an update method for your sprites, and pass delta into it here)
func update(currentTime: NSTimeInterval) {
if self.last_update_time == 0.0 {
self.delta = 0
} else {
self.delta = currentTime - self.last_update_time
}
self.yourSprite.update(self.delta)
your sprite's time properties
var timeSinceTouched = NSTimeInterval(0)
let timeLimit = NSTimeInterval(5.0)
your sprites update / touched method
func touched(){
self.timeSinceTouched = 0.0
}
func update(delta: CFTimeInterval) {
if self.timeSinceTouched < self.timeLimit {
self.timeSinceTouched += delta
} else {
// five seconds has elapsed
}

accelerometer data not correct, delayed for few seconds

I am creating a very simple game using Swift and SpriteKit and I am moving a ball on the screen using the accelerometer data (acceleration x,y).
I would say the code works fine but I have noticed that sometimes (often right when I open the app) the accelerometer data is not correct and delayed for few seconds.
Why is that happening?
I am using the following code to read the accelerometer data:
if motionManager.accelerometerAvailable == true {
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler:{
data, error in
self.accX = CGFloat(data.acceleration.x)
self.accY = CGFloat(data.acceleration.y)
})
}
And the function update to apply some impulse to the ball:
override func update(currentTime: CFTimeInterval) {
var impulse = CGVectorMake(accX, accY)
var obj = childNodeWithName("ball") as SKSpriteNode
obj.physicsBody?.applyImpulse(impulse)
}
Am i missing something?
Thank you
With any accelerometer data, it is a good idea to run it through a filter to smooth out any irregular spikes. Here is my favorite:
double filteredAcceleration[3];
memset(filteredAcceleration, 0, sizeof(filteredAcceleration));
CMAccelerometerData *newestAccel = motionManager.accelerometerData;
filteredAcceleration[0] = (filteredAcceleration[0]*(1.0-alpha)) + (newestAccel.acceleration.x*alpha);
filteredAcceleration[1] = (filteredAcceleration[1]*(1.0-alpha)) + (newestAccel.acceleration.y*alpha);
filteredAcceleration[2] = (filteredAcceleration[2]*(1.0-alpha)) + (newestAccel.acceleration.z*alpha);
alpha can be any value from 0 to 1. The closer to 1 the more responsive it will be, the closer to zero the more smooth it will be. My favorite value on the iPhone is 0.2 It is a good compromise for smooth yet responsive for a game like doodle jump, or possibly moving a ball around.
I don't know why the accelerometer data is incorrect/delayed on startup, my guess would be that the hardware has to wake up and calibrate itself, but regardless of the why, if you implement a filter, it will smooth out these irregularities, and they won't be nearly as noticeable.
I have given priority to both functions and the issue seems fixed.
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_async(dispatch_get_main_queue()) {
// code with priority
}
}

Any way to speed up gameplay gradually in Swift?

I'm currently working on a game using Spritekit. The game has objects which spawn at the top of the screen and fall towards the player character, and the game ends when the player character collides with any of the objects. I am trying to find a way to gradually speed up gameplay over time to make the game more difficult (i.e. objects fall at normal speed when the game begins, after 5 seconds speed up 50%, after 5 more seconds speed up another 50%, ad infinitum.)
Would I need to use NSTimer to make a countdown to increase the gravity applied to the falling objects? Sorry if this is a basic thing, I'm kind of new to programming.
Thanks, Jake
EDIT:
My spawn method for enemies-
let spawn = SKAction.runBlock({() in self.spawnEnemy()})
let delay = SKAction.waitForDuration(NSTimeInterval(2.0))
let spawnThenDelay = SKAction.sequence([spawn, delay])
let spawnThenDelayForever = SKAction.repeatActionForever(spawnThenDelay)
self.runAction(spawnThenDelayForever)
And my method for making the enemies fall-
func spawnEnemy() {
let enemy = SKNode()
let x = arc4random()
fallSprite.physicsBody = SKPhysicsBody(rectangleOfSize: fallSprite.size)
fallSprite.physicsBody.dynamic = true
self.physicsWorld.gravity = CGVectorMake(0.0, -0.50)
enemy.addChild(fallSprite)
}
In spawnEnemy(), you set self.physicsWorld.gravity. Move this line to your update: method.
If you are not keeping track of the game's duration right now, you will want to implement that. You can use the parameter of the update: method to accomplish this.
You can then use the game duration to change the gravity.
For example,
override func update(currentTime: CFTimeInterval) {
if gameState == Playing{
//update "duration" using "currentTime"
self.physicsWorld.physicsBody = CGVectorMake(0.0, -0.50 * (duration / 10.0))
}
}
10.0 can be changed depending on how fast you want the gravity to increase. A higher number makes it change less drastically, and a smaller number makes the gravity increase quite rapidly.
Hopefully this answers your question.

Resources