I'm really quite confused as to how I'm supposed to implement the following app. I have 90% of the code, but the last 10% I can't figure out. I can't figure out how I'm supposed to control the flow of events. I'll describe the app/game first.
The Game
The flow of events happens like this. The user sets the number of teams and the number of rounds. The game will then show a screen saying "Pass to team 1". The player on team 1 then presses a button which pushes on another view.
On this view, the current player tries to describe words/names on the screen to the other players on their team without saying them. Each time someone guesses a word/name correctly, the player presses a button which pulls out more words, and adds 1 to the score for that team. This continues until a timer runs out.
When the timer has ran out, this view will get popped off the navigation controller, and the previous view will tell the player to pass to team 2.
This will loop for the number of teams and the number of rounds.
My Problem
My problem is that I really don't understand how I'm supposed to keep track of all these events. I have a "GameBrain" class where I keep an array of scores and team names etc. but I don't know how to access this from each ViewController.
I asked a similar question earlier and someone suggested a Singleton class, but I've since read that this is bad practice and I can't help but feel that I should be able to do this following the MVC design pattern.
So my question is, how would you guys/girls approach coding a game like this?
Sorry for the kind of vague question. Any help would be greatly appreciated.
EDIT: Are delegates the correct way to go? i.e. Would I create the first ViewController that I need from my "GameBrain", set the brain (so self in this case) as the delegate for this instance, and have the ViewController call a "I'm done with this round" method on the brain which would then fire off the next ViewController?
Your GameBrain should be designed as a singleton, singletons may have some bad sides, but in your case they are the best choice, so just go with it
Since this class has to be accessed by all your viewControllers and since there is no need of having multiple instances of this class, then this would fit a singleton perfectly
I started with a comment but moved on to an answer.
In short, as #Omar says, for a quick little thing you describe the Singleton may work fine.
The longer version, several years ago I designed a quick little thing like this and we released it and all was well. Several months later we had several million users and had undergone multiple development phases and the Singleton pattern we had begun with was destroying the project. I might mention that my boss insisted at the beginning it was a small project and we would release it in two weeks and be done - hah, funny guy.
The reason the Singleton did not work well is because it restricted modularity. In the end, everything "game related" had to come back through this class which in turned sent a message to another class which sent a response back to the Singleton etc. etc. It was horrible.
If you have the time/energy, I recommend you create a GameBrain (or whatever) class for each game. This class is usually only ever used in the "game screen" anyway, so why keep it around when you are back in the menu or sending emails? If you need it persistent the make it backed by a database. If you only need it in one or two extra places (your winning screen might need to know who won etc.), just pass it along by reference - you should only need to do it one or two times.
Good luck.
Related
I have a multiplayer project which has some forever loops with checking code inside of them.
The problem is, multiple computers might process this and change crabx or craby due to lag in the variables dvotes, uvotes, lvotes, or rvotes. Only one machine should change this, though.
This can be easily solved by giving each player an ID like many people do in SQL. I would just check if the ID is 1, and that would be the "operating machine". I would then do all of these checks on that one machine. It would do things a Scratch server would do if you could program it...
The problem with this is that there is no way to detect when a player leaves the game. There is no block that is called "on exit" or "on stop button pressed". How would I go about doing this? I have seen people have a button which people click to exit, but some people will not click it/not even see it.
Thanks in advance!
Option 1
I've never been especially successful with cloud data myself, but I've heard the theory on this before:
Essentially, each player gets a "counter". Their computer then constantly increases that counter. If the counter ever stops increasing (which will be detected by the other computers, who are all looking after one another), the project will know that the user has left and one of the computers will take care of removing their ID and other data.
Obviously, this is much easier said than done. (As I said, I've never gotten complex cloud data to work well for myself, but I've seen it done successfully and explained.)
Option 2
Alternatively, you might be better off taking advantage of this cloud api created by MegaApuTurkUltra. I find that stealing from others tends to be the best way of solving problems when it comes to code. ;)
I'm new to iOS (although I do have a lot of C++ experience) and I am working on a turn-based card game using gamecenter. Here's the catch - The player who's turn it is is the judge and waits for all OTHER players to play a card before the turn is over. Is there a way to do this in Game Center, so all players chose what to do simultaneously and once all have done so, the judge is notified, makes a decision, and then passes priority to the next player? For example, say we start turn 1. I ask the question, #"What is your favorite color?" to all players passing them a gamestate which has that as the question and them not having answered it. Then you respond, #"Green", and our friend Steve responds #"Blue". I then decide which is better, give one of you a point, and then whoever I gave the point becomes the new judge. My question is, how do I allow all players to respond simultaneously, rather than sequentially. I know that, worst case, I could sequentially loop around through players until it comes back to me, then judge it, but this would slow down my game and make it less fun. Is there a way to do this simultaneously?
I agree with NSSplendid about the API for turnbased games requiring sequential turns. The only truly simultaneous method would be using the real-time matches from GKMatch, and that isn't really an option for games with more than a few players.
However, the sequential version could be improved slightly by using a programmatic approach to game center instead of the default view controller.
Ending a turn fires off a push notification through Game Center, and by using GKTurnBasedEventHandler's method handleTurnEventForMatch:didBecomeActive:, you can receive that in your app. When the judge asks the question, have the users display that as part of the game, and have their responses stored locally until their turn. Once it becomes a given player's turn, they receive the notification, even with the app in the background.
In the method, it can check the locally stored answer and end the turn immediately, if they've answered. If they haven't, send the turn once the answer is complete. It's not truly simultaneous, but the judge gets the answers as soon as everyone has responded, without the players having to wait for one player to finish before they can enter their own answers.
The players won't get the notification that the judge has ended their turn until they open the app, but they can't see the question anyways without doing that. Another approach to this, though slightly wasteful, is after the judge ends their turn with their question, is to do a runthrough of all the players ending their turn as soon as they get the "Your turn" notification, so everyone knows a question has been asked, then doing the steps from the previous two paragraphs.
The iOS API is built around the model of sequential turns. While the workaround you mentioned will work, there is no way to get GC to do real concurrent turns. Sorry ):
Me and my team are currently rookie developers in Objective-C (less than 3 months in) working on the development of a simple tab based app with network capabilities that contains a navigator controller with a table view and a corresponding detailed view in each tab. The target is iOS 4 sdk.
On the networking side, we have a single class that functions as a Singleton that processes the NSURLConnection for each one of the views in order to retrieve the data we need for each of the table views.
The functionality works fine and we can retrieve the data correctly but only if the user doesn't change views until the petition is over or the button of the same petition (example: Login button) is pressed on again. Otherwise, different mistakes can happen. For example, an error message that should only be displayed on the root view of one of the navigation controllers appears on the detailed view and vice versa.
We suspect that the issue is that we are currently handling only a single delegate on the Singleton for the "active view" and that we should change it to support a behavior based on the native Mail app in which you can change views while the data that was asked for in each one of the views keeps loading and updating correctly separately.
We have looked over stackoverflow and other websites and we haven't found a proper methodology to follow. We were considering using an NSOperationQueue and wrapping the NSURLConnections on an NSOperation, but we are not sure if that's the proper approach.
Does anyone have any suggestions on the proper way to handle multiple asynchronous NSURLConnections to update multiple views, both parent and child, almost simultaneously at the whim of the user's interaction? Ideally, we don't want to block the UI or disable the buttons as we have been recommended.
Thank you for your time!
Edit - forgot to add, one of the project restrictions set by our client is that we can only use the native iOS sdk network framework and not the ASIHTTPRequest framework or similar. At the same time, we also forgot to add that we are not uploading any information, we are only retrieving it from the WS.
One suggestion is to use NSOperations and a NSOperationsQueue. The nice thing about this arrangement is you can quickly cancel any in-process or queued work (if say the user hits the back button.
There is a project on github, NSOperation-WebFetches-MadeEasy that makes this about as painless as it can be. You incorporate one class in your classes - OperationsRunner - which comes with a "how-to-use-me" in OperationsRunner.h, and two skeleton NSOperations classes, one the subclass of another, with the subclass showing how to fetch an image.
I'm sure others will post of other solutions - its almost a problem getting started as there are a huge number of libraries and projects doing this. That said, OperationsRunner is a bit over 100 lines of code, and the operations about the same, so this is really easy to read, understand, use, and modify.
You say that your singleton has a delegate. Delegation is inappropriate when multiple objects are interested in the result. If you wish to continue using a singleton for fetching data, you must switch your pattern to be based on notifications. Your singleton will have responsibility for determining which connection corresponds to which task, and choosing an appropriate notification to be posted.
If you still need help with this, let me know, I'll try to post some sample code.
I am struggling with this question since I noticed that many functional testing frameworks (like Selenium for the web or UISpec for iOS) actually simulate UI events while testing. I am asking: couldn't it be sufficient just to check for preconditions such as that, e.g., the target and selector for a button are set correctly and then fire the selector manually? Why do I need to simulate touches? This has the con that you have to know more about the UI elements you're testing (you have to know what makes them to behave correctly), but since I am the one writing the tests, maybe this doesn't matter?
Could anyone shed some light on this?
Simulating touches can be useful for determining crashes caused by obscure or unplanned user behaviour - a particularly common one is having two items pressed simultaneously. It also allows you to create potentially quite esoteric tests: for example, random user input for a sustained period of time to attempt to crash or break your application in ways you wouldn't expect. The level to which you'd do this would depend on your app, and how important it was to you.
Your alternative approach also has some disadvantages when it comes to multi-touch. Whilst it would be fairly straightforward to fire a button selector through some sort of automatic test rather than simulating user input, what happens if you have an app that deals with swiping, pinching, or other multiple input gestures? In those cases the desired result may not be as black and white as the on/off of the button: you may have many shades of grey and differing output that required validation.
Simulated UI testing actually has quite a long history - there's an interesting story (well, interesting to me) about the original MacPaint and how a random UI input test was able to assist in reproducing obscure or difficult crashes here: http://www.folklore.org/StoryView.py?story=Monkey_Lives.txt
Just to give background for my situation, I have a manager singleton that pulls data from a webserver and provides access to the downloaded data. I have several types of views that will consume this data, but only one view at any time will need to receive events.
I was just wondering what people prefer to use when they need to get events from a singleton. Do you use NSNotificationCenter, Target/Action, or delegate?
Thanks for any help.
Are you really, really sure only one view needs to receive events? For instance, you don't have a master view that would need access to the same update that a subview was notified about?
If you truly have only one view controller needing updates at a time ever, I might use a delegate approach. Here's something to consider - what happens if you are in the middle of receiving an update and the user change screens... is that OK? would you cancel the request?
Anything more than one, or if that in-flight changing delegate scenario has issues, then you may well be better off with a notification that anyone can hook into. It's best to keep the notification light with some kind of reference to the change and have the receiver have to look up the altered data.
If there are going to be a large number of events, then you want to stay away from NSNotifications.
For the least amount of overhead I would go with the delegate pattern, although I don't think that target/action has much more overhead than delegates.
Try your favorite way and if there is a problem profile or try a different approach.
I usually start with the easiest to get implemented. For example I once tried to use notifications for some interface code I had written years ago but with 30-60 updates/second the whole interface bogged down unacceptably so I went with delegates which fixed the problem.