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.
Related
A lot of people when creating a Timer app or a StopWatch, or similar uses this function:
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true);
in order to update the timer using a user defined function updateTimer that gets called every timeInterval.
But my question is whether using such function could give a non accurate timer, since we call a function that is user defined and we don't count the overheads that there may be, because of our implementation. And if we have loops or other stuff going on, am I right that this isn't the best approach?
I'm wondering because in my case I would need to use this function to increment a variable timer, and also another function that computes the string of the timer to display every time the updateTimer gets called.
What would be the better and most accurate approach to implement a timer? Maybe using NSDate?
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.
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.
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.
I'm trying to make a subclass of NSCalendar, but without much luck. I've tried two ways:
thorough categories. I can create a modified object and a test method that I added (not part of NSCalendar) works just fine, but overriden methods don't work - e.g. if I call dateFromComponents:, the NSCalendar method is apparently called, not what I wrote in the category definition
regular subclass. In this case I can't even create an instance: initWithCalendarIdentifier throws a _CFRequireConcreteImplementation exception. Initially I only had a couple of methods overriden in the subclass, but then I've overriden all of the (documented) NSCalendar methods - and the result is the same.
Is it even possible to subclass NSCalendar?
The reason I want to do it is to make repeating Local Notifications with non-standard repeat intervals. The default functionality allows Local Notifications to repeat every [calendar unit], but I need irregular intervals - e.g. I can emulate "every 15 minutes" notifications by creating 4 "every hour" notifications 15 minutes apart, but I need them to fire at, say T+20, T+22, T+24, T+44, T+46, T+66 minutes and so on (T is the start time) - the interval between notifications is 20 minutes, then 2 minutes, then 20 minutes again and so on.
I was hoping that, since UILocalNotification wants an NSCalendar (in repeatCalendar property) to calculate when to fire the next notification, I can achieve what I want by overriding, say, dateFromComponents to just return [NSDate dateWithIntervalSinceNow] with interval alternating between 20 and 2 minutes - but my cunning plan seems to have a major problem because of the inability to subclass NSCalendar.
Edit: This whole thing is needed for when the app is in the background. In the foreground I use timers, just like No one in particular suggests.
Even if you do manage to subclass NSCalendar, I doubt it'll work. I strongly suspect that local notifications are scheduled by SpringBoard, and I don't think it's going to launch/resume your app every time it needs to see what the next fire date is.
The first step is to find out what UILocalNotification is doing with your calendar. The easiest way to do this is to write an NSObject subclass which forwards undefined method calls and prints log messages (respondsToSelector:, methodSignatureForSelector:, forwardInvocation:). Generally, you want something like if ([super respondsToSelector:selector]) { return [super ...]; } else { return [target ...]; }.
Then, the easiest hack is to write a class which implements the necessary methods of NSCalendar for your purposes.
You might also consider calling [super init]; -[NSCalendar initWithCalendarIdentifier:] is likely to return a different self (e.g. [self release]; return [[NSGregorianCalendar alloc] init]), and you don't want that. What calendar identifier are you passing it? Maybe it's complaining that it requires a "concrete implementation" that it knows about for the calendar identifier you're passing.
A direct inherit from NSCalendar is tricky because I think that it's a class cluster. I'm a bit fuzzy on this concept so I'll give you a link to the Apple document instead of making a greater fool of myself.
http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW34
Try using the NSTimer method
+ (NSTimer *)scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
Set the repeats to TRUE and have a time interval of 2 minutes. Have a counter that you set to 1 or 10. Everytime the selector is called you decrement the counter until it reaches 0 when you do your work and reset the counter.