nextLevel Method - ios

How do I make a method that switches levels for me? I'm using cocos2d btw. I'm not talking about the simple replaceScene, I want a method that, when called, will change from say level 10 to level 11. I'm not sure how to achieve this, but my levels are simply named LevelOne, LevelTwo, LevelThree, etc. I thought about doing
-(void)nextLevel:(ccTime)dt {
if (currentLevel += 1) { //CURRENT LEVEL + ONE LEVEL
}
}
but of course, just adding one to currentLevel (an int I have that has the current level the user is at) would just make the number +1.
I don't want a method that detects the level, I want a method that takes currentLevel and goes to the nextLevel.

One nice way would be to store your data in a linked list. Here's a nice article on how to implement one in Core Data. I'm actually using this in my app currently; while the setup is a little complex, the extreme benefit comes with lines of code like this:
IPhoneGameScene *nextScene = [IPhoneGameScene sceneWithPuzzle:[self.puzzle next]];
[[CCDirector sharedDirector] replaceScene:nextScene];
So clean!

Related

Sprite-kit game lifecycle, properties and global variable?

In my sprite-Kit game, my game goes through the various scenes, across which I want certain variables to be available. See the following diagram:
So the title screen loads the main game screen. When the 'wave' is finished (all objective complete or all lives lost), the end scene is presented with some stats. Then if the player has lives left the main game is loaded again, if not the title screen is presented again.
I want the player's score and number of lives left to be available across the main game scene and the end scene; the high score should be kept across all scenes.
I'm using global variables for these, whereas most of my variables are properties defined under the class.
The first time I had to do this (for my score property before I added a high score or multiple lives) I used a score property on every scene and passed it between scenes when I did the presentScene for the next scene, but that seemed clumsy, especially when I had to add more variables.
Is there a best practice for this i.e. should global variables be used/not be used and if not, is there a correct way to handle properties, perhaps controlled by where you initialise them e.g. in init compared to didMoveToView, which determines if they are re-initiialised when the scene is shown again?
EDIT:
Am I doing something 'wrong' when I go from the End Wave Scene back into the Main Game Screen that is causing the main screen to be re-initialised again? Is there a way to preserve it (with all it's properties) so it isn't fully re-initialied but it's didMoveToView is called again?
I know that many people work with generalized rules like "Don't use globals" or "Singletons are evil". These words of wisdom may be applicable at times, however another way of looking at them would be as tools to make you more efficient in getting your game finished.
There are times when globals/singletons are useful. Games and embedded systems play by different rules than conventional applications. These are typically resource constrained "applications" coupled with performance requirements. Globals are more common than you think in each. Singletons are also commonly in use. I've worked on both embedded systems and games and can say that on every project I've worked on, they've employed either globals, singletons, or both.
In practice, I use singletons over globals. Mainly because I don't have to worry about where to shove the global and what header file it belongs in. Note, the basis as to the why will differ from all you Swifties. For me this stuff is done in primarly in C++ with some Obj-C and a smattering here and there of Swift.
The need to manage game lifecycle is independent of SpriteKit. Many of the SpriteKit posts I see on SO have the devs embedding game state into the scene or VC. They are usually faced with some dilemma on how to move state to the next scene. While this approach may be good for what I will call "local state" (ie. state for the current screen, stage, etc), it is not good for global game state. For example, if you transition from a main screen to an option screen then back to main and then in the game, how are you tracking the changes to those options (eg. changing game difficulty)? Yes you certainly can pass around dictionaries, structs, or what have you around. But at some point of time, you are going to discover that having one common and convenient dumping ground for it all is more convenient. This "dumping ground" would be globals/singletons.
Now before ya'll start yelling at me, there is a catch to all this crazy talk of globals and singletons. I'm not saying create alot of globals/singletons. Rather, be controlled aboutwhen/if you employ globals/singletons.
I'm not talking a gazillion if 'em. I'm talking like one (although I usually have a handful in use). Enter our ficticious friend, the GameManager.
Let's walk down a very simple scenario of a space shooter. Say I have multiple screens such as the title screen, main screen, the in game screen, and the end wave screen. There are certain bits of information that are useful to be passed to the different screens. For example high score or even current score. Those may be values that you want to display on various screens/scenes. So where do you store the score? How do I pass the score between them? For example, if the last high score is displayed on all screens, where do I keep that value?
class GameManager : NSObject {
// Overall game state, GameState is probably some enum
var state:GameState
var lastState:GameState
// Sometimes tracking scenes is useful
var currentScene:SKScene?
var nextScene:SKScene? // Sometimes helpful if you need to construct the next scene and it takes a non-trivial amount of time
// These are the globals we need to share to different "parts" of the game
var score: UInt
var highscore: UInt
var lives: Uint
var stage: Uint
var highscores:[Uint] // A list of all the high score for the user. You would probably want HS based on other users too
// Egads a singleton!
static let sharedInstance = GameManager()
}
If this was a global, it would have some global definition of the instance outside any scope. Like:
var theGameManager : GameManager
So if you want to udpate the score, you'd do
theGameManager.score += 100
If it was a singleton updating the score would look something like:
GameManager.sharedInstance.score += 100
Okay the singleton syntax is a little longer, but perhaps a little less cryptic than the global as to where/what this is.
But now here is where you can have a little more power in things. Let's say when you add a score, every multiple of 100000 scores you an extra life. I can now easily leverage the setter and use that setter to also reward the extra life.
For example this:
GameManager.sharedInstance.score += 100 // the magic of the 100000 for extra life happens automagically in the setter
versus something potentially like this:
myScore += 100
// Do logic to find out if we get an extra life.
// Is this done in a method and if so where does this method live?
// Or is it straight up code which will be duplicated?
Code like this which helps manage global game state is all neatly contained within the GameManager. In other words, the GameManager doesn't just maintain values, but it also provides a way of encapsulating functionality around those values.
Hmm, it seems the currentScene is also here? Why would that be? The GameManager would also be an excellent way to manage the changing of the scenes. More likely done through the game state. Maybe something like:
GameManager.sharedInstance.gameState = GameOverState
Behind the scenes, the gameState setter can then do the magic of swapping out scenes.
These are but a few examples of the practical nature of this approach.
Regarding the talk of loading/storing, this is can also be done through the GameManager if desired. Although for myself, I typically treat it independently based on some data within the GameManager. And this brings up another distinction. I would typically encapsulate ideas within the GameManager. For example, I would probably have a Player and that would make GameManager look like this:
class GameManager : NSObject {
// Overall game state, GameState is probably some enum
var state:GameState
var lastState:GameState
// Sometimes tracking scenes is useful
var currentScene:SKScene?
var nextScene:SKScene? // Sometimes helpful if you need to construct the next scene and it takes a non-trivial amount of time
// These are the globals we need to share to different "parts" of the game
// Note player state is done through this object. This way I can pass around only player when needed.
var player: Player
var stage: Uint
var highscores:[Uint] // A list of all the high score for the user. You would probably want HS based on other users too
// Egads a singleton!
static let sharedInstance = GameManager()
}
Wait you say; "But I don't like this global/singleton jazz. Why don't I just pass this object through to everyone that needs it." The answer is "you can". But in practice, you'll start to find this becomes tedious. You also may find that you discover you need the GameManager, but the caller never had the GameManager passed to it. This means now you're reworking a few methods to pass this object through.
Soooo are globals/singletons evil? You can be your own judge for it. Everyone will have there solution of choice. And if it works for you, use it. For me, it's a no brainer. The benefits of using it for consistent ease of use in accessing/managing global game state across your implementation make it an obvious choice.
So I'm adding a little more info here for an already long answer to
try clarify a few things.
My choice of singleton or global would be on usage, platform, and language. It is also dependent upon the game code base as well. It is not meant to be a dumping ground of just any data. If utilized, the contents should be carefully considered and when possible, use other containers for the contents (ie. wrap them in classes). So while my first example had player information dangling out (done to more easily convey the idea), in reality I would have PlayerState contain player data. Note this may not be the player in it's entirety, but perhaps some shared info that needs to live beyond the in-game life of the player.
class PlayerState {
var score:Uint
var highscore:Uint
var lives:Uint
}
// Simplified GameManager
class GameManager {
var state:GameState
var lastState:GameState
var player:PlayerState
// Egads a singleton!
static let sharedInstance = GameManager()
}
Additionally, I would end up passing around the PlayerState instance versus expecting code to always grab it through the global/singleton.
So for example I would do this:
func doSomething(playerState:PlayerState) {
var score = playerState.score
// Blah blah blah
}
verus
func doSomething() {
// Whee I have singleton
var score = GameManager.player.score
// Blah blah blah
}
Effectively what I'm doing is using the singleton as anchor points to access data objects more easily and then if needed, pass it around. In other words, While they are being employed, I also do not want my code riddled with GameManager.sharedInstance.
As mentioned, there are certainly a bunch of cons to this approach. One of which is concurrency. However, I will point out that concurrency still can occur with data even if it is not in a global/singleton.
My point of this addition is that game dev (and coding in general) involves a degree of practicality. Not only are you doing a balancing act with the system resources to present your game, but presumably you're making the game for people to play it. And for that to happen you need to get it done. Everyone wants to make a perfect snowflake, but what is the timecost for that perfection? At the start of the answer I indicated this technique is a tool. Globals/singletons won't be for everyone. At the same time, one should also not just blindly follow design mantras. If it can be an effective tool for you and help you finish your game faster, then its worthwhile doing. There will always be another game to write and you can then decide based on experience what worked and what did not.
General rule of thumb: If you can avoid global variables, do so.
Now every node has a mutable dictionary called userData. This is designed to be used to save data to a node.
Upon creation of your new scene, transfer whatever data you need from the old scene.
let scene = SKScene(fileNamed:....)
scene.userData["highscore"] = self.highscore
view.presentScene(scene)
Now in the new scenes didMove(view:) method, you read from said userData
As 0x141E has pointed out, remember you need to initialize userData, since chances are you have a custom class, you could do this in your init methods, just remember to override all designated inits so that you have access to the convenience methods.
Also, as mentioned in the comments between Whirlwind and myself, SKNode is NSCoding compliant, so when you go and save your information, you can save the SKNode as a whole and userData will go along with it.
This means all you would have to do is write an extension for SKNode to save/load the node, and this avoids having to worry about managing another class.
During the execution of a game many things could happen, a game have a crash, the player close the app, internet stops, a node could be paused from a parent (so it will be skipped when a scene processes actions). For this reason I agree with Simone Pistecchia comments: you could prepare a "storage manager" class to load and save to file your player stats, use NSCoding to declare and initialize them, use a Shared Instance class to handle them across the project. With this way you could load and save your vars when you need and show them also out of the game (to your main menu for a "High Scores" scene for example of wherever you want)

How can I organize my code to optionally provide a backing view for my logic layer?

I'm a bit sceptic wether this belongs to stackoverflow or not, please let me know if I should post to codereview or programmers instead.
I want to write a reusable component for iOS that does something like this:
Accepts a number as an input, let's call it inputNumber
Records audio for 10 seconds or until the user stops recording
During recording shows live metering
After the recording, checks the recording using the provided inputNumber (we don't really care about this part at the moment)
Allows the user to play the recorded audio
Returns a path to the recorded file
Returns YES or NO based on the check of step 4
The GUI is pretty simple, just two buttons (play/pause and record/stop) together with a view for showing the audio metering during recording.
Something like this:
Now, I have implemented all the logic I need in a singleton "manager" class and what I want to do is also provide the GUI. That means that the consumers will not care about enabling/disabling buttons, showing/hiding the meter etc.
I would like for others to be able to keep using this "manager" (and probably it will be refactored to stop being a singleton), but at the same time I would like to give the option to use it as a "drop in" view.
So, this is a question of how can I setup the whole architecture.
Right now my manager has only one method:
typedef void(^CompletionBlock)(BOOL isValid, NSString* filePath, NSError *error);
-(void)evaluateRecordingForInputNumber:(NSNumber *)inputNumber completion:(CompletionBlock)completionBlock;
and this works as I want.
But if I introduce a view, how should my API look? It doesn't seem correct to me to write a custom UIView -init that will take the role of the aforementioned method, since ideally I would like to reuse this view for different model classes (providing the inputNumber) that need to be evaluated.
How can I choose between subclassing NSObject, UIControl or UIView in my case? Is there a nice way to use both my "engine" as a standalone component and also optionally provide a backing view layer?
I think this coupling is largely dependent on how you envision the custom view/manager being used.
Will it be a lot of logic that people can use without the view, and the view is just an optional feature? If so it likely makes sense to subclass NSObject and prove the view as a property of the manager itself. That way people can use your manager class as a standalone, and in UIView's where it's needed they can do something like the following:
[self.view addSubview:myCustomManager.audioView];
On the other hand if the manager class has no value to your user without the UIView itself then I think it makes a lot of sense to subclass UIView, and hide your manager class behind that UIView. One example of a widget that uses this style of implementation is stripe: Stripe iOS Widget. Everything is based off of their 'STPView', like retrieving a charge token:
[self.stripeView createToken:^(STPToken *token, NSError *error) {
if (error) {
// Handle error
// [self handleError:error];
} else {
// Send off token to your server
// [self handleToken:token];
}
}];}
One can imagine a private 'manager' class behind the scenes of the stripeView doing all the work (this method is in addition to their delegate callback).
In your case this might be a fairly good pattern. You can add a property to the custom view for the number to be evaluated, add the view to the hierarchy, and then create a custom delegate that calls back automatically after it processes things; which would take the place of your manager class callback.
The final answer is that it depends a lot on how much of split between business logic and UIView treats this will provide. As long as the code is readable, maintainable, and you have some reasonable pattern to follow I don't think anyone is going to nail you to a cross in iOS land.

iOS - Clarifying class and instance methods

I just want to make sure I'm using class methods correctly.
By way of example, let's say I'm creating a game that involves a single map and individual tiles on that map (for instance, 16 x 16 tiles).
Each tile can consist of either a building, tree, road, etc - and this can change throughout the game.
Would I be correct in setting up a Map class with a class method to initialise the map, simply because there will only be one map and I would have no need to instantiate more than one?
Would I also be correct in setting up a Tile class with instance methods to initialise the tiles, because there would be 256 tiles each with their own properties?
Struggling to get my head around it all, any advice would be greatly appreciated.
There are multiple patterns for dealing with this, but basically it boils down to the Map class being a singleton. Some prefer to enforce the singleton-ness of the class by disallowing the creation of multiple instances (for example, by hiding the constructor, or making the constructor throw an exception, etc). In other cases it just suffices to document the Map class as being a singleton and use it as such.
A simple way of dealing with singletons in Objective-C is to create a class method for instantiating it, i.e.:
static Map* defaultMap = nil;
+ (Map*) defaultMap {
if(!defaultMap) defaultMap = [[Map alloc] init];
return defaultMap;
}
Using class methods for the map is probably not such a good idea, just like global variables is something that should usually be reduced to a minimum (though the example above is really a global variable, it will be a lot easier to refactor your code once you have a need for multiple maps).
Map class can be implemented as singleton pattern. Or any other way that limits it to only 1 shared instance.

Need some advice on object oriented design for an iOS project

I have a few questions about code design. This might be long. I'll shorten it whereever possible.
Q1) Dependant or Independant?
Creating a class and adding required functionality so as to allow the object to change its own state vs state being changed by a controller (aka viewcontroller)
I find code examples are best when trying to communicate:
Note: I reduced some lines of code. Original code from http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming.
Anyways if I had to set the Account balance for an account it is suggesting I do this:
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
// Implementation Section Starts Here
#implementation BankAccount
-(void) setAccountBalance: (double) x
{
accountBalance = x;
}
-(double) getAccountBalance
{
return accountBalance;
}
#end
//usage
BankAccount *account1 = [BankAccount alloc] init];
[account1 setAccountBalance: 1500.53];
----HOWEVER I believe I would have wrote it in a controller like this:------
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
import "BankAccount.h"
#interface MeViewController : UIViewController
-(void)setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc;
#end
#implementation myViewController
-(void) setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc
{
tempBankAcc.accountBalance = x;
}
//USAGE
BankAccount *account1 = [BankAccount alloc] init];
[self setAccountBalance(Account1,1500.53)]
#end
because I believe it is Me (meViewController) setting the AccountBalance, not the account itself as an account is just an account.
Is this a very bad idea? I can see with their example that the object can look after itself (independent) meaning changing its own state whereas my approach says that the BankAccount can only be modified through/with the controller (dependant)
???
Q2) What should/should not be in a controller?
I have also read somewhere that code written inside the controller should be only for:
Responding to user interaction & Updating the views
so does this means I should never do the following in the controllers:
READ or WRITE to and from NSUserDefaults. Since its a singleton, I thought it would be easier to write to it regardless of which controller is currently active? bad idea?
I understand that I should save data (includes NSUserDefaults) in applicationDidEnterBackground and in applicationWillTerminate so does that its a bad idea to save elsewhere (eg. in another controller).
Q3) Which design patterns do you most commonly use and which ones do you abuse wrongly?
Singletons:
My understanding is that [UIApplication sharedApplication],[NSNotification defaultCenter] and other singletons are accessible via all controllers, how about NSObject subclasses? or UIView subclasses?
And apparently you can use NSNotification to notify other controllers when the model has been updated.
Can someone tell me an example of when to use and how to use that?
Maybe when you import some data, that has different attributes, than was originally intended, then the observers could be notified of an upgraded data model, is that an example of when you would within your data model notify a controller?
Thats enough questions for now.
Sorry but I had to get them all out of my head:-)
Ben
First things first: don't use this
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
Here, the accountBalance ivar is public, while it should be private.
Instead, use a #property:
#interface BankAccount: NSObject
#property (assign, nonatomic) double accountBalance;
#end
That'll define a setter:
- (void)setAccountBalance:(double)accountBalance { ... }
and a getter:
- (double)accountBalance { ... }
and a private instance variable (ivar) named _accountBalance.
You can then, in your implementation, use:
#synthesize accountBalance;
which will automatically create the setter/getter like this:
- (void)setAccountBalance:(double)accountBalance {
_accountBalance = accountBalance;
}
- (double)accountBalance {
return _accountBalance;
}
Q1
If you take away all the business logic from the object itself, it's nothing more than a shallow container object. Further more, you need to replicate that logic in every controller you use. Business logic goes into business objects.
To your concrete example, the method of the controller does nothing but delegates the call down to the very object itself (infact, calling the same method if you use properties here). So you gained nothing at all. It may be fine to have that method in the controller, if the controller does more than just calling down on the object, maybe update some more data. One of the good hints here is that the controller does not use any of its own instance variables. It could easily be a class method. It's a code smell.
Q2
Basically, you have three choices for accessing NSUserDefaults: application level, view controller level, or view level.
Worst case is view level - a view should work in any context and should be configurable any way you like, and it certainly should not depend on some magic outside things. This would make reusability (not only for other apps, but also within the same app) a pain.
Accessing the defaults on the view controller level is often ok, especially if they take some singleton role. I.e. if you only ever have one playing screen and one setting screen, each of them might easily talk to the defaults. If there's the chance that you may have several instances of the same class differently configured, this gets a pain and bad smelling work arounds to "individualize" those.
This is where you want to place the access of the defaults outside of the view controllers, which is the most elegant and flexible approcach, but sometimes just not necessary.
Reusability may come earlier than expected, i.e. opening up a second text editor window (which might or might not show a different font), a second settings screen (i.e. a popover), a second playing screen for board games, etc.
Q3
I don't think Singletons are bad per se. They do come with a hefty price tag, though. They come convenient at early stages, just like global variables do.
They get very expensive, soon. There's no ownership, everything is shared, no chance to change a single bit without effecting the other users of that object. Reusability for objects depending on singletons is poor, as you always need those singletons as well. I tend to avoid them most of the time. And whenever I had one of them in my code, getting rid of them was a good decision.
As for the notifications: they are really designed for communicating on a system level. They shouldn't be abused for normal application logic and communication. It's a broadcast for system level events. If you use them as a substitute for object communication, this is a sure way to hell. This takes every logic out of the code, and there's no way build up responsible code.
Q1) Model-layer objects, especially ones that will be interacted with and mutated, should be responsible for their own internal representation as well as representing the knowledge of the rules of the interactions. For a bank account, I think both the approaches you present are wrong. The second in particular because it is actually taking even the responsibility of updating the state away from the account. But the first also because it only provides a setBalance method, which doesn't make sense in the real world. Whoever uses that account has to now handle all the logic of transfers, withdrawals, deposits, interest, and so on. Really, a bank account should have the methods deposit withdraw balance and so on, that way it can represent the rules and logic by which these interactions happen. In this case drawing from how this would work in real life can be helpful.
Q2) A lot of this depends on how your app is set up. A simple app's model layer may be just a plist or NSUserDefaults and some NSDictionary instances. In that case you might not want to have a view controller interact with it, but maybe a data controller object. But you can probably get away with having view controllers talk to that kind of model. When things get more complex though, you definitely need to separate concerns, and have controller objects closer to the data model or have more sophisticated models providing the rules of their interactions. Personally I'd avoid having all the view controllers loading NSUserDefaults, you could just make a single data controller class that could handle that and instantiate it as needed.
Q3) I see two questions here. Not sure what you mean by "accessible to all controllers". But NSNotification is incredibly useful when used right. Say you have 3 view controllers, all coordinating a different view of the bank account - one is a ledger, one is a pie chart, one is a budget calculator. When the app makes a request to refresh the bank account's information from the internet, when that request comes back it can notify all three of these view controllers at once and they can refresh their views accordingly. It's really used any time you have more than one object interested in knowing that something happened.
Hope this helps and let me know if you have any questions.
Read Stanford's lecture about MVC. I think you will find many answers there http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/205

