I've been studying this for hours (2 days, actually) and just cannot figure out what is wrong. The touches are accepted and processing, but the isTouchHandled test is triggering TRUE prematurely; as if a different bounding box was touched than the one that is touched. I have several non-overlapping CCSprite buttons, with each pointed to in the levelButtons array. Iterate through to see which one is touched; but it's always the wrong one.
Does the CGRectContainsPoints method get thrown off if these sprites are in their own layer, which is then in another layer? In other words, is CGRectContainsPoints using raw equality of pixel locations as reported by position? If so, a sprite's position relative to the entire screen is different than its reported position if it is a child, which is relative to the parent. Maybe this has something to do with it? My array and the tags of its contents are correctly lining up, I've logged and checked that many times; it appears to be the bounding box check.
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CCLOG (#"levelButtons size:%i",[self.levelButtons count]);
BOOL isTouchHandled = NO;
for (int i=0;i<25;i++){
CCSprite*temp=(CCSprite*)[self.levelButtons objectAtIndex:i];
CCLOG(#"iteration temp.tag: %i for object: %i",temp.tag,i);
isTouchHandled= CGRectContainsPoint([temp boundingBox], [[CCDirector sharedDirector] convertToGL:[touch locationInView: [touch view]]]);
if (isTouchHandled) {
CCLOG(#"level touched: %i",temp.tag);
break;
}
}
return isTouchHandled;
}
UPDATE: Incidentally, I also just subclassed CCSprite and add the touche methods to the individual sprites in this fashion ,taking my array of sprites out of the picture. The results were the same, so I suspect the CGRectContainsPoints is not properly working when your rect is a child of other children, the coordinates are not being reported correctly, I suspect.
I think it may be problem with an array that you are getting sprites. Any way , this is how i am using the code for getting the sprite tag.
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(int i1=0;i1<=25;i1++)
{
CCSprite *sprite1 = (CCSprite *)[self getChildByTag:i1];
if(CGRectContainsPoint([sprite1 boundingBox], location))
{
//Your Code
break;
}
}
I solved this by creating a new CGRect for the CGRectContainsPoint test, and translating the bounding box into the actual onscreen rectangle; the bounding box test will not work on its own if it is located on a child sprite (or layer). It returns its local position only, relative to the parent.
Related
I created a tile map using Tiled application. The map is 40X40 with the tileset size of 32X32. In the game the map is scrolling downwards giving the illusion that the car is moving. I am having trouble getting the Y coordinates when I click on the map during the game. I need to convert the Cocos2d coordinate system into a tileset system. When the tile map has reached the end I place the car again at the start of the map. This way the map continues infinitely. Inside the Tiled application I can see the coordinate of the block I need to get which is 3,19 but I am having a hard time figuring out how to convert the Cocos2d coordinate to reflect that tile. Here is my code:
- (CGPoint)tileCoordForPosition:(CGPoint)position {
int x = position.x / self.tiledMap.tileSize.width;
int y1 = ((self.tiledMap.mapSize.height * self.tiledMap.tileSize.height) - position.y) / self.tiledMap.tileSize.height;
return ccp(x, y1);
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGPoint tileCoord = [self tileCoordForPosition:location];
}
Check follow link: http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps?s=tmx
Try to get CCTMXLayer object with CCTMXTiledMap's method:
/** return the TMXLayer for the specific layer */
-(CCTMXLayer*) layerNamed:(NSString *)layerName;
Then use one of follow CCTMXLayer's methods:
-(CCSprite*) tileAt:(CGPoint)tileCoordinate;
-(uint32_t) tileGIDAt:(CGPoint)tileCoordinate;
-(uint32_t) tileGIDAt:(CGPoint)pos withFlags:(BOOL) flags;
When i move my layer that's contain all sprits by scrolling, sprits location does't change.i want's to change my sprits location with scrolling. please give me some solution for this.
Thanks in Advance......
// simple position update
CGPoint a = [[CCDirector sharedDirector] convertToGL:[touch previousLocationInView:touch.view]];
CGPoint b = [[CCDirector sharedDirector] convertToGL:[touch locationInView:touch.view]];
CGPoint nowPosition = scrollLayer.position;
nowPosition.y += ( b.y - a.y );
nowPosition.y = MAX( 0, nowPosition.y );
nowPosition.y = MIN(20, nowPosition.y);
scrollLayer.position = nowPosition;
My scrollLayer contain all the sprits. This is the code by which my layer moves to a new location. All sprits also move with the layer but their position does not change with respect to the layer moving. When i touch on that possition the sprits move. But I want to touch on sprits for moving them.
if you move a layer without moving its child sprites, the sprite.position will return the same value even after moving the layer because its returning it relative to node space (layer). To get the position of the sprite according to the world or your scene you need to convert it to world space:
CGPoint worldPosition = [self convertToWorldSpace:sprite.position];
i hope this answers your question because it wasnt very clear.
I have a problem dragging a sprite i've got the sprite moving left and right while keeping the y position the same, but i can't get the sprite to move up or down when the x position stays the same.
Also in the cctouchended the sprite moves so that it is in a fixed position, when all touches have ended
I am trying to make a game like slidieo/skozzle. Could do with some help
c1 is the column that is being moved, r1 is the row that is being moved,
[pos objectAtIndex:0] is the sprite's:red1 position and checks if the sprite is in c1 as every time you go into the game the sprite has a new random position and t1 is the cgrect of the sprite so that you must be clicking on the spirte because if you don't when you click above the sprite and try moving the sprite jumps to the touchlocation.
here is my code:
CGPoint touchLocation = [touch locationInView:[touch view]];
CGPoint prevLocation = [touch previousLocationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
prevLocation = [[CCDirector sharedDirector] convertToGL:prevLocation];
if (CGRectContainsPoint(c1,touchLocation)) {
if (CGRectContainsPoint(c1,[[pos objectAtIndex:0]CGPointValue])) {
if (CGRectContainsPoint(t1,touchLocation)) {
if (touchLocation.y>0||touchLocation.y<0) {
touchLocation.x = red1.position.x;
[red1 setPosition:ccp(touchLocation.x,touchLocation.y)];
}
}
}
}
if (touchLocation.x>0||touchLocation.x<0) {
touchLocation.y=red1.position.y;
[red1 setPosition:ccp(touchLocation.x,touchLocation.y)];
}
}
thanks
i've solved the problem :) just had to remove a few if statements and edit a few, now i've got it moving up and down and when the sprite stops it can move left and right
I am really stuck on this. My application is in landscape view and on one screen i wanted my instructions image to be scrollable. I have added this image as a sprite. First i tried to get scroll effect available from other sites, but soon i saw that scrolling was being done for the complete screen and not the sprite image. Then i resorted to implement the scrolling effect by dragging the sprite only in y axis (up and down). Unfortunately i am messing things somewhere, due to which only a portion of the sprite (shown on the screen only with the height 320pixels) is being dragged and the rest of the sprite is not being shown. The code is as follows
in the init layer function i have
//Add the instructions image
instructionsImage = [Sprite spriteWithFile:#"bkg_InstructionScroll.png"];
instructionsImage.anchorPoint = CGPointZero;
[self addChild:instructionsImage z:5];
instructionsImage.position = ccp(40,-580);
oldPoint = CGPointMake(0,0);
self.isTouchEnabled = YES;
//The touch functions are as follows
- (BOOL)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Move me!
if(touch && instructionsImage != nil) {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedPoint = [[Director sharedDirector] convertCoordinate:location];
CGPoint newPoint = CGPointMake(40, (instructionsImage.anchorPoint.y+ (convertedPoint.y - oldPoint.y)));
instructionsImage.position = newPoint;
return kEventHandled;
}
return kEventIgnored;
}
//The other function
- (BOOL)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Move me!
if(touch && instructionsImage != nil) {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedPoint = [[Director sharedDirector] convertCoordinate:location];
oldPoint = convertedPoint;
return kEventHandled;
}
return kEventIgnored;
}
Your approach is generally correct.
The code did not format properly, and you were not clear on exactly what the symptom is of the problem...
But it appears as if your math in the ccTouchesMoved is wrong. The anchor point is not what you care about there, as that's just a ratio within the image where the position and rotation anchor occurs. Set that, like you do, to whatever makes sense in the constructor but after that you don't need to reference it.
Try just adding your movement to the sprite:
deltaY = convertedPoint.y - oldPoint.y;
Now you know how many pixels your finger has moved up and down.
Reset your oldPoint data for next time:
oldPoint.y = convertedPoint.y;
Now apply this delta to your sprite:
instrucitonsImage.position = ccp(instructionsImage.position.y,instructionsImage.position.y + delta);
Should do it.
I have a class named insect child of sprite.I have created a
instance of that class in GameLayer and then initialize with
it using,
insect *bgg = [insect spriteWithFile:#"bird2a.gif"];
then i set a timer(10 second) to change the image using
*bgg = [insect spriteWithFile:#"2.gif"];
but my program crashes.Now my question is it possible to
re-initialize an object or it is immutable??
I have another question, when i used
- (BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
CGPoint point2 = [touch locationInView:[touch view]];
CGPoint cpoint=[[Director sharedDirector] convertCoordinate:point2];
NSLog(#"In touch began");
}
in my insect class it cannot detect touch on 'bgg' object declared
in GameLayer.But when I used this function in GameLayer it can
detect touch.
whats wrong with my approach??Plz someone explain.
Advanced thanx for your reply.
Your program crashes because you have a typo. Remove the '*' from '*bgg'. That means you are dereferencing the pointer, then trying to apply the creation of a new object to the dereferenced pointer. You just want
bgg = [insect spriteWithFile:#"2.gif"];
However, it's overkill to create an entirely new sprite just to change the image. A Sprite is a subclass of TextureNode, so just use TextureNode's texture property to give a Sprite a different image.
Texture2D *newImage = [[TextureMgr sharedTextureMgr] addImage:#"2.gif"];
bgg.texture = newImage;