how to save the touched position of x and y values in a array - ios5

I'm working with the cocos2d 3.x and Xcode 5.1.1.i'm doing the game like a candy crush,here i load the sprites to 5*5 matrix,and i already get the position for the touched sprite,now i need to save and use that x,y value in a array like (0,0),(3,0),(2,2)

there are a few of ways to store coordinates, it is hard to tell which way would fit better for, regarding I don't know what you mean exactly when you say save...
options #1
CGPoint _coords = CGPointMake(x, y);
obvious choice to store them in a CGPoint struct, however the struct is designed to store fraction coordinates, but it can handle integer values as well.
you cannot insert a CGPoint directly into any collection type, like e.g. NSArray, NSSet or NSSDictionary, but you can store them in e.g. a fix-sized C-array, like:
CGPoint _fiveCoordinates[4];
option #2
NSString *_coordinates = [NSString stringWithFormat:#"%d %d", x, y];
that is a quick and ugly solution, I personally don't like it – however in certain cases is useful (vs. option #4!). it is also possible to store it any collection type, and you can extract the coordinates after, for further usage, like e.g.:
NSArray *_components = [_coordinates componentsSeparatedByString:#" "];
NSInteger x = [[_components firstObject] integerValue];
NSInteger y = [[_components lastObject] integerValue];
if you'd store the values in a simple NSArray like
NSArray *_coordinates = [NSArray arrayWithObjects:#(x), #(y)];
the extraction procedure would be the similar to the idea above.
option #3
NSDictionary *_coordinates = [NSDictionary dictionaryWithObjectsAndKeys:#(x), #"x", #(y), #"y"];
a simple dictionary can store them flawlessly, if you need to extract the values, it is like e.g.
NSInteger x = [[_coordinates valueForKey:#"x"] integerValue];
NSInteger y = [[_coordinates valueForKey:#"y"] integerValue];
option #4
NSIndexPath *_coordinates = [NSIndexPath indexPathForRow:y inSection:x];
if you like to work with index paths, that is a very straightforward way to store indices, because the NSIndexPath widely used and can be inserted directly into any collection type.
extracting the coordinates would be the same easy way:
NSInteger x = [_coordinates section];
NSInteger y = [_coordinates row];
option #5A
another obvious way would be that creating an own class to store those coordinates, like e.g.:
.h
#interface MyCoordinates : NSObject { }
#property (nonatomic) NSinteger x;
#property (nonatomic) NSinteger y;
#end
.m
#implementation MyCoordinates
#end
option #5B
and you can also extend it comforming the NSCoding protocol, if you want to get a pure serialisable object, which can be archived with the NSArray for permanent storing, like:
.h
#interface MyCoordinates : NSObject <NSCoding> { }
#property (nonatmic) NSInteger x;
#property (nonatmic) NSInteger y;
#end
.m
#implementation MyCoordinates
#pragma mark - <NSCoding>
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
_x = [[aDecoder decodeObjectForKey:#"x"] integerValue];
_y = [[aDecoder decodeObjectForKey:#"y"] IntegerValue];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:#(_x) forKey:#"x"];
[aCoder encodeObject:#(_y) forKey:#"y"];
}
#end
...or something similar, or you can combine them together as you'd feel which the most convenient way is in your personal view.

//SET
NSMutableArray* points = [[NSMutableArray alloc] initWithCapacity:10];
CGPoint pointToBeStored = CGPointMake(0,0);
[points addObject:[NSValue valueWithCGPoint:pointToBeStored]];
//GET
NSValue *value = [points objectAtIndex:index];
CGPoint storedPoint = [value CGPointValue];

Related

ordering NSString of NSArray in a particular order

I have a NSString in an NSArray and I wanted to order this string/fields based on how important it is. So say the string is B, H, A, Q, Z, L, M, O.
I wanted it to be always sorted as A, Q, Z, B, H, O, L, M. This is a predefined set of rule. How do I do this? Can this be done using NSSortDescriptor?
The short answer: Yes!
And here's how...
Since there are two pieces of information you need to know about your value (the importance and the value itself), you should create an object with these two important pieces of information, then store in an array similar to the way you store your strings. This makes it simple if, say, you want to change the 'importance' some time later with very little effort:
#interface MyObject : NSObject
#property (nonatomic, readwrite) NSInteger sortOrder;
#property (nonatomic, retain) NSString *value;
#end
#implementation MyObject
#synthesize sortOrder;
#synthesize value;
-(NSString *)description
{
//...so I can see the values in console should I NSLog() it
return [NSString stringWithFormat:#"sortOrder=%i, value=%#", self.sortOrder, self.value];
}
-(void)dealloc
{
self.value = nil;
[super dealloc];
}
#end
Add your objects to an array. Then sort:
NSMutableArray *myArrayOfObjects = [NSMutableArray array];
//Add your objects
MyObject *obj = [[[MyObject alloc] init] autorelease];
obj.sortOrder = 1;
obj.value = #"A";
[myArrayOfObjects addObject:obj];
obj = [[[MyObject alloc] init] autorelease];
obj.sortOrder = 2;
obj.value = #"Q";
[myArrayOfObjects addObject:obj];
//Sort the objects according to importance (sortOrder in this case)
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"sortOrder" ascending:YES] autorelease];
NSArray *sortedArray = [myArrayOfObjects sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSLog(sortedArray); //<--See for yourself that they are sorted
NSArray has several sort functions. Three you might consider are:
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr
- (NSArray *)sortedArrayUsingSelector:(SEL)comparator
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context
I think you might find the second, selector-based comparator the easiest to use to get started. See the docs here:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/sortedArrayUsingSelector:
EDIT:
I think using NSSortDescriptor may be overkill, but here is a good post describing it:
How to sort NSMutableArray using sortedArrayUsingDescriptors?

Sharing Struct Information Between Classes - Objective C - OpenGL ES

I have an OpenGL ES based app with the following structure :
I parse vertices from a DAE file which contains a number of objects (using NSXMLParser).
As I parse each set of vertices, I create an object (sceneObject) and set the vertices array in this object to match the parsed vertices. I am then planning to add these sceneObjects to array of objects to be rendered by OpenGL ES.
Initially I had taken an approach of using NSArrays to store the vertice data, however I understand that the OpenGL commands (such as glvertexpointer) do not accept NSObject values, bue instead need raw values (glfloats and gluints etc).
Rather than convert the NSObjects back to GL raw values within the object class, I am now trying to take a struct approach. This is the code where I parse the vertice information :
if (floatArray) {
if (currentlyParsing == kVerticeInformation) {
if (currentParserTagType == kGeometry) {
//NSLog(#"Loaded Vertices %#", string);
NSArray * nums = [string componentsSeparatedByString:#" "];
culmunativeCount += [nums count];
//NSLog(#"Culm Count is %d", culmunativeCount);
[fullParseString appendString : string];
if (checkSumCount <= culmunativeCount) {
//NSLog(#"Full Parse String is %#", fullParseString);
NSArray * finishedArray = [fullParseString componentsSeparatedByString:#" "];
//NSLog(#"Finihsed ARray is %d", [finishedArray count]);
[finishedParsingArray addObjectsFromArray:finishedArray];
//NSLog(#" FINISHED PARSING = %d", [finishedParsingArray count]);
NSUInteger baseIndex;
for (baseIndex=0; baseIndex <[finishedParsingArray count]; baseIndex +=3) {
NSString * xPoint = [finishedParsingArray objectAtIndex:baseIndex];
NSDecimalNumber * errorCheckX = [NSDecimalNumber decimalNumberWithString:xPoint];
float x = [errorCheckX floatValue];
NSString * yPoint = [finishedParsingArray objectAtIndex:baseIndex +1];
NSDecimalNumber * errorCheckY = [NSDecimalNumber decimalNumberWithString:yPoint];
float y = [errorCheckY floatValue];
NSString * zPoint = [finishedParsingArray objectAtIndex:baseIndex+2];
NSDecimalNumber * errorCheckZ = [NSDecimalNumber decimalNumberWithString:zPoint];
float z = [errorCheckZ floatValue];
Vertex3D vertexItem = {x,y,z}
//NSLog(#"Vertices stored are %f, %f, %f", x,y,z);
}
currentlyParsing = kNilSetting;
checkSumCount = 0;
[finishedParsingArray removeAllObjects];
//[finishedArray release];
culmunativeCount = 0;
[fullParseString setString:#""];
}
}
}
}
As you can see, I am now creating a Vertex3D C Struct each time with the parsed vertice information.
My questions are :
How would I then create an array of these individual C Vertex3D structs ?
How can I then pass this array of structs to my sceneObject ?
Create Objective C wrapper class for your array. It can hold several arrays (e.g. vertices, normals and tangents). You know the array size beforehand, so you can preallocate the required amount of space:
#interface MYVertexArray : NSObject {
float* _mVerts;
float* _mNormals;
int _mCount;
}
#property(nonatomic, readonly) float* verts;
#property(nonatomic, readonly) float* norms;
/**
Here you're allocating your arrays (don't forget to free them is dealloc).
*/
-(id) initWithSize:(int) size;
#end
and then in cycle, you're just doing this:
MYVertexArray* my_vertex_data = [[MYVertexArray alloc] initWithSize: [finishedParsingArray count]];
for(int i=0; i<[finishedParsingArray count]; ++i) {
my_vertex_data.verts[i] = [[finishedParsingArray objectAtIndex: i] floatValue];
}

Adding items from an NSDictionary to an NSMutableArray

I'm trying to make an implementation of a k-means clustering algorithm for map annotations using the iPhone MapKit. I've got 2 classes which implement MKAnnotation: PostLocationAnnotation for individual points and LocationGroupAnnotation for clusters of points. The header for LocationGroupAnnotation is as follows:
#interface LocationGroupAnnotation : NSObject <MKAnnotation>
{
NSMutableArray *_locations;
CLLocationCoordinate2D _coordinate;
}
#property (nonatomic, retain) NSArray *locations;
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
+ (LocationGroupAnnotation *)initWithLocations:(NSArray *)locationArray;
+ (LocationGroupAnnotation *)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
- (id)initWithLocations:(NSArray *)locationArray;
- (id)initWithCoordinate:(CLLocationCoordinate2D)startCoordinate;
- (void)addAnnotation:(PostLocationAnnotation *)annotation;
- (NSUInteger)locationCount;
#end
In my map view controller, I have a method to add all of the PostLocationAnnotations to LocationGroupAnnotations by creating k LocationGroupAnnotations (using the initWithCoordinate method) each with a location selected at random from the annotations, and adding PostLocationAnnotations to their nearest LocationGroupAnnotations. For this, I use an NSMutableArray of NSMutableDictionary objects, like so ('means' is an NSMutableArray of LocationGroupAnnotations which has been populated before this):
// find nearest cluster to each point
NSMutableArray *distances = [[NSMutableArray alloc] initWithCapacity:[[ffMapView annotations] count]];
for (id <MKAnnotation> point in [ffMapView annotations])
{
if ([point isKindOfClass:[PostLocationAnnotation class]])
{
NSMutableDictionary *distanceDict = [[NSMutableDictionary alloc] initWithCapacity:2];
[distanceDict setObject:point forKey:#"location"];
double minDistance = 0;
LocationGroupAnnotation *closestMean = nil;
for (id <MKAnnotation> meanPoint in means)
{
if ([meanPoint isKindOfClass:[LocationGroupAnnotation class]])
{
if (closestMean)
{
if ([ClusteringTools getDistanceBetweenPoint:[point coordinate] and:[meanPoint coordinate]] < minDistance)
{
closestMean = meanPoint;
minDistance = [ClusteringTools getDistanceBetweenPoint:[point coordinate] and:[meanPoint coordinate]];
}
} else {
closestMean = meanPoint;
minDistance = [ClusteringTools getDistanceBetweenPoint:[point coordinate] and:[meanPoint coordinate]];
}
}
}
[distanceDict setObject:closestMean forKey:#"closestMean"];
[distances addObject:distanceDict];
[distanceDict release];
}
}
// add annotations to clusters
for (NSDictionary *entry in distances)
{
[(LocationGroupAnnotation *)[entry objectForKey:#"closestMean"] addAnnotation:[entry objectForKey:#"location"]];
}
The problem I am having is when I output the locationCount of each LocationGroupAnnotation after this, I get 0 for each one. I have a log output for each time an annotation is added, like so (in LocationGroupAnnotation):
- (void)addAnnotation:(PostLocationAnnotation *)annotation
{
[_locations addObject:annotation];
NSLog(#"Added annotation at (%f,%f) to cluster %#",
[annotation coordinate].latitude,
[annotation coordinate].longitude,
[self description]);
}
...and it looks like everything is being added where it should, judging by the memory addresses. So what's going on?
Do you initialize _locations anywhere? It looks like you could be merrily adding objects to nil which would not cause any errors.
You haven't shown the code but you also have a property locations which is an NSArray and an instance variable _locations which is an NSMutableArray, are you doing anything clever with this in the background which could be messing things up? How are you linking those two properties together?

Sorting an NSMutableArray with custom objects 'overwrites' some objects

For a little iPhone application I am making, I want to sort a NSMutableArray.
I found 2 ways of doing this, but they both result in the same thing. Sorting the array will cause some objects to 'overwrite' eachother.
First off, here is my code:
AppDelegate.h
NSMutableArray* highScores;
Somewhere down that AppDelegate.h, I also make this variable a property so that I can access it from differen classes:
#property (retain, nonatomic) NSMutableArray* highScores;
When my application starts, I read the high scores from a file and import them into my NSMutableArray.
AppDelegate.m
NSMutableData* data = [NSData dataWithContentsOfFile:highScoresPath];
NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
self.highScores = [decoder decodeObjectForKey:#"highscoresArray"];
The objects I store in this NSMutableArray are from the type HighScore.
HighScore.h
#interface HighScore : NSObject {
int score;
int roundsPlayed;
int wrongAnswers;
NSString* name;
NSDate* datetime;
}
#property int score;
#property int roundsPlayed;
#property int wrongAnswers;
#property (nonatomic, copy) NSDate* datetime;
#property (nonatomic, copy) NSString* name;
- (id) init;
- (void) update:(int)roundScore:(BOOL) correct;
#end
HighScore.m
#import "HighScore.h"
#implementation HighScore
#synthesize score, roundsPlayed, wrongAnswers, name, datetime;
- (id) init
{
self.name = #"";
self.score = 0;
self.roundsPlayed = 0;
self.wrongAnswers = 0;
self.datetime = [NSDate date];
return self;
}
- (void) update:(int)roundScore:(BOOL) correct
{
self.score += roundScore;
if (!correct)
self.wrongAnswers++;
self.roundsPlayed++;
self.datetime = [NSDate date];
}
- (id) initWithCoder:(NSCoder *) decoder
{
self.name = [[decoder decodeObjectForKey:#"name"] retain];
self.score = [decoder decodeIntForKey:#"score"];
self.roundsPlayed = [decoder decodeIntForKey:#"roundsPlayed"];
self.wrongAnswers = [decoder decodeIntForKey:#"wrongAnswers"];
self.datetime = [[decoder decodeObjectForKey:#"datetime"] retain];
return self;
}
- (void) encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:self.name forKey:#"name"];
[encoder encodeInt:self.score forKey:#"score"];
[encoder encodeInt:self.roundsPlayed forKey:#"roundsPlayed"];
[encoder encodeInt:self.wrongAnswers forKey:#"wrongAnswers"];
[encoder encodeObject:self.datetime forKey:#"datetime"];
}
- (NSComparisonResult) compareHighscore:(HighScore*) h
{
return [[NSNumber numberWithInt:self.score] compare:[NSNumber numberWithInt:h.score]];
}
#end
Now, when I try to sort my array by using the following code:
NSArray *sortedArray;
sortedArray = [highScores sortedArrayUsingSelector:#selector(compareHighscore:)];
It somehow screws up my highScores array, I get an X amound of highscores with the same score and name.
What am I doing wrong?
I'm noticing that in your initWithCoder: method, you're not doing this:
if (self = [super initWithCoder:coder]) {
// Decode your stuff here
}
Same with your regular init method. There needs to be a call to [super init].
Also, since you defined your string properties as copy and you're using the property syntax, there's no need to retain them. They will be retained for you by the synthesized accessor.
Otherwise, your code looks fine to me. Just remember: every init method must always have a call to a super's init... method.
You're trying to sort using #selector(compare:), not #selector(compareHighscore:), which I presume was your intention.
try
sortedArray = [highScores sortedArrayUsingSelector:#selector( compareHighscore: )];
Post the actual compareHighscore: method. The most important thing is that it has to be consistent, that is if a <= b and b <= c, then a <= c and if a < b and b < c then a < c. If you managed to write a compare method that is not consistent, anything can happen.

Iphone Object C - Data,Objects and Arrays

So I'm a Flash guy and I'm trying to convert the following code to Object C:
var slot:Object = new Object();
slot.id = i;
slot.xPos = 25*i;
slot.yPos = 25*i;
slot.isEmpty = False;
// push object to array
arrGrid.push(slot);
Later I can override like:
arrGrid[0].isEmpty = True;
I can't seem to find a reference to creating generic objects in Object C. Can someone help?
Well assuming you are doing something with the iphone or mac in cocoa you can simply subclass NSObject (the base class in objective-c).
You need a .h and .m so for you example it would be something like:
(Note that I used slotId instead of id because id is a keyword in objective-c)
Slot.h
// Slot.h
#interface Slot : NSObject {
NSInteger slotId;
float xPos;
float yPos;
BOOL empty;
}
#property NSInteger slotId;
#property float xPos;
#property float yPos;
#property BOOL empty;
#end
// Slot.m
#import "Slot.h"
#implementation Slot
#synthesize slotId;
#synthesize xPos;
#synthesize yPos;
#synthesize empty;
#end
That defines a simple Slot object with 4 properties which can be accessed using dot notation such as:
s = [[Slot alloc] init];
s.empty = YES;
s.xPos = 1.0;
s.yPos = 1.0;
There are a lot of variations for which data types you use and how you define the properties, etc depending on what kind of data you are dealing with.
If you wanted to add a slot object to an array one simple example:
// create an array and add a slot object
NSMutableArray *arr = [NSMutableArray array];
Slot *slot = [[Slot alloc] init];
[arr addObject:slot];
// set the slot to empty
[[arr objectAtIndex:0] setEmpty:YES];
If you're only using this Object instance to store named values, you can use an instance of NSMutableDictionary instead, although you'll need to wrap your integer values with NSNumber instances:
NSMutableDictionary * obj = [NSMutableDictionary dictionary];
[obj setObject: [NSNumber numberWithInt: i] forKey: #"id"];
[obj setObject: [NSNumber numberWithInt: i*25] forKey: #"xPos"];
[obj setObject: [NSNumber numberWithInt: i*25] forKey: #"yPos"];
[obj setObject: [NSNumber numberWithBool: NO] forKey: #"isEmpty"];
Then you'd add these to an NSMutableArray allocated using [NSMutableArray array] or similar:
[array addObject: obj];
To get the integer/boolean values out of the dictionary, you'd do the following:
int i = [[obj objectForKey: #"id"] intValue];
BOOL isEmpty = [[obj objectForKey: #"isEmpty"] boolValue];