Draw filled dynamic polygon in Cocos2D, iOS - objective-c

How can i draw polygon with points read from NSMutableArray object in cocos2D framework?
I am able to draw polygon using this function: filled antialiased poly cocos2d
The problem is becouse points argument *(CGPoint poli) must be static object.
Any ideas or suggestions?

What is type of NSMutableArray objects?
You need to extract raw data of points and set it as poli argument.
If it's NSValue with CGPoint then:
NSMutableArray* yourPointsArray;
...
CGPoint* poli = malloc (sizeof (CGPoint) * [yourPointsArray count]);
for (uint i=0; i<[yourPointsArray count]; i++)
{
poli[i] = [[yourPointsArray objectAtIndex: i] CGPointValue];
}
ccFillPoly (poli, [yourPointsArray count], YES);
free (poly);

Related

Most efficient way to draw lines from array of points in cocos2d

Given an NSMutableArray of dynamic CGPoints, what is the fastest and most efficient way to draw lines from array[0] to array[1], array[1] to array[2], etc.? Should I rewrite my function in C or C++ for better performance? Currently my framerate suffers dramatically when there are more than ~20 points in the array. I am using cocos2d v2.0.0-rc2 and I currently have:
-(void)draw
{
for (int i = 0; i < [points count]; i+=2)
{
CGPoint startFromArray = [[points objectAtIndex:i] CGPointValue];
CGPoint endFromArray = [[points objectAtIndex:i+1] CGPointValue];
ccDrawLine(startFromArray, endFromArray);
}
[super draw];
}
There's no need to use iteration here. Cocos2d has a built-in function called ccDrawPoly(). You can use it like this:
CGPoint *verts = malloc(sizeof(CGPoint) * [points count]);
for (int i = 0; i < [points count]; i++) {
verts[i] = [[points objectAtIndex:i] CGPointValue];
}
ccDrawPoly(verts, [points count], NO);
free(verts);
Obviously, you'll get even better performance if you store your CGPoints in a C array instead of boxing and unboxing them from NSValues, but if you really need the mutability, that can't be helped.
As for the third argument of ccDrawPoly(), setting it to YES will connect the start and end points of the array, making a closed polygon, while using NO will just make a bunch of open lines.

Sort Array of CGPoints

I am trying to figure out what the fastest/cleanest way to sort an array of CGPoints would be. I think I could achieve this using loops but that might not be the fastest and I hope it isn't the cleanest way. I would like to take an array of random CGPoints and sort them say by smallest x coordinate to largest, or smallest x and y coordinate to largest.
After the correct comment by Chuck, I've updated the answer using the sortUsingComparator method:
Here is the complete code with sample data:
First we generate 100 random values that we enter to the Array:
NSMutableArray *testArray = [[NSMutableArray alloc] initWithCapacity:100];
for (int i=0; i<100; i++) {
CGPoint testPoint = CGPointMake(arc4random()%100, arc4random()%100);
[testArray addObject:[NSValue valueWithCGPoint:testPoint]];
}
and here is the actual code to sort the array:
[testArray sortUsingComparator:^(id firstObject, id secondObject) {
CGPoint firstPoint = [firstObject CGPointValue];
CGPoint secondPoint = [secondObject CGPointValue];
return firstPoint.x>secondPoint.x;
}];
finally we can verify that the array was sorted, by printing it:
NSLog(#"%#",testArray);
The C qsort() function is probably your best bet if you just have a plain array of CGPoints. Something like this:
int compareXCoords(CGPoint *a, CGPoint *b) {
return b->x - a->x;
}
// Later:
CGPoint points[100];
// initialize points somehow
qsort(points, 100, sizeof(CGPoint), compareXCoords);
// points is now sorted by the points' x coordinates
According to my comment, it's a good solution insert them on a NSMutableArray keeping the sort you decide.
You have to do something like this:
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
CGPoint candidate;
// Look for the position it has to be
int 0;
for (CGPoint point in array) {
i++;
// Compare candidate with current point
// You have to define this condition, when point is greater than candidate
if (point > candidate) {
break;
}
}
[array insertObjectAtIndex:i-1];
Maybe my code has some errors, I can't check if it's correct now.

Copy NSMutableArray into array of floats for GLES rendering

I have an NSMutableArray called mVerticies stored as a member of my class and I'd like to place them into a float array to draw them with glVertexAttribPointer.
Normally when drawing, I would have something like:
float verticies[] = {-1, -1, 1, -1};
// ... prepare to draw
glVertexAttribPointer(GLKVertexAttribPosition,
2, GL_FLOAT, GL_FALSE, 0, verticies);
// ... draw
But in order to use the glVertexAttribPointer function, i need a float[]. The verticies are stored as an NSMutableArray because they change quite often. Is there an easy way to either store a dynamic float[] as a member or to quickly convert an NSMutableArray to a float[]?
Assuming the values are stored as NSNumbers, you can do something like this:
float *floatsArray = malloc([numbersArray count] * sizeof(float));
if (floatsArray == NULL) {
// handle error
}
[numbersArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) {
floatsArray[idx] = [number floatValue];
}];
// use floatsArray
free(floatsArray);
You need to use malloc if you just want a raw chunk memory to read and write values directly.
If you have an NSArray array containing NSNumber instances:
float *vertices = malloc(sizeof(float) * [array count]);
for (int i = 0; i < [array count]; i++) {
vertices[i] = [[array objectAtIndex:i] floatValue];
}
// draw cool 3D objects and stuff
glVertexAttribPointer(....)
// then, when you're totally done with the memory
free(vertices);
Unlike Objective-C objects, the vertices pointer doesn't have a retain count, so you need to free it yourself, and keep track of when you can free it, because when you call free it will be gone immediately.
Just loop through the values. Assuming your floats are stored as NSNumbers:
NSUInteger count = [mutableVerticesArray count];
float vertices[count];
for (NSUInteger i = 0; i < count; i++) {
vertices[i] = [[mutableVerticesArray objectAtIndex:i] floatValue];
}
// Drawing etc.

