I have Cocos2D in my app and I use it as the game engine for my game. At this point I need to have a game loop fire at the rate the screen refreshes. So this leads me to think that I need to use CADisplayLink. So how would I implement CADisplayLink so that my game loop which will consist of Cocos2D will be called at the rate of the screen refreshing?
Thanks!
Cocos2D has the CADisplayLink object already integrated. In fact, it will be using CCDirectorDisplayLink by default unless you have specified a different director type.
Check your project's AppDelegate class, in particular the didFinishLaunching… method.
Related
I am building a simple ios gaming app where I have to move a few objects on screen, and these moving objects react to swipe gestures and change their direction based on that. I am not using spritekit or any other gaming framework for this, and the way I am moving the objects is by triggering an NSTimer that fires 60 times a second. I am not using any threads explicitly so I guess the timer is executed by the main thread ? The code block that the timer triggers updates the location of objects based on their speed (defined as pixels per time unit in x/y direction). It is working fine and I am almost at the end of my project, but while testing the app I've realized that although the movement of objects seem pretty good most of the times, however sometimes the movement is a little rough/patchy.
My question is that is it the right way to do something like this, how can I improve the performance ? will using something like GCD can help with the issue of jittery movement ? (I haven't looked into GCD in detail but I am willing to spend time on it if I know that will help)
Thanks for any help !
and the way I am moving the objects is by triggering an NSTimer that fires 60 times a second
I would recommend not doing that. Various forms of animation are built in (View animation, Layer animation, CADisplayLink, UIKit Dynamics), and of course there's always Sprite Kit. Use the tools you are given for this purpose. Don't reinvent the unicycle when you already have a Ducati at your disposal.
This seems like such a basic concept but there is really no good answer.
I currently have a pretty basic setup, in my game's scene, I have an enum gameState which is currently either inGame or gamePaused.
I have my button set up, and I have it so pressing simply toggles gameState.
Then, to make it work, I have two separate update methods: One for when gamePaused, one for when inGame.
This works for 95% of my game, as the updates in my game can be pretty readily started and stopped without any issues. There are some issues I cannot tackle though.
First and foremost are actions. I use SKActions for a bit of my project (some movement, scaling, fading...) and this method does NOT pause them. This can be catastrophic in certain points. Secondly, this doesn't handle particles, physics, and a few other things that are not directly associated to my update methods.
The only clue I have is self.view.paused = YES, but that isn't going to work either.
First off, this DOES fix my actions, particles, and physics problem... kinda. But This question suggests that SKActions aren't actually PAUSED by this, but actually STOPPED completely. Is this true? If it is, then it won't work smoothly either because my actions are thrown out of whack.
Also, pausing the view seems to do what it says: stop everything. EVERYTHING. Newbie question here, but how am I supposed to get any code to run at that point? It's all cut off. Is this where I need subViews? I have never used a subView yet, but it sounds like its what I want in this case.
Simply put, there are a lot of unanswered questions for me, and I don't know how to proceed. I'm hoping there's some 'standard procedure' for pausing in Sprite Kit, but with pausing the view halting actions I truly have no idea where to proceed.
Should I move away from using actions? Is my idea of a pause subView sound?
I don't want to babble, all I want to know is how you go about pausing in your average Sprite Kit project. Additional info provided upon request.
Pausing a node will pause (not stop) the node's actions, and i suppose pause will also be applied to all children of the paused node in the same way. All other unpaused nodes will continue to run their actions to completion.
You should have a "game layer" node with all game nodes in them that you want to pause, and then just pause that "game layer" node. Then have a "pause game menu" node where you add all the pause menu stuff you need which will continue to function normally even if the game layer is paused.
Be very sure you do not use performSelector or NSTimer or GCD or any other scheduling methods besides actions or the scene's update: method because those will not adhere to a node's paused state.
Pausing the view effectively freezes everything in it, pausing the scene according to some will not pause the update: calls - but I have not verified this myself. If this were the case you can always check inside the update method whether a given node that you send a message to is paused and if so, decide not to send certain messages to that node.
I just called a map function on all children of the scene and set the paused property to true
self.children.map{($0 as SKNode).paused = false}
By setting it to true you can easily undo the freeze.
EDIT:
Better use a for-loop to iterate over the children.
for node in self.children as [SKNode] {
node.paused = false
}
I can tell you what I did in my game:
Pause the SKView on -applicationWillResignActive: (or equivalent, using NSNotifications),
Un-pause the SKView on -applicationDidBecomeActive: (or equivalent, using NSNotifications),
For the actual game scene only, I set a boolean flag _isPaused when resigning active, and if it is true I just skip the -update: method (frame updates). (I also show the "paused" menu when the user resumes the app).
...But my game is a simple puzzle game, and there's no long actions that should continue past the pause/resume. I can not confirm right now that all actions are aborted, but I think it's not the case.
I also used self.children.map{($0 as SKNode).paused = false} and it does work if you create a var layer of type SKSpriteNode and add it on top of the scene. But I also have an NSTimer I'm using to spawn sprites on the scene. Everything currently on the scene is paused, but sprites keep appearing and moving across the screen. It is not pausing the spawning.
I tried pausing the NSTimer when I call the above code by setting repeats to false, then setting it to true when I remove the layer but it doesn't work. I also tried self.scene?.view?.paused = true but that freezes everything and the layer I create does not even appear onscreen.
You need to set the delegate for the View!
func PauseGame(){
self.scene.view.paused = true
}
fun playGame(){
self.scene.pause = false
}
This function is work perfectly if you are not using the NSTimer to call a function. If you use NSTimer your view will pause perfectly but when you play the game again by play game functionality you see that all the functions that use the NSTimer function that runs in the back end and your screen full with your sprite-kits. So when you use NSTimer in the function you have to first pause the NSTimer functions also after that this function work perfectly.
//For Pause
func pauseGame() {
scene?.view?.paused = true
}
//For play.
func playGame() {
scene?.view?.paused = false
}
I have a simple scenario (default SpriteKit template): one ViewController and a MyScene SpriteKit scene.
In my ViewController I managed in viewDidLoad the gamecenter initialization but my scene after start immediatelly starts a rather quick sprite movement infinitely (a background parallax scrolling).
Everything works correctly but until GameCenter goes through the authentication procedure my sprite movement lags, breaks, not running fluently.
What practice can I have to minimize this (with keeping the parallax sprite movement running)?
I'm testing this on iPhone4 device (IOS7.03)
GameCenter authentication is actually something that has been causing lag in games for awhile. There are a couple ways people try to get around it, and it's really depends on the app and programmers taste.
Pause the game during GameCenter authentication
This is the easiest way typically, and pretty straightforward.
Put the authentication on another thread
If you desire a fluid option from menu to gameplay, this would be the route to go.
Just use GCD to start a new thread and run the GameCenter authentication in it.
Hope this helps. There might be a couple of other ways, but these are the two I've seen the most. I typically just use the first method.
I am trying to completely reload a gamepage in monogame - simply by touching a sprite on the page. I cannot find any solution for this.
In Android, I can call finish for the gameactivity, and then recreate a new one. How can I do that in monogame?
I am using WP8.0 SDK, monogame with XNA 4 framework.
I'm not familiar with Android development, or specifically what you mean by "gamepage", but typically this type of thing is handled with "states" in game development. You can have a playing state, paused state, Main Menu state, etc, and you just pass the game object to each state class and have it override the update/draw methods with its own information.
So, in your case, you would be in the playing state of the game, and if the sprite is touched, you might want to go back to the main title, you can pass the game object to the Title Screen State. The Title SCreen can have a call to LoadContent() which will reload all assets (effectively restarting the game completely).
Not sure if that helps. =X
Cocos2d templates and the usual sample projects initialize cocos openGL ES view and other stuff in the applicationDidFinishLaunching / application:didFinishLaunchingWithOptions: method. In relation to the last method, Apple iOS Programming Guide states that:
"Apps that use OpenGL ES should not use this method to prepare their
drawing environment. Instead, they should defer any OpenGL ES drawing
calls to the applicationDidBecomeActive: method."
So, my question is, is application:didFinishLaunchingWithOptions: really the proper place to initialize cocos2d? or should we be doing that in applicationDidBecomeActive: ?
If you think that applicationDidBecomeActive: is the way to go, what would be the consequences in relation to background execution? i.e. what should we do to avoid a sort of double initialization when the app comes to foreground from being inactive?
Thanks in advance
Good question … so far 99.9% of all cocos2d apps do it the way cocos2d does it and I haven't heard of a single issue.
Since Apple doesn't really explain why this is particularly important for OpenGL ES apps, I would assume the following:
OpenGL ES apps tend to take a relatively long time to initialize their view. In particular when loading lots of assets. This could lead to the App being killed by the system if it takes too long. That means the Cocos2D first scene should load fast, and in particular it shouldn't load all the game's assets unless loading of the first scene is deferred to applicationDidBecomeActive. The latter requires an additional check to make sure there's no other scene already running.
Apps are supposed to perform common tasks in applicationDidBecomeActive. This is generally good advice because some settings can now change while the app is suspended. For example the user might change the device language, or enter Airplane Mode and the app needs to respond to that when it becomes active again. Some changes may affect OpenGL ES apps in particular, like for example reloading all bitmap fonts if the user changed locale from english to japanese.