How to create multiple objects in SpriteKit which follow the same methods? - oop

I am currently creating a game and am working on creating multiple objects of the same type that each follow their classes methods separately. Eventually the goal is to have Object A be created in either the top left, or top right corner of the screen on a random interval and bounce off the left and right walls until they hit the bottom of the screen.
For testing purposes, I created a new 'Object A' each time the user touches the screen inside the touchesBegan method.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
objectA = [HHObjectA objectA];
[world addChild:objectA];
objectA.position = CGPointMake(world.scene.frame.size,width/12, world.scene.frame.size.height/3.2);
[objectA moveLeft];
}
Although indeed this does create a new 'Object A' each time the screen is pressed, in the location I specified; each 'Object A' is connected. If the first 'Object A' collides with the left wall, each 'Object A' will move right. If one 'Object A' gets stuck on another, the rest glitch. I thought potentially changing the name of the second 'Object A' might make each run separately, but this too had the same result as above. My next thought would be arrays, however I'm not sure how many Object A's I will be needed per level.
What would be the best way to achieve my desired goal?

Related

Transferring Touch points between classes [Objective-C]

I'm working on an alternate version of a program I already wrote, it's mostly for the sake of understanding a little more.
In x-Code (Objective-C), I have a ViewController that calls out a UIView (GraphicsView) that draws a line from the center to the touch point. This sub-view is smaller than the larger ViewController.
The view controller has a label that outputs the coordinates of the touched point.
So far I was able to get everything working, so that if you touch inside the sub-view you get the line AND the coordinates updated and if you touch outside the sub-view you only get the coordinates updated. I did this using delegates which was a little complicated.
I've been reading some books and I learned about using the extern feature and global variables (which are supposed to be bad practice) and I wanted to try the same app but using global variables.
I declared my externCGPoint in the ViewController.h and imported it on the GraphicsView.m file and in the method touches began I put the definition of myGlobalPoint = touchedpoint; followed by an NSLog that displays the coordinates. So far it works. (However it does not update the coordinates)
However whenever I touch outside the sub-view, into the main view the app crashes with a EXC_BAD_ACCESS message. From what I understand the main View cannot access the global variable if it's declared in another class ?
I've read many there stack overflows about this and I;ve tried it in the methods suggested but I keep getting this error.

How to compare the trackingArea of NSEvent to see which trackingArea triggered the "theEvent"

