I'm new to swift, and I'm creating a random generated game using NSTimer i used this function for timer https://github.com/yuzixun/swift-timer/tree/master/example
my game was working fine until i got a problem with speeding up my game depending on the player score using timer, so i can't change the speed of my game
my Gamescene class :
let myGame = Timer.repeat(after: 1) {
//my generated game code here
}
myGame.start()
myGame : is a function that generate random object for my game every second using Timer.repeat(after:1).
let LevelUpdate = Timer.repeat(after: 0.1) {
//update my game and verify player score
if(self.score >= 1000 && self.score <= 2500){
// Speedup the time of the game
}
}
LevelUpdate : is a function that update some variable for my game and verify player score every 0.1 second.
My objectif : is to be able to change the timer of myGame if the player reached more then 1000 point and speedup myGame to 0.8 second, and my question is it possible to change time interval of myGame?
Please i need to find a way of speeding up my game by player score.
Ok, now we have enough information to answer your question.
To summarize:
You're using a third party library from Github (link provided) that lets you create timers in various different ways.
You're using a class called Timer from that library, and creating a repeating timer with the method Timer.repeat(after:).
You create 2 repeating timers. The first runs on a 1 second interval and you save it in a constant myGame.
You also create another repeating timer that runs on a .1 second interval and save it to a constant called LevelUpdate.
You want to know how to change the interval of your myGame timer.
That is the kind of description you should write. Clear, specific, and easy to follow.
Now the answer:
You can't change the interval on the system class NSTimer once it's created.
Looking at the library you're using, it appears that it doesn't offer that feature either.
What you have to do is to kill the timer and replace it with a new one with a different interval.
You could probably modify the library you're using to do that internally if you change the interval on the timer.
Failing that, you'd need to change your myGame to a var.
You should create a method func createGameTimer (interval: NSTimeInterval) -> NSTimer that takes a timer interval as input and creates and returns your game timer. That way you can kill the old timer and create a new one with a different interval when you need to do that.
Related
Im trying to find out how much time SpriteKit spends in update, didEvaluateActions, didSimulatePhysics, didApplyConstraints and didFinishUpdate. This would allow me to find whether its my physics, actions, constraints or graphics that are slowing my game down sometimes. Im facing a fps drop of a few frames every now and then and this would be a good way to go i think. But how can i do that? I created a timeInterval() variable but how would i start and stop it?
override func didEvaluateActions() {
let currentTime = TimeInterval() // How to start?
print("didEvaluateActions: \(currentTime)")
}
Thank you in advance.
I'm creating new game with Swift and SpriteKit.
I'm using NSTimer for create a new objects on scene.
For example:
enemyTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector:#selector(GameScene.enemyAppear),userInfo: nil, repeats: true)
But I don't need to use time interval. I want to use distance interval. How can I do this? For example: 50 dots between nodes.
Sorry for my english
But I don't need to use time interval. I want to use distance interval.
NSTimer doesn't know anything about distances. NSTimer does one thing: it sends a message to an object after some time period has elapsed. You supply the message, the object, and the time period. You also have the option to make it repeat or not. That's all it does -- it doesn't monitor object positions or anything like that.
You'll need to keep track of the positions of the objects in question yourself. You could build that functionality into the class you're using for your nodes, or you could create a new class that's patterned after NSTimer, but you can't use NSTimer for this task.
I have a sequence that spawns enemies and then moves them across the screen, it essentially reads
moveAndRemoveEnemy = SKAction.sequence([moveEnemy, removeEnemy])
enemy.runAction(moveAndRemoveEnemy)
The problem is I want to add another action to the sequence which updates the score after the enemy is removed. I have tried making a separate method that increases the score, calling it as an SKAction.runBlock() and inserting it into the sequence, as in
let updateScore = SKAction.runBlock { self.increaseScore() }
moveAndRemoveEnemy = SKAction.sequence([moveEnemy, removeEnemy, updateScore])
enemy.runAction(moveAndRemoveEnemy)
but this doesn't work. I think the reason it doesn't work is because the method needs to be called using "self", as in
self.runAction(increaseScore)
I have tried putting the enemy spawning and moving into a separate method, and then using
self.runAction(moveAndRemoveEnemy)
but this causes the problem to reverse itself, so that the updateScore works, but the enemies don't spawn. Unfortunately I have tried other ways of increasing the score, and they do work for a period of time, but based on how my game is set up they eventually break down as the levels get harder. Does anyone know any ways around this? Any help is much appreciated.
For those that are interested, the final solution reads:
enemy.runAction(moveAndRemoveEnemy, completion: {self.runAction(updateScore)})
You can look into SKNode's runAction:completion: method. This will call completion() after the action has been completed.
Or, in Swift: runAction(_ action: SKAction!, completion block: (() -> Void)!).
If removeEnemy removes enemy from the scene, the action will stop because the node that is executing the action must be in the scene to continue running the action. If you change the order of the sequence to [moveEnemy, updateScore, removeEnemy], updateScore will be called.
Sorry to bother, but I am in a bit of a pickle and I was wondering if anyone here could give me a hand.
I am currently designing a game in which enemies appear on the left side of the screen (out of boundaries) and move to the right. I have used a number of codes (this is using Sparrow Framework) and pretty much the number of enemies increases as you beat them. i.e. lvl 1-> 1 enemy, lvl 2-> 2 enemies, lvl3-> 3 enemies, etc...
I am having some trouble though with producing enemies. I have them appearing on 1 of 5 set paths (path numbers in NSMutableArray), selected by a random number generator, however they often appear on the same path, 1 on top of the other.
To produce the enemies, i am running a number of methods:
addEnemy -> produces the enemies (animations) which then travel from left to right.
onTouchEnemy -> if i touch the enemy, they die. activates drawEnemies
drawEnemies -> calls addEnemy a number of times equal to your lvl. coded as:
for(int i = 0; i < level; i++){
[self performSelector:#selector(addEnemy) withObject:nil afterDelay:3.0];
}
Is there a way to program so that there is a delay between activating the produce enemies method? I tried this afterDelay, but for some reason the program just ignores the 3 second delay and just produces enemies all in 1 go. This is rather irritating since i would like them to appear in a more orderly fashion.
I thank anyone willing to give me a hand with this. Sjkato.
performSelector:withObject:afterDelay: appears to ignore its delay because of the way the code executes. That for loop will iterate almost instantly, queuing up 3 calls to the addEnemy method. After 3 seconds the addEnemy methods execute, almost all at the same time.
To get a better result, you should look at NSTimer. You could set an interval of 3 seconds and tell it to repeat (you can invalidate the timer after the desired number of enemies has been produced).
Something like:
// creates and returns a new timer
// the timer is retained by the run loop for as long as it is valid
// invalidating the timer will cause the runloop to release it.
myTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:#selector(addEnemy)
userInfo:nil
repeats:YES];
This will cause the addEnemy method to be fired once every 3 seconds. You should keep a tally of how many enemies you have already made, and after the last one is made, stop the timer so that it doesn't fire again.
if (numberOfDesiredEnemies == numberOfEnemiesProduced)
{
[myTimer invalidate], timer = nil;
}
Did you mean to do this, with a extra "*i" at the end? Like this:
for(int i = 0; i < level; i++){
[self performSelector:#selector(addEnemy) withObject:nil afterDelay:3.0 * i];
}
Try to look through NSTimer class.
There are some methods that provide ability to perform selectors with predefined delay and loop conditions.
How can I apply a timer count down in Cocos2D and the score counter that both will be display on the screen?
I am still new to this
Please help me out
Thanks a lot
You should have a look into the Timer class. Here is a link to the Timer class overview - cocos2d for iPhone 0.8.2. You won't need to implement one directly (but indirectly), but its good to know how it works.
For displaying the actual counter in the screen using cocos2d, have a look at LabelAtlas. Here is a link to LabelAtlas class overview - cocos2d for iPhone 0.8.2
/* basically you create a LabelAtlas subclass that
has a method for updating itself with the current time
or score. I will call it ScoreLabel in this example */
ScoreLabel * bonusScore = [[ScoreLabel alloc] initWithString:#"0"
charMapFile:#"charMap.png"
itemWidth:10
itemHeight:10
startCharMap:'0'];
// then schedule a method to be called that updates the current score
// schedule: paramter of type SEL. It should pass the method to be scheduled
// interval is in seconds, it determines how often the method is called.
[bonusScore schedule:#selector(updateScore) interval:0.5];
/* the implementation of the updateScore method could be */
-(void)updateScore {
[self setString: [[World sharedWorld] timeLeft]]];
}
Have a look at the cocos2d examples for AtlasSprites (and for LabelAtlas) to see how to implement the image you need to support the class.