I'm using Game Center to create a real time match and I am working on a restart button. When the game ends it takes you to another screen that shows you everyone's score and on that screen there is a restart button. If someone presses it their name will turn green and if they leave the game then their name will turn red. Once everyone has either hit restart or left the game then the game will restart by presenting the game scene again.
The thing is though, they're all doing this at slightly different times and sometimes one of the devices will send a signal to the other devices before those other devices have made it to the game scene and so the message isn't being interpreted and is just lost. So my question is, is there any way to make sure that all the players go the the next scene at exactly the same time?
You can have a synchronization step after the scenes have loaded. You will never be guaranteed everyone loads at the same time/rate.
So,
1-signal everyone to load,
2-everyone works on loading,
3-don't show the scene or render anything relevant yet,
4-wait for everyone to send a ready signal (some people may have to
send the ready signal repeatedly to work around boundary loading
issues),
5- everyone gets a ready signal,
6- users can now display the scene,
7- do one last check by sending another 'ready signal' to everyone
(again some may have to broadcast multiple times),
8- with the last signal received from everyone confirmed, the game can begin.
This redundancy is to make sure the users are able to broadcast appropriately before and after showing the scene. Of course, There is a LOT of implicit error checking and timeout checking during this process, if there is a stray user unable to broadcast, then they may just need to be considered for booting off the match after a given amount of time so the other players can still play.
Also this is my best whack at syncing things as much as possible to where you can try and make sure signals are not lost. Do a synchronization procedure, then start sending relevant signals.
You CAN NOT guarantee exact timings of next screens for different users, you can just get them as close as possible.
The important part is NOT the screen display but rather making sure all users are in the correct STATE to receive the next set of data broadcasted by the others.
Different internet speeds and different device speeds will always hinder perfect visual synchronization.
Related
I am working on an app for a physical boardgames I have produced in the past. Everything is working fine (for now). But the app "freezes up" when the code for the computer "thinking" kicks in.
This is understandable, the computer needs time to make it's turn.
My question is. Is there any way I can simultaneously set an animation to run (like a progress icon), while the computer continues to "think" over it's turn?
Thank You.
You can't make something like a progress bar which indicates exactly when the computer will finish 'thinking' exactly because the computer does not know when it will be done.
However, you can create an animation that will run as long as the computer 'thinks'.
In your Gameplay file in Spritebuilder, create the animation that you want shown while the user waits. Chain this animation timeline to itself. Let's call the default timeline animation 'default' and the 'computer is thinking' timeline animation 'think'.
Inside the method you use to start the computer's turn, add a line of code that warns cocos2d to run the 'think' animation sequence; it would also be good to make any user interaction with the game impossible at this time (example below is given in Swift):
animationManager.runAnimationsForSequenceNamed("think")
self.userInteractionEnabled = false
Since the 'think' timeline was chained to itself, it will run in an infinite loop, only stopping once cocos2d receives an instruction to break that timeline and start executing another one, so, just inside the method you execute once the computer's turn is over, add these two lines in order to stop the 'think' animation from running and to enable user interaction once again:
animationManager.runAnimationsForSequenceNamed("default")
self.userInteractionEnabled = true
Not knowing where you are building your actual game in, using different threads is the way to go. What are you building your game in? Which language, framework, platform?
There are a couple of games that I want to mention, to show how they handle entering the background mode:
Clash of Clans. It seems it doesn't free any memory at all when it enters background mode, in fact I can open lightweight applications like Notes and get back to the game to continue playing without any noticeable delay, which seems pretty cool to me from the user's perspective.
Game of War. The game immediately falls back to the loading screen and the initialization process starts all over again when it runs inmediately after it enters background mode, it's just like restarting the game, which is very annoying sometimes.
So, in the case of my game, it has an average memory footprint of 25 mb (and it's going to be less with some optimisations), I know the "Free up as much memory as possible" stuff recommended in order to be a good neighbour on the iOS platform, but considering that freeing memory when the game enters background mode could cause my game to have an "annoying" pause when it enters foreground mode...
...should I save the progress and pause the game when entering background mode without freeing up any memory at all, or should I free as much memory as possible and load those resources again when entering foreground mode, with the respective loading pause?
As you yourself point out (by giving two games as examples that use opposite strategies), there is no unique answer to your question.
I think a proper answer can be worked out in a given case by clearly defining the use cases you want your app to support.
E.g., one use case, as you mention, could be "the user can switch to a lightweight app and go back to the game without unnecessary waits". (UC1) Then, you should also have a list of lightweight apps and reference devices where you want to make sure that the use case is actually satisfied.
On the other hand, you may want to support a slightly different use case: "the user will always come back to the point where she left the game, unless the app was terminated, in which case the app should present the main menu". (UC2)
In the first case, not freeing up could be the best approach; in the second case, you may want to minimise the chance that the app is terminated while the user does another task (lightweight or not), so that she can go back to the place where she left, even though she has to wait for all resources to load.
There might even be cases where an intermediate approach is best, where you free up only a part of memory, so to strike a balance.
And, of course, it would make no sense going for the first use case (UC1) if your app memory footprint is so large that it will be terminated almost immediately after switching to another app on most of the devices. In such case, it might make more sense freeing up memory, so you at least can spare the app load time (vs. resources load time) when you go back to it.
So, in the end, it depends...
I would save the progress and pause the game when entering the background without freeing up memory, as many people if they need the memory just delete it from the history thing, or the "carousel of cards". Multi tasking is emphasized in ios 7 so you don't want them to restart the game.
for example, somebody wants to text someone in the middle of playing your game. They exit the game and text someone. But then they have to load the game again. Nobody likes this.
While your game doesn't take up much memory, most users don't bother to close out of applications. I would recommend freeing up as much memory as possible without sending them back to the start menu, much like #sergio recommended with his 'intermediate' option.
I strongly suggest to free up memory. I have an iPhone 4, and some apps are now taking too much persistent memory, so that switching between them becomes a nightmare. E.g. recently, I could not switch between Safari and Twitter anymore, without them reloading all their state (taking more than 20 seconds in both directions).
Bottom line: Try to keep important state, but with as little memory as possible (i.e. not retaining images / textures), otherwise the app will get closed on older devices and you will effectively lose more state.
Save the progress and free the memory with the loading pause, especially if your game is for older devices. I have an iPhone 4, and when a game is running in the background without freeing memory, my foreground apps crash every 15 minutes. But if you have things such as "Vehicle/weapon upgrade is done in x minutes", you will need to save game progress and free the memory, so only the upgrade timer is running. If you do enough optimisations you may decrease the memory footprint, so I would recommend you to keep the optimisations in mind while coding and then the background performance will be your least problem.
I'm writing an iOS app that uses chromecast to cast a series of pictures. When the user taps on the right edge of the current picture, the app presents the next picture, and the next picture is casted to the bigger screen. However, if the user taps fast enough and brings up the third picture before the second picture shows up on the bigger screen, the second picture, once shows up, will stay there even though the third picture shows up on the device. From the Google Cast SDK it looks like all the casting requests are queued up and the third one should show up automatically. So does this mean I have to queue the requests manually on the sender side?
I imagine your images are available on a server (which could be your phone as well). What receiver are you using? What is the behavior you expect to have? If, for example, you need to see all the images no matter how fast you cast them, then your receiver should queue the urls of images and when is completely loaded, loads the next one, etc. If you expect to skip over the previous images if a new one is casted, then your receiver should drop the previous requests as soon as a new one comes in.
You can queue them on the sender side as well (especially for the first scenario) and your sender should listen to "image is fully loaded so send in the next one) but that is not optimal since
your app creates a better experience if the next image is loaded behind the scene on the receiver while the first one is being shown so it can quickly transition to the next one and
You probably want to provide an experience that if you queue up some photos, your app can play them on the TV even if your phone gets disconnected (only relevant if images are served from a separate server).
Another factor to consider is what do you expect if a second device is connected to your Chromecsst while the first one is casting; do you want to the second one be able to "participate" in the activity and cast as well or not.
Regardless, there is a sample code on our github repo that shows a simple playlist for videos (queued up on the receiver).
I have a question regarding sending and receiving data through Game Center when playing a multi-player game on iOS.
In my game after I matchmake two people, the game is taken to the Game Screen where the user can start playing.
Because the two devices do not load the game screen at the same time (for network reasons), the viewDidLoad function in my first device sometimes will already have completed by the time the second device has loaded the screen.
What this means is say for example in the viewDidLoad I send through my local player alias to my slower device, as the slower device is still loading by the time the faster device is doing so, when the screen loads, my faster device receives the slower devices player alias, but not vice versa.
Therefore, is there any easy way for one device to detect when the other device has loaded, and push through any relevant code from there?
First of all, you should only send messages once the connection has been established. You can detect this in the match: player: didChangeState: method of your delegate by waiting for the GKPlayerStateConnected state. If you send any message after this event occurred, it should arrive.
Otherwise, there may be concerns with your design. Your delegate should be able to interpret and use any message that comes in. If you are exchanging player aliases and really need to know them when starting the game, you should wait for the alias to come in as a trigger, or come up with an even more elaborate handshake protocol.
So, one simple recipe would be to
Send the alias shortly after you receive the GKPlayerStateConnected message.
Transition to your game view after receiving the alias of your peer.
I am working on a research project that involves user interaction with an iPod. The application runs for approximately 10 hours, and I need to record the following information:
1) How many times was the screen touched?
2) For each touch, where was it touched? (Inside the button vs.outside)
3) What time was it touched? This would preferably be the time of day, but I can do back-calculations if this is not possible.
This information needs to be saved, and exported to a file that can be manipulated in Matlab, Igor, Excel,etc.
The application itself is very simple. A button in the middle of the screen flashes while playing a sound. When a touch event occurs inside the button, the flashing and sound stop for 30 seconds.
My questions is similar to this one from 2010 How to record all of the user's touches in iPhone app. The asker, however, did not provide the details for how he accomplished this, and I'm afraid I need a little more guidance than is given.
I'd be grateful for some advice, or if you could point me to the appropriate resources. I would especially appreciate it if you could also let me know the general area where the code should go. I'm still getting the hang of objective-C.