So, I have this mouseEntered event that will make visible a label if I mouse enter a trackingArea. But, depending on which trackingArea was entered I want to set a custom String to the label.
The main question is: How do I get which trackingArea was entered.
This is my code:
-(void)mouseEntered:(NSEvent *)theEvent
{
if([theEvent trackingArea] isEqual: -- to my trackingArea --)
{
[self.label setStringValue:#"Test"];
}
}
Sounds like the beginning of Spaghetti code to me..
I.e.: Checking in one view whether something was triggered by another view - I suppose you're attempting to implement some kind of online help system with some text to be displayed for various views/controls. In that case you might easily end up with a huge if-then-else block and dozens of views to check.
In any case I'd suggest to use a different approach and embrace loose coupling in your code:
How about having the view that actually owns the tracking area send a notification with the string it wants somebody else to display?
That way views don't need to know each other, no instance variables to set up to point to each other, etc. - just a notification somebody sends and somebody else will listen to.
Clean, maintainable, easily extensible.

Accessing CCSprite From Different Scene

So basically what I am trying to do is when the player of my game completes a level (for example level 1), it switches scenes back to the level select scene, and swaps the sprite picture of level 1 to a different one (for example one that has a check mark over it). I can replace the scene but I don't know how to change the sprite in the new scene, specifically when the scene change occurs after the level is completed. So I am assuming I would use a singleton class, am I right? If so, how would I go about using it?
Singletons are ok, don't be afraid to use them. Many components of cocos2d are singletons.
I think what you need is some sort of structure that keeps track of the state of the game. (How many levels are completed/What should be the next level/etc). When your level select scene is loaded it should look up that 'state of the game' object (be it a singleton, plist, etc ) and displays itself accordingly.
I would stay away from passing information directly from one scene to another, this makes reordering them a headache later on.
First, let me make sure I understand the problem correctly.
You have a scene (A) with a sprite in it.
You transition to another scene (B) for the game play.
The game ends and you transition back to scene A.
When scene A redisplays, you want to change the image displayed by the sprite.
If I've got this right, then regardless of whether singletons are good or bad, you don't need one for this.
If, like me, you've created your sprite using a display frame from the CCSpriteFrameCache, then you can simply change the frame you want the sprite to use when "A" is redisplayed.
Some sample code demonstrating this can be seen in another question:
How to switch the image of a CCSprite
(Certainly, if I've got this right, then feel free to just dupe this)

How do you find out what is retaining an object in Instruments?

I've recently converted my iOS project over to ARC. One of the view controllers is not calling its dealloc method and is not being dealloc'ed according to Instruments.
I've double checked all of my properties and set the appropriate ones to weak. I've also made sure that anything that has the view controller as a delegate has it unset on viewWillDisappear but the view still sticks around in memory.
I'm a newbie at Instruments: how can I tell what is retaining this view?
Well if you are really stuck and the program is complex (or abstracted, in the case of ARC), you can bring out the cannons:
Open your Xcode project
Choose the executable (if needed)
Press cmd+i (Profile)
Choose the 'Leaks' Instrument in Le Wizard (if needed)
Press Return to begin profiling
Exercise your app
Press 'Stop' in Instruments
Verify the 'Allocations' instrument is selected
Click and Hold the Popup Button named 'Statistics'
Select the Objects List item
Locate the allocation you are interested in, among the records in the Objects List
Select that allocation/object
Click the 'detail arrow' to the right of the address in the table view cell of that allocation
Now you see all events related to the allocation (allocation, free, reference count operations)
Press cmd+shift+e for Extended Detail
Go through the events in this list, and locate the imbalance you seek.

NSBrowser setRowHeight, not supported for browsers with matrix delegates

I have an NSBrowser and try to use setRowHeight, but I get the error:
"setRowHeight: is not supported for browsers with matrix delegates."
I really don't understand what this means, and if someone could help me out by either telling me how to fix it or even just what a matrix delegate is, it would be much appreciated.
A delegate is a helper object that you tell the NSBrowser instance about either by using -setDelegate: in code or hooking the delegate outlet up in IB (the NIB editor). It is commonly used to fill the browser's data, determine programmatically the layout options, etc.
If you have a delegate assigned in your NSBrowser instance, you are expected (required) to give the row height using the delegate method:
- (CGFloat)browser:(NSBrowser *)browser heightOfRow:(NSInteger)row inColumn:(NSInteger)columnIndex
Which will allow you to optionally set the row height on a per-row basis, but in your case, you can safely return a constant.
A NSBrowser creates one instance of NSMatrix per column. The browser itself only manages the columns and leaves row management entirely to the matrices. The matrices display cell objects (NSCell or subclasses of it). A cell is a simple displayable object that knows nothing but how to draw itself. Unlike a view (NSView and subclasses), it never manages an own drawing context, it also doesn't belong to a window (and thus won't ever directly access the window's drawing context) and it knows nothing about the "view hierarchy" (superviews, subviews, view order, constraints, etc.), it just manages some properties, some state and knows how to draw itself to a drawing context provided.
If your delegate works with items (the docs speak about "the item delegate methods"), the developers of NSBrowser thought it's unlikely that you ever want to deal with matrices directly, thus the browser will control all the display aspects for you. You are only supposed to hand out items (basically arbitrary objects) in your delegate and answer questions about them by implementing various delegate methods. E.g.: What is the root item? Is item x a leaf item or has children? How many children does it have? What's child number n of item x? What display object (string, image, etc.) shall I use to display that item?
If you don't work with items, you have to work directly with the cells (NSBrowserCell, a subclass of NSCell) that the matrix owns and is going to display. In that case you are said to be a "browser matrix delegate". That means the browser will only ask you how many rows a column has, setup a matrix with cells for you for that column and finally pass every cell once to your delegate, so you can do something meaningful with it, e.g. fill it with displayable content, otherwise the cell would just be empty, and teach it all the stuff the browser has to know (e.g. setting the leaf property).
As a matrix based delegate has to deal with cells directly, it can as well also deal with the matrices directly and in fact that his exactly what you have to do here. E.g. if you want that all rows of your browser have a height of 50 points, implement the following NSBrowser delegate method:
- (void)browser:(NSBrowser *)browser
didChangeLastColumn:(NSInteger)oldLastColumn
toColumn:(NSInteger)column
{
NSMatrix * matrix = [browser matrixInColumn:column];
CGSize cellSize = [matrix cellSize];
if (cellSize.height != 50) {
cellSize.height = 50;
matrix.cellSize = cellSize;
[matrix sizeToCells];
}
}
Every matrix created by the browser is passed to that method at least once before it gets displayed on screen. In case that matrix is not using a cell height of 50 already, we change that and finally tell the matrix to re-layout; that is important as otherwise it won't recalculate its total height. The if is only to avoid that we call sizeToCells more often than necessary as this call may be rather expensive. In this example all columns get equal row height but of course you can set a different row heights per column.