Keeping Score in XNA Game - xna

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.

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)

Run once inside update loop inside a update loop

So, basically I am making a game that includes land mines, which I want to have them release a red shockwave whenever the player gets close. The only problem is since the code looks like this:
loop {
if (<...Player inside radius...>) {
spawnShockwave();
}
}
//This is simplified
Each time the player gets near one of the mines, an large number of shockwave images get created (Once every time the loop is run.) How can I get it so that only shockwave gets created per mine.
The game is being written in SpriteKit, and the mines are there own class , however, I have to enumerate each object as an SKNode. Which sucks because that means I can't use custom properties that an SKNode doesn't have.
If anyone has a solution please help.
(Application written in swift)

Understanding ReactiveCocoa and MVVM in my ReactiveCocoa test project

I've written a very simple ReactiveCocoa test application to try my hand at coding in RAC (rather than just reading about it endlessly). It's on Github, and I wanted to get some specific questions about it answered. I'll link to the code components as I go along.
First, a brief explanation of the application: it's a timer-driven iteration counter that can be paused by the user. (Its purpose is to count how many seconds have elapsed, eliding the ones where the user paused it.) Once a second, a timer increments a variable iff the user hasn't paused the incrementing behaviour.
There are three classes I'm concerned about hearing feedback for:
MPSTicker (.m), which performs "accumulate since initialization unless paused" and provides that result on a signal. It has a public BOOL property to control whether or not accumulation is running.
MPSViewModel (.m), which provides a ViewModel wrapping from MPSTicker to the view controller. It provides read-only strings which show the number of ticks and show the text for the action which, if taken, "pauses" or "resumes" ticks. It also has a read-write BOOL for pausing/unpausing ticks.
MPSViewController (.m), which consumes strings from MPSViewModel by binding a label to the ViewModel's tick string, binding a button's text to the "tick action" string, and mapping a button's press into the ViewModel's paused property.
My questions:
I don't like the BOOL property on MPSTicker for enabling/disabling its accumulation, but I didn't know how to do it more Reactive-ly. (This also runs downstream to the ViewModel and ViewController: how can I run a string through all three of these to control whether or not the ticker is running?)
The ViewModel exposes tickString and tickStateString as very traditional properties, but the ViewController which consumes these immediately maps them back into text on a label and button text with RACObserve. This feels wrong, but I don't know how to expose a signal from the ViewModel that's easy for the ViewController to consume for these two attributes.
The ViewController suffers an indignity when flipping the paused BOOL on the ViewModel. I think this is another downstream effect of #1, "This shouldn't be a BOOL property", but I'm not sure
(Notes: I think I shied away from a signal for the BOOL of paused on MPSTicker because I didn't know how to consume it in the ViewModel to derive two strings (one for the current tick count, and one for the action text), nor how to push UI-driven value changes when the user pushes the "pause" or "resume" button. This is my core concern in questions 1 and 3.)
Some screenshots to help you visualize this gorgeous design:
Ticking:
Paused:
This is such an awesome write-up!
I don't like the BOOL property on MPSTicker for enabling/disabling its accumulation, but I didn't know how to do it more Reactive-ly. (This also runs downstream to the ViewModel and ViewController: how can I run a string through all three of these to control whether or not the ticker is running?)
Broadly, there's nothing wrong or non-Reactive about using properties. KVO-able properties can be thought of as behaviors in the academic FRP sense: they're signals which have a value at all points in their lifetime. In fact, in Objective-C properties can be even better than signals because they preserve type information that we'd otherwise lose by wrapping it in a RACSignal.
So there's nothing wrong with using KVO-able properties if it's the right tool for the job. Just tilt your head, squint a bit, and they look like signals.
Whether something should be a property or RACSignal is more about the semantics you're trying to capture. Do you need the properties (ha!) of a property, or do you care more about the general idea of a value changing over time?
In the specific case of MPSTicker, I'd argue the transitions of accumulateEnabled are really the thing you care about.
So if MPSTicker had a accumulationEnabledSignal property, we'd do something like:
_accumulateSignal = [[[[RACSignal
combineLatest:#[ _tickSignal, self.accumulationEnabledSignal ]]
filter:^(RACTuple *t) {
NSNumber *enabled = t[1];
return enabled.boolValue;
}]
reduceEach:^(NSNumber *tick, NSNumber *enabled) {
return tick;
}]
scanWithStart:#(0) reduce:^id(NSNumber *previous, id next) {
// On each tick, we add one to the previous value of the accumulate signal.
return #(previous.unsignedIntegerValue + 1);
}];
We're combining both the tick and the enabledness, since it's the transitions of both that drive our logic.
(FWIW, RACCommand is similar and uses an enabled signal: https://github.com/ReactiveCocoa/ReactiveCocoa/blob/9503c6ef7f2f327f4db6440ddfbc4ee09b86857f/ReactiveCocoaFramework/ReactiveCocoa/RACCommand.h#L95.)
The ViewModel exposes tickString and tickStateString as very traditional properties, but the ViewController which consumes these immediately maps them back into text on a label and button text with RACObserve. This feels wrong, but I don't know how to expose a signal from the ViewModel that's easy for the ViewController to consume for these two attributes.
I may be missing your point here, but I think what you've described is fine. This goes back to the above point about the relationship between properties and signals.
With RAC and MVVM, a lot of the code is simply threading data through to other parts of the app, transforming it as needed in its particular context. It's about the flow of data through the app. It's boring—almost mechanical—but that's kinda the point. The less we have to re-invent or handle in an ah hoc way, the better.
FWIW, I'd change the implementation slightly:
RAC(self, tickString) = [[[[_ticker
accumulateSignal]
deliverOn:[RACScheduler mainThreadScheduler]]
// Start with 0.
startWith:#(0)]
map:^(NSNumber *tick) {
// Unpack the value and format our string for the UI.
NSUInteger count = tick.unsignedIntegerValue;
return [NSString stringWithFormat:#"%i tick%# since launch", count, (count != 1 ? #"s" : #"")];
}];
That way we're more explicitly defining the relationship of tickString to some transformation of ticker (and we can avoid doing the strong/weak self dance).
The ViewController suffers an indignity when flipping the paused BOOL on the ViewModel. I think this is another downstream effect of #1, "This shouldn't be a BOOL property", but I'm not sure
I'm probably just missing it due to tiredness, but what's the indignity you have in mind here?

Is there a good way to prevent recursion of a particular bit of code in Objective-C?

Here is what I'm currently doing for a looping scroll-view:
// Call the on-scroll block
static BOOL inOnScrollBlock = NO;
if((_onScrollBlock != nil) && !inOnScrollBlock)
{
inOnScrollBlock = YES;
_onScrollBlock(self, self.loopOffset);
inOnScrollBlock = NO;
}
This is in the setContentOffset for the looping scroll view. So the user can run code whenever it scrolls. If you set up two of these and you want them to track each other, so for both you supply a block that sets the other then you can get a recursive situation where they keep calling each other.
Actually in this case it's not too bad as there's a separate check to see if the value being set is already set before doing all the more advanced stuff, but because it's a looping view there are multiple equivalent values so it can happen a few times.
Anyway, the question is about preventing recursion in this kind of situation. Given that this is a UI method and therefore only called on the main thread, is my approach of a simple flag to catch when you're being called from within the block a reasonable one, or not?
Are there any language features or framework patterns (available in iOS) to do this - similar to #synchronized or dispatch_once but to prevent recursion of a particular code section?
I wouldn't use a static BOOL as a static is implemented at class level. What if you had two instances of this class? They would be shooting each other in the foot! At the very least, use an instance variable (i.e. a property, and don't declare it nonatomic either, just in case).

nextLevel Method

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!

Resources