Spritekit Screen/Background Update - objective-c

Is it possible to get 2 positions from the same SKSpriteNode in the -(void)update:(CFTimeInterval)currentTime method?
I am making a demo. A ball is shot from a random point outside of the screen. I want to get the ball's direction and an array of positions so that I can do something based on it. But when I use the update: method, it seems that it fills the array in each update. How do I add only one SKSpriteNode to the array for each update?
NSMutableArray *nodePos;
int returnPosCount;
-(void)update:(CFTimeInterval)currentTime {
if ([self childNodeWithName:#"//ball"]!=nil){
returnPosCount++;
if (returnPosCount == 15) {
SKNode *node = [self childNodeWithName:#"//ball"];
[nodePos addObject:node];
if ([nodePos count]>4) {
[nodePos removeObjectAtIndex:0];
NSLog(#"%#",nodePos);
}
returnPosCount =0;
}
NSLOG:
<SKSpriteNode> name:'ball' (64 x 64)] position:{-127.63968658447266, 135.19813537597656}
<SKSpriteNode> name:'ball' (64 x 64)] position:{-127.63968658447266, 135.19813537597656}
<SKSpriteNode> name:'ball' (64 x 64)] position:{-127.63968658447266, 135.19813537597656}

You are not filling the array in each each update. You are seeing the array full, because you are only printing the data when it is full. Just move your NSLog outside the [nodePos count] condition.
Now the reason why you have the same value is because you are adding the node, instead of its position at each update. Since the node is a reference, you will have an array full of references to the same object, thus obtaining the same position. You should build an array of CGPoint instead of an array of SKNode.
To do so, try changing:
[nodePos addObject:node];
To
[nodePos addObject:node.position];

Related

Check if a physicsbody is touching another without waiting for didBeginContact

I know you can detect contact collisions using SKPhysicsContactDelegate, but can you check if a physicsbody is currently touching another physicsbody?
I need this for checking which area in the scene is still available to put an item (eg. pick a random spot, and if there's something in the way, pick another random spot).
There's this function:
/* Returns an array of all SKPhysicsBodies currently in contact with this one */
- (NSArray *)allContactedBodies;
But it doesn't appear to return anything useful until after the next update of creating the node.
You can write a function to iterate manually through all the nodes and check if the two circles intersect a point.
Since you said that the radius of the circles will differ each time, you have to keep track of it. One method is to use the user data of the node.
[node.userData setObject:[NSNumber numberWithFloat:10.0] forKey:#"radius"];
Then you can find if there are intersecting circles in the following way.
-(BOOL)checkPointForNode:(CGPoint)point withRadius:(CGFloat)nodeRadius
{
for (SKNode* child in [self children])
{
NSNumber *childRadius = child.userData[#"radius"];
if (childRadius != nil)
{
CGFloat diffX = point.x - child.position.x;
CGFloat diffY = point.y - child.position.y;
CGFloat distance = sqrtf(diffX * diffX + diffY * diffY);
CGFloat sumRadius = nodeRadius + childRadius.floatValue;
if (distance <= sumRadius)
{
return YES;
}
}
}
return NO;
}
The function returns YES if there is a circle within the boundary of the circle you are going to add. This means you cannot add a new node without touching another node. Otherwise it returns NO. This means you can add a new node without touching any other nodes.

Mutable Array and Sprites

I'm making a "snake game" like player and I have the body moving fine so that it adds a block in the previous position each time it moves up to 4 then it removes the last one... etc. I'm adding each block to a NSMutableArray (each block is a sprite and I add the sprite to the array) and I was wondering how to get the position of one of the sprites in the array. I need this so I can check to see if the "head" is trying to move onto itself.
P.S. I'm using cocos2d for iPhone.
When I say position I mean the coordinates, not the index position in the array.
[tail insertObject:block atIndex:i];
[self addChild:[tail objectAtIndex:i]];
i +=1;
CCSprite *sect;
for (int j = 0; j >= i; j++) {
sect = [tail objectAtIndex:j];
}
if (i > maxHealth) {
[self removeChild:[tail objectAtIndex:i-maxHealth-1] cleanup:YES];
id object = [tail objectAtIndex:i-maxHealth-1];
[tail removeObject:object];
}
When the scene is started i is set to 0 and the max health equals 3.
Get the position of a node in an array? Like
// Get the node from the array
CCNode *node = (CCNode*)[myArray objectAtIndex:0];
// Retrieve the position
CGPoint nodePosition = node.position;

Access C Array within blocks (variable array count) Objective-C

Blocks are fine but what about writing C arrays?
Given this simplified situation:
CGPoint points[10];
[myArray forEachElementWithBlock:^(int idx) {
points[idx] = CGPointMake(10, 20); // error here
// Cannot refer to declaration with an array type inside block
}];
after searching a while found this possible solution, to put it in a struct:
__block struct {
CGPoint points[100];
} pointStruct;
[myArray forEachElementWithBlock:^(int idx) {
pointStruct.points[idx] = CGPointMake(10, 20);
}];
this would work but there is a little limitation I have to create the c array dynamically:
int count = [str countOccurencesOfString:#";"];
__block struct {
CGPoint points[count]; // error here
// Fields must have a constant size: 'variable length array in structure' extension will never be supported
} pointStruct;
How can I access my CGPoint array within a block?
OR
Is it even possible at all or do I have to rewrite the block method to get the full functionality?
Another simple answer which works for me is the following:
CGPoint points[10], *pointsPtr;
pointsPtr = points;
[myArray forEachElementWithBlock:^(int idx) {
pointsPtr[idx] = CGPointMake(10, 20);
}];
Maybe you can allocate the array on the heap?
// Allocates a plain C array on the heap. The array will have
// [myArray count] items, each sized to fit a CGPoint.
CGPoint *points = calloc([myArray count], sizeof(CGPoint));
// Make sure the allocation succeded, you might want to insert
// some more graceful error handling here.
NSParameterAssert(points != NULL);
// Loop over myArray, doing whatever you want
[myArray forEachElementWithBlock:^(int idx) {
points[idx] = …;
}];
// Free the memory taken by the C array. Of course you might
// want to do something else with the array, otherwise this
// excercise does not make much sense :)
free(points), points = NULL;

interacting with UIViews stored inside a NSMutableArray

a big noob needs help understanding things.
I have three UIViews stored inside a NSMutableArray
lanes = [[NSMutableArray arrayWithCapacity:3] retain];
- (void)registerLane:(Lane*)lane {
NSLog (#"registering lane:%i",lane);
[lanes addObject:lane];
}
in the NSLog I see: registering lane:89183264
The value displayed in the NSLog (89183264) is what I am after.
I'd like to be able to save that number in a variable to be able to reuse it elsewhere in the code.
The closest I could come up with was this:
NSString *lane0 = [lanes objectAtIndex:0];
NSString *description0 = [lane0 description];
NSLog (#"description0:%#",description0);
The problem is that description0 gets the whole UIView object, not just the single number (dec 89183264 is hex 0x550d420)
description0's content:
description0:<Lane: 0x550d420; frame = (127 0; 66 460); alpha = 0.5; opaque = NO; autoresize = RM+BM; tag = 2; layer = <CALayer: 0x550d350>>
what I don't get is why I get the correct decimal value with with NSLog so easily, but seem to be unable to get it out of the NSMutableArray any other way. I am sure I am missing some "basic knowledge" here, and I would appreciate if someone could take the time and explain what's going on here so I can finally move on. it's been a long day studying.
why can't I save the 89183264 number easily with something like:
NSInteger * mylane = lane.id;
or
NSInteger * mylane = lane;
thank you all
I'm really confused as to why you want to save the memory location of the view? Because that's what your '89183264' number is. It's the location of the pointer. When you are calling:
NSLog (#"registering lane:%i",lane);
...do you get what's actually being printed out there? What the number that's being printed means?
It seems like a really bad idea, especially when if you're subclassing UIView you've already got a lovely .tag property which you can assign an int of your choosing.
You're making life infinitely more complex than it needs to be. Just use a pointer. Say I have an array containing lots of UIViews:
UIView *viewToCompare = [myArray objectAtIndex:3];
for (id object in myArray) {
if (object == viewToCompare) {
NSLog(#"Found it!");
}
}
That does what you're trying to do - it compares two pointers - and doesn't need any faffing around with ints, etc.

Objective-C, sorting an array based on a objects instance variable.

I'm working on a game like Rodents Revenge, just to point out where I'm coming from with this question. I'm using the cocos2d game engine aswell...
I have a layer that contains about 168 blocks, these blocks are a subclass of a Sprite. Each block contains two instance variables that are integers, one for the xGridLocation and yGridLocation. I have a method that I call that returns an array containing all the blocks that are on the same x or y row as the main character your controlling (the mouse). This method works as long as the blocks stay in the same order (smallest x/y value to largest), but when I start pushing the blocks out of their original row and mixing them up a bit (when playing the game) my logic no longer works because it is based on the fact that the blocks in the array are indexed from smallest to largest based on their xGridLocation or yGridLocation. The xGridLocation and yGridLocation are not based on their position, when the layer first loads they are given preset grid locations and as the block moves in any direction the grid location is changed based on which direction they moved.
My question is how can I go about sorting the array before it's returned in order based on the instance variables xGridLocation or yGridLocation. I was thinking using the sortUsingSelector:#selector(compareValues:) method but wasn't sure how to go about implementing the compareValues method that will do the sorting.
Here is my method I used for getting an array of blocks.
//I have another one for x. The y parameter is the mouses y value.
-(NSMutableArray *)getBlocksForY:(int)y
{
NSMutableArray *blocks = [[NSMutableArray alloc] init];
int tagNum = 0;
//tagNum starts at 0, and goes up to 168, the numer of children (blocks) on
//this layer...
for(tagNum; tagNum<=168; tagNum++)
{
BlueBlock *currentBlock = (BlueBlock *)[self getChildByTag:tagNum];
int currentY = [currentBlock getBlockLocationY];
//Checks to see if the current block has same y value as the mouse, if
//so it adds it to the array.
if(currentY == y)
{
[blocks addObject:currentBlock];
}
}
//I want to sort before returning...
return blocks;
}
If you need more information just ask.
As stated in NSMutableArray reference:
The comparator message is sent to each
object in the receiver and has as its
single argument another object in the
array. The comparator method should
return NSOrderedAscending if the
receiver is smaller than the argument,
NSOrderedDescending if the receiver is
larger than the argument, and
NSOrderedSame if they are equal.
So your comparator should be something like this, and should be added to BlueBlock class:
- (NSInteger) compareBlocks:(BlueBlock)block
{
if ([self getBlockLocationX] < [block getBlockLocationX])
return NSOrderedAscending;
else if ([self getBlockLocationX] == [block getBlockLocationX])
{
if ([self getBlockLocationY] < [block getBlockLocationY])
return NSOrderedAscending;
else if ([self getBlockLocationY] == [block getBlockLocationY])
return NSOrderedSame;
else
return NSOrderedDescending;
}
else
return NSOrderedDescending;
}