I was wondering if anyone could help me with my program,
I have randomised my sprites into a specific set of co-ordinates.
I want one of the sprites that is at that specific co-ordinate, to be able to make them do something when they are at this random co-ordinate. The problem i am having is that i have to make a long list of if statements saying if this sprite is here do this if another sprite is here do the exact same thing.
if (red1.position.y>=0 && red1.position.y<=63) {
id r1animation = [CCMoveTo actionWithDuration:0.2 position:ccp(red1.position.x,33)];
[red1 runAction:r1animation];
}
if (red2.position.y>=0 && red2.position.y<=63) {
id r2animation = [CCMoveTo actionWithDuration:0.2 position:ccp(red2.position.x,33)];
[red2 runAction:r2animation];
}
i want to be able to say if any of the sprites are at that exact co-ordinate then move them to a point, in a short amount of code as possible. so basically grouping the sprites or something i'm not sure.
Thanks
i want to be able to say if any of the sprites are at that exact co-ordinate then move them to a point
Firstly, specify the 'hotspot' programatically:
CGPoint hotspot = ccp(32,32); // convenience macro,
//creates a CGPoint with x = 32, y = 32
You should store a reference to all your sprites in an array when you create them (you can use cocos2d's 'tagging' also, but I usually like to use an array for simplicity)
-(void)init {
//.. misc
// creating sprite returns a reference so keep it in an array
CCSprite* curSprite = [CCSprite spriteWithFile: //...etc]
[self.spriteArray addObject: curSprite];
// add all sprite references to your array
}
Now you can iterate over this array to see if any of the sprite's frames overlap the hotspot:
-(BOOL) checkAllSpritesForCollision
{
for (CCSprite *sp in self.spriteArray)
{
CGRect spriteRect = sp.frame;
if (CGRectContainsPoint(spriteRect,hotspot))
{
// run your action on sp...
}
}
// you might like to return YES if a collision happened?
}
This is a brute force method of checking whether every sprites frame contains a given point. There are many ways to skin this cat of course, but hopefully this will set you on a better path.
What you can do is to calculate the distance:
float pointX = thePoint.position.x;
float pointY = thePoint.position.y;
float pointDeltax = sprite.position.x-pointX;
float pointDeltay = sprite.position.y-pointY;
float pointDist = sqrt(pointDeltax*pointDeltax+pointDeltay*pointDeltay);
But maybe davbryns solution suits your purpose better.
Related
In my game, I'm trying to determine what points to dole out depending on where an arrow hits a target. I've got the physics and collisions worked out and I've decided to draw several nested circular SKShapeNodes to represent the different rings of the target.
I'm just having issues working out the logic involved in checking if the contact point coordinates are in one of the circle nodes...
Is it even possible?
The easiest solution specific to Sprite Kit is to use the SKPhysicsWorld method bodyAtPoint:, assuming all of the SKShapeNode also have an appropriate SKPhysicsBody.
For example:
SKPhysicsBody* body = [self.scene.physicsWorld bodyAtPoint:CGPointMake(100, 200)];
if (body != nil)
{
// your cat content here ...
}
If there could be overlapping bodies at the same point you can enumerate them with enumerateBodiesAtPoint:usingBlock:
You can also compare the SKShapeNode's path with your CGPoint.
SKShapeNode node; // let there be your node
CGPoint point; // let there be your point
if (CGPathContainsPoint(node.path, NULL, point, NO)) {
// yepp, that point is inside of that shape
}
My testing environment:
Xcode 4.6, New cocos2d-x+box2d project
cocos2d-2.1beta3-x-2.1.1
PhysicsEditor 1.0.10
I modified a bit in HelloWorldScene of PhysicsEditor cocos2dx demo to make it simpler, Here are some of my code:
initPhysics
gravity.Set(0.0f, 0.0f);
So that the sprite will not move.
Replace source code inside ccTouchesEnded to:
CCTouch* pTouch = (CCTouch *)touches->anyObject();
CCPoint location = pTouch->locationInView(pTouch->view());
CCPoint convLoc = CCDirector::sharedDirector()->convertToGL(location);
b2Vec2 v = b2Vec2(convLoc.x/PTM_RATIO, convLoc.y/PTM_RATIO);
for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
{
b2Fixture *f = b->GetFixtureList(); // get the first fixture
CCSprite *sprite =(CCSprite *) b->GetUserData();
if(sprite != NULL)
{
if(f -> TestPoint(v))
{
CCLog("You touched a body %d",sprite->getTag());
}
}
}
The problem is that TestPoint only return true in a very small area (not for whole shape area).
Here is the screenshot:
Can anybody suggest how I debug this problem? Thanks
Updated: showing the generated data from PhysicsEditor
The problem is that you only probe for the first fixture. But complex bodies are made from several. The reason is that
Box2d only allows 8 vertexes per fixture
Box2d can only work with convex shapes
This is why complex shapes are decomposed into a list of polygons.
Iterate over the fixture list instead.
b2Fixture *f = body->GetFixtureList();
while(f)
{
if(f -> TestPoint(v))
{
CCLog("You touched a body %d",sprite->getTag());
}
f = f->GetNext();
}
For a simple game, I have 4 different platforms (all on one spritesheet). I initially add 5 of each to a CCSpriteBatchNode, and set them all as not visible. When I set my platforms I want to take a platform of a certain type from my CCSpriteBatchNode and change it to make it visible and position it.
I am having trouble finding platforms of a specific type that aren't visible. Or vice-versa?
I know you can use [batchnode getchildbytag:tag] but as far as I know that only returns one sprite. Is there any way I can put pointers to each platform of a specific type into an array, so that I can iterate through the array and find all the not visible sprites?
Thanks!
As suggested by Drama, you will have no choice than to 'iterate' the children. As for identifying which sprite corresponds to which platform, a few ways exist. A simple one would be to use the 'tag' property of the sprite -- assuming you do not use it for any other purpose.
// some constants
static int _tagForIcyPlatform = 101;
static int _tagForRedHotPlatform = 102;
... etc
// where you create the platforms
CCSptiteBatchNode *platforms= [CCSpriteBatchNode batchNodeWithFile:#"mapItems_playObjects.pvr.gz"];
CCSprite *sp = [CCSprite striteWithSpriteFrameName:#"platform_icy.png"];
sp.tag = _tagForIcyPlatform;
[platforms addChild:sp];
sp = [CCSprite striteWithSpriteFrameName:#"platform_redHot.png"];
sp.tag = _tagForRedNotPlatform;
[platforms addChild:sp];
// ... etc
// where you want to change properties of
-(void) setVisibilityOf:(int) aPlatformTag to:(BOOL) aVisibility {
for (CCNode *child in platforms.children) {
if (child.tag != aPlatformTag) continue;
child.visible = aVisibility;
}
}
once again, this works if you are not using tags of platform's children for another purpose. If you need the tags for some other purpose, consider using an NSMutableArray in the class, one per platform type, and store in that array the pointer to your sprites of the appropriate type.
There's not a super straightforward way to do that. You'll need to iterate through the children and inspect each child individually.
For coding efficiency, consider adding a category to CCSpriteBatchNode that performs this function for you. That way you can easily replicate it as needed.
I'm new to cocos2d and I made my way through the 'Learning cocos2d' book.
Like in the Book I implemented a scrollingLayer for scrolling, when my gamecharacter moves.
My problem is the following: I'm using a normal Sprite to do the scrolling layer rendering who can I check if my character is touching the scorlling layer?
fyi: It's a fish and he needs to swim through a hole and there are walls above und underneath it and he should not be able to get in front or behind the rocks.
I've searched the internet and this forum, but was not be able to find any suitable solutions.
Is 'Tiled' the kay for happiness, I read about collisions implemented but can't make it out how they are implemented using tmx's
Can someone assist me with that?
For simplier, but powerful collision detection you most likely need physics engine.
I recommend SpaceManager extension for Chipmunk engine.
In Tiled you can add object layer to tmx file, where you can line out all obstacles.
That's how I parse this information in my game scene:
in init:
self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:#"TileMap.tmx"];
...
smgr = [[SpaceManagerCocos2d alloc] init];
smgr.constantDt = 1/60.0;
smgr.gravity=ccp(0, 0);
[smgr addWindowContainmentWithFriction:0.0 elasticity:0.0 size:CGSizeMake(1000, 1000) inset:cpvzero radius:1.0f]; //borders of your world, can be set from tmx size
player = [smgr addCircleAt:ccp(x,y) mass:6 radius:15];
and somewhere:
- (void) drawWalls {
//searching for object layer called "Collisions"
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:#"Walls"];
NSMutableDictionary * objPoint;
int x ;
int y ;
int w ;
int h ;
for (objPoint in [objects objects]) {
x = [[objPoint valueForKey:#"x"] intValue];
y = [[objPoint valueForKey:#"y"] intValue];
w = [[objPoint valueForKey:#"width"] intValue];
h = [[objPoint valueForKey:#"height"] intValue];
GameController *controller = [GameController sharedController];
if(controller.retina==1)
{
x=x/2;
y=y/2;
w=w/2;
h=h/2;
}
cpShape *staticShape = [smgr addRectAt:ccp(x+w/2,y+h/2) mass:STATIC_MASS width:w height:h rotation:0];
}
}
Then, you can apply force at "player" object and update your sprite position in "update" method:
playerSprite.position=ccp(player->body->p.x, player->body->p.y);
Of course you can use some other algorithm to detect collision, but this is just an example of storing and retrieving this information from tmx.
I am trying to find collision detection between Two Sprits ( encircle with black color in below picture)
here is the code from which i m trying to find with the help by compairing x cordinate of both sprits but unsuccessful
have a look and tell me what is the mistake
- (void)update:(ccTime)dt {
NSLog(#"Target y %f, player y %f",target.position.y, player.position.y);
if(target.position.y==player.position.y)
// if((target.position.x==player.position.x)&&(target.position.y==player.position.y))
// if((sprite.position.y==player.position.y)||(sprite.position.y==player.position.y))
{
Nslog (#"Matched");
//do Something
}
}
The CCNode class which is the parent of the CCSprite class has a boundingBox property of type CGRect. Using this property of the player and target objects you can check for collisions using...
if (CGRectIntersectsRect(player.boundingBox, target.boundingBox) {
// Kaboom...
}
you could have a look at CGRectIntersectsRect like shown here
http://www.icodeblog.com/2009/02/18/iphone-game-programming-tutorial-part-2-user-interaction-simple-ai-game-logic/