Using CGPoints in an NSArray

I have been trying to create an array stating the location of a UIImageView in an app I've been working on. What I am trying to do is by using an array I can store the location of my "player" image by using its x,y and z coordinates. The script I am trying to accomplish would look like
NSArray *location[3];
-(IBAction)startup;{
[location addObject: player.center.x];
[location addObject: player.center.y];
[location addObject: playerheight];
}
So I will be able to access this array to move my "player" on the screen in "3-dimensions", but I don't know how to convert the CGpoint values to NSValues so they can be used in the array, is there a simple way to do this inside of the array?
To convert floating point values to objects, use NSNumber. NSValue has wrappers for geometric types like CGPoint. Either would work for you.
[NSValue valueWithCGPoint:player.center];
[NSNumber numberWithFloat:player.center.x];
[NSNumber numberWithFloat:player.center.y];
To addition for the first answer.
When you'll need to read CGPoint back from your array, you can use something like that:
CGPoint point = [(NSValue *)[pointsArray objectAtIndex:i] CGPointValue];
Also note that there's no addObject method for NSArray (you can't add objects to an NSArray after its been created); you want NSMutableArray.
Instead of:
NSArray *location[3];
you probably want something more like:
NSMutableArray *location = [NSMutableArray arrayWithCapacity:3];
Does it have to be an NSArray? Why not use an array of structs?
typedef struct {
CGPoint location;
CGFloat height;
} PlayerLocation;
PlayerLocation players[3];
players[0].location = player.center;
players[0].height = playerheight;
Or depending on your design it may make more sense to declare an objective-C class that contains the x,y,z coordinates as ivars and store those objects into an NSArray.
#interface PlayerLocation : NSObject {
CGPoint location;
CGFloat height;
}
#end

Create a re-sizable array of CGPoints in objective-c

I am trying to create a re-sizable array of CGPoints in objective-c. I've have looked into using NSMutableArray however it doesnt seem to allow resizing. Is there something else I can use?
thank you
Use an NSMutableArray, but just box your CGPoint structs in NSValue objects. Example:
CGPoint myPoint = {0,0};
CGPoint anotherPoint = {42, 69};
NSMutableArray * array = [NSMutableArray array];
[array addObject:[NSValue valueWithCGPoint:myPoint]];
[array addObject:[NSValue valueWithCGPoint:anotherPoint]];
CGPoint retrievedPoint = [[array objectAtIndex:0] CGPointValue];
Note that the +valueWithCGPoint: and CGPointValue methods are only available on the iPhone. However if you need this for the Mac, there are similar methods for dealing with NSPoints, and it's trivial to convert a CGPoint to an NSPoint (you can cast or use NSPointFromCGPoint()).
NSMutableArray is for objects. For plain old datatypes, use NSMutableData and good old pointer typecasts. It's a resizable unstructured memory buffer, just what you need for a vector of PODs. As for static type safety, Objective C does not give you any of that anyway.
EDIT:
Creating a mutable data object with an initial size n CGPoint structs:
NSMutableData *Data = [NSMutableData dataWithLength: n*sizeof(CGPoint)];
Placing a CGPoint pt into the buffer at the i-th position:
CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data replaceBytesInRange: r withBytes:&pt];
Retrieving a CGPoint from the i-th position into pt:
CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data getBytes: &pt range:r];
Growing the array by n objects:
[Data increaseLengthBy:n*sizeof(CGPoint)];
Hope that covers it. See the NSMutableData reference, and keep in mind that all NSData methods apply to it.