Keeping Score in XNA Game

I'm following an XNA tutorial and have the following code for collision detecting (detecting when a bullet collides with a target). Basically I'm looking to increment a score variable to display the score to the screen without re-writing the whole program. No matter where I place it in this method it seems to start incrementing from the number of targets, not from zero. Is there something simple I'm missing here? Any help would be greatly appreciated. Thanks.
private CollisionType CheckCollision(BoundingSphere sphere)
{
if (completeCityBox.Contains(sphere) != ContainmentType.Contains)
return CollisionType.Boundary;
for (int i = 0; i < targetList.Count; i++)
{
if (targetList[i].Contains(sphere) != ContainmentType.Disjoint)
{
targetList.RemoveAt(i);
i--;
AddTargets();
return CollisionType.Target;
}
}
return CollisionType.None;
}
You could simply have a separate method called OnCollision() that updates the score (and could perform any physics for you if you wanted later on) and in your Update method, just have an if statement checking for collisions. Something like:
if( CheckCollision() == CollisionType.Target )
{
OnCollision();
}
Hope that helps.
Ray
Assuming you're not incrementing / assigning the score variable anywhere else, and it's set to zero during initialization, the only other thing I can think of is that somehow you're triggering a collision with all of your objects - is that possible somehow, perhaps during the setup phase? Have you tried setting a breakpoint on your score increment line to see when it gets hit?
if you are initialing it at the top of your class, and only incrementing it in the second if statement it sounds like the collision has to be happening with all items the first time.
without the rest of the code it might be hard to determine but for example in the AddTargets function if they start with the same location, and then are adjusted it could be possible that when this collision is checked they all qualified, or something of that nature.
As stated above, either set a break point when you update the score - if needed update it via a property and set a break point on the property so you can see where its being called and track back why it is being called. If its going from 0 to 250 before you actually have what you expect to be a collision, it should be easy to track down where the counter is being updated incorrectly, as it sounds its happening before what you expect to be your first collision and thus adding the first 250 points.

Resources