Finding nearest points with Chipmunk and cocos2d - ios

Using cocos2d and chipmunk, I try to get the different object around a sprite (for example a bomb) so that I can apply an impulse on these. I first added this on top of my project:
#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
#import "CCPhysics+ObjectiveChipmunk.h"
And then the code:
ChipmunkSpace *space = [_physicsNode space];
cpVect origin = item.position;
for(ChipmunkPointQueryInfo *info in [space pointQueryNearest:origin maxDistance:32.0f filter:CP_SHAPE_FILTER_ALL])
{
CCLOG(#"Found one body");
}
I receive this error:
-[ChipmunkPointQueryInfo countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x813cdca0
What's the problem ?

You code should be
ChipmunkPointQueryInfo *info=[space pointQueryNearest:origin maxDistance:32.0f filter:CP_SHAPE_FILTER_ALL];
pointQueryNearest doesn't return array, as you are trying to enumerate.
Cheers.

Related

How to SuperClass object cast to SubClass [objective -c]

I want to add polyLine to mapView , the baidu mapView polyline superclass is BMKPolyLine, it have a class method:
+ (BMKPolyline *)polylineWithPoints:(BMKMapPoint *)points count:(NSUInteger)count;
I creat a subclass BKMyPolyLine, i add a #property colorString
when I get points and used superclass method :
BKMyPolyLine *myLine = [BKMyPolyLine polylineWithPoints:points count:points.count];
myLine.colorString = colorString;
and crash message:
[BMKPolyline setColorString:]: unrecognized selector sent to instance 0x138266fe0'
This isn't "casting" (casting merely informs the compiler; it does not alter actual types)--but you have done something that should return your subclass. It sounds like BMKPolyline's +polylineWithPoints:count: method returns a BMKPolyline, even when it's called on a subclass. Instead you need to override what's known as the "designated initializer", which should be marked in the documentation. But from what I see online, it isn't documented--you probably (annoyingly) need to look into the source of BMKPolyline to know how to proceed.

Calling a instance method while using childNodeWithName

Is it possible to call an instance method without using an instance variable or #property?
Here is how I create an instance of a class. Within the method, I try to call on the class's instance movement method to force the instance to move:
-(void)createCharacterNPC
{
int randomness = [self getRandomNumberBetweenMin:1 andMax:20];
for (int i = 0; i < randomness; i += 1)
{
NSString *npcName = [NSString stringWithFormat:#"anNPC%i", randomness];
NPCclass *NPC = [[NPCclass alloc] initWithName:npcName];
NPC.position = CGPointMake(self.size.width/2, self.size.height/2);
NPC.zPosition = 1.0;
[_worldNode addChild:NPC];
// THIS OBVIOUSLY WORKS. But I can't use this technique outside this method.
[NPC beginMovement];
// THIS IS WHAT I WANT, BUT XCODE DOESN'T ALLOW ME TO WRITE CODE THIS WAY.
[[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
}
}
Is there a way to allow [[_worldNode childNodeWithName:#"anNPC1"] beginMovement]; to work? Or some way similar to this so I wouldn't have to have create an instance variable of NPC (like so: _NPC)?
I'm asking because all of this is happening inside a mini-game scene and NPCclass will be initialized a random number amount of times (with arc4random() method). NPCclass moves on its own using vector (physics in a platformer) movement but I need to initialize its movement method right after creation then I need to periodically access each individually created instance of NPCclass using its name in other methods of the scene. Since I don't know how many NPCclass instances will be created each time the mini-game is played, I CAN'T use IVAR's or something like #property NPCclass *anNPC;
Please help.
Xcode complains about
[[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
because the method -childNodeWithName returns an SKNode object. Instances of the SKNode class do not respond to the selector -beginMovement (or as Xcode puts it, no visible #interface declares the selector -beginMovement). Xcode shows this to you to force you to make sure you wrote what you wanted to write. Since you are sure, you can tell Xcode that the returned object is of the type NPCclass.
(NPCclass *)[_worldNode childNodeWithName:#"anNPC1"]
Now you can expand the statement to call -beginMovement.
[(NPCclass *)[_worldNode childNodeWithName:#"anNPC1"] beginMovement];
Note
There are a few concepts which you might be confusing. NPCclass is a class. +node is a class method of SKNode, which you can call with [NPCclass node];. -beginMovement is an instance method, called with:
NPCclass *npc = [NPCclass node];
[npc beginMovement];
Or:
[(NPCclass *)anyObject beginMovement];
// make sure anyObject responds to this selector though, or you app will crash.
Class methods are prefixed with a +, instance methods with -.
Class methods do not use an instance, just the class name.
As an example consider the
NSString` class method: `+ (id nullable)stringWithContentsOfFile:(NSString * nonnull)path
and a usage:
NSString *fileData = [NSString stringWithContentsOfFile:filePath];

NSMutableArray Interaction Troubles With Collisions

I am having trouble getting objects added to my NSMutableArray to log properly (which definitely means they won't process any of the appropriate functions correctly) with Spritebuilder [version 1.4.9, from the Apple App Store]. I am creating several objects using the same class, but each new one is overriding the older objects which exist. I thought an array would help keep things in order (and then on collision, I could call the array to check for which object was collided with), but it simply is not working that way - at all. Here is the relevant code.
Main.h
#property Coven *coven;
#property Nellie *nellie;
#property NSMutableArray *array;
//Physics, other things
Main.m
/Adding other things...
-(void) addCovenMember{
//This function is called on a RANDOM time interval
_array = [[NSMutableArray] alloc]init];
for (i = 0, i < 15, i++){
_coven = (Coven*) [CCBReader load:#"CovenMember"];
[_array addChild:_coven];
}
[_physicNode addChild:_coven];
}
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
for (_coven in _array){
NSLog(#"%#",_coven.name)
if (CGRectIntersectsRect(_nellie.boundingBox, _coven.boundingBox){
NSLog(#"We're intersecting!");
}
}
Coven. h
//Nothing Important Here
Coven.m
-(void)didLoadFromCCB{
self.physicsBody.CollisionType = #"coven";
}
Nellie.h
//Nothing Here
Nellie.m
-(void) didLoadFromCCB{
self.physicsBody.CollisionType = #"nellie";
}
The collision is logging with every collision - but only as the name of the LATEST _coven member to be generated, no matter what I am colliding with. This also means that the _coven.boundingBox is solely on the latest _coven member and interaction only occurs when I hit the new member as soon as it generates on to the screen.
Any ideas? Any help?
Note: This is also posted on the Spritebuilder website - I decided to post it here as well because answers can be a little slow on those forums.
The -(void) addCovenMember overwrites (creates a new instance) of _array every time it's called. Thus, when you try to iterate in -ccPhysicsCollisionBegin: you'll only ever see 1 coven.
Add a nil check around your array creation:
if(_array == nil) {
_array = [[NSMutableArray] alloc]init];
}
The for loop in the -addCovenMember method looks broken (at least not a c loop). Reaplace the , with ;:
for (i = 0; i < 15 i++){
Also, using for(_coven in _array) seems wrong, you already have a property self.coven (presumably) with a backing _coven ivar. Try changing it to for(Coven * c in self.array) and use the local c in the loop:
for (Coven * c in _array){
NSLog(#"%#",c.name)
if (CGRectIntersectsRect(_nellie.boundingBox, c.boundingBox){
NSLog(#"We're intersecting!");
}
}
To everyone out in the world struggling with their ccPhysicsCollisions, arrays may not be the answer - this was a simple fix that left me incapacitated for days.
Using the basic ccPhysicsCollisionsBegan that ships with spritebuilder, try this without arrays first:
Scene.m
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
[_coven stopAction:coven.path];
}
I initially created the method with:
[_coven stopAction:_coven.path];
Yes, that (underscore) set me back three weeks. Be sure you refer to the object interacting through the physics delegate, and not the object itself, which in my case, was constantly being overwritten by the new ones being generated.
Check your underscores.
Solved! :D
Thanks to #thelaws for your help! I'll get better at Obj C... eventually.

Not casting properly?

I'm following this tutorial. And I keep getting this casting error. I've imported the Obstacle.h file in the shown class (MainScene.m). I have no idea what I'm doing wrong
- (void)spawnNewObstacle {
CCNode *previousObstacle = [_obstacles lastObject];
CGFloat previousObstacleXPosition = previousObstacle.position.x;
if (!previousObstacle) {
// this is the first obstacle
previousObstacleXPosition = firstObstaclePosition;
}
Obstacle *obstacle = (Obstacle *)[CCBReader load:#"Obstacle"];
obstacle.position = ccp(previousObstacleXPosition + distanceBetweenObstacles, 0);
[obstacle setUpRandomPosition];
[_physicsNode addChild:obstacle];
[_obstacles addObject:obstacle];
}
Error:
-[CCNode setUpRandomPosition]: unrecognized selector sent to instance 0x9a88a30
2014-04-20 10:51:28.046 FlappyFlyl[2104:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CCNode setUpRandomPosition]: unrecognized selector sent to instance 0x9a88a30'
Likely you didn't set the custom class of your root node in "Obstacle.ccb" in SpriteBuilder correctly. That's why your "Obstacle.ccb" root node is a CCNode and not an Obstacle object.
The obstacle variable does not hold an object of type Obstacle. Instead it holds an object of type CCNode. CCNode does not have a method named -setUpRandomPosition, so you get a runtime error. In Objective-C, casting is a no-op. It doesn't do anything except helping the reader of your code see the intent of the person who wrote the code.
In this regard Objective-C differs from languages like C++ or Java. Objective-C has an object system that is similar to the programming language "Smalltalk".

Accessing an instance variable from another class for cocos2d project?

In my cocos2d game, I have a "powerup" of sorts where, once attained, the character becomes blue, the platform becomes blue, and so does the background. I'm not sure if I am implementing this in the best way so if you have other suggestions please do share!:)
I created a class Blue that has an instance variable called blueCalled
I imported this class to both my "Platform" class as well as my "Player" class.
The powerup and player colliding code is inside my Platform class. This is the code for when the powerup is hit:
// try remove powerup
- (void) tryRemovePowerup
{
NSMutableArray * currentPowerUpArray = [self getcurrentPowersArr];
if(currentPowerUpArray)
{
int playerY = ((CCLayer*)(self.player)).position.y;
for(int x=0; x<[currentPowerUpArray count];x++)
{
CCSprite *powerup = [currentPowerUpArray objectAtIndex:x];
if(abs(powerup.position.x+powerup.parent.position.x-[Player initX])<50)
{
if(abs(powerup.position.y+blueberry.parent.position.y-playerY)<30 && powerup.visible && powerup.visible)
{
[power.parent powerup cleanup:YES];
CGSize winSize = [[CCDirector sharedDirector] winSize];
[[SimpleAudioEngine sharedEngine] playEffect:#"yay.wav" pitch:1 pan:0 gain:1];
// THIS IS WHERE ALL OF EFFECTS SHOULD HAPPEN
NSLog(#"powerup hit");
}
}
}
}
[self hitTestOB];
}
The place of // THIS IS WHERE ALL OF EFFECTS SHOULD HAPPEN is where I want to make everything blue. Right now, I plan to do this by setting the instance variable in the Blue class to YES.
In the methods that take care of the 1. frames of the main player, 2. background, and 3. platform frames, I have an if statement checking if the instance variable of the Blue class is YES or NO and it acts accordingly.
However, I don't know how to use the instance variable from the Blue class in my platform and player class, also, I'm not 100% confident this is the best way to implement a powerup.
Thank you for any help you can provide me :)
Go iOS!
As a general rule, if you want to access an iVar of another object, you should make a property to access it. This is not an exception to that rule, but I'll tell you how to do it anyways.
Objective C objects are inherently C structures. This means that the -> operator works on them. In this case, you would want to use blue->blueCalled, where blue is the instance of your Blue class.
Visibility is the key to this working (or failing). You can only use this if the iVar is declared within the #interface in the header file and not following and #private or #protected declaration.

Resources