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;
Related
I can't figure out how to handle with tile map layer and other node. I want to make another one layer(CCNode) for such things as menu button, score, joystick that must always stay fixed(not scrolled), when the whole map is scrolled.
self.theMap=[CCTiledMap tiledMapWithFile:#"map.tmx"];
self.bgLayer=[theMap layerNamed:#"bg"];
[self addChild:theMap z:-1];
CCNode *joystickNode;
joystickNode=[CCNode node];
[bgLayer.parent addChild:joystickNode z:2];
upArrowFrame=[CCSpriteFrame frameWithImageNamed:#"uparrow.png"];
upArrow=[CCButton buttonWithTitle:#"" spriteFrame:upArrowFrame];
[upArrow setTarget:self selector:#selector(upArrowPressed)];
upArrow.position= ccp(190,190);
[joystickNode addChild:upArrow z:2];
Now upArrow is not visible on the screen at all. If I add to self instead of joystickNode, it will appear.
I can't even understand, what parent should new CCNode have. Can anyone explain it to me? I also tried to add new CCNode as a child of self and theMap.
EDIT: Oops, it's actually moving the camera. How to implement it in this case?
-(void)setCenterOfScreen :(CGPoint) position {
CGSize screenSize=[[CCDirector sharedDirector]viewSize];
int x=MAX(position.x, screenSize.width/2);
int y=MAX(position.y, screenSize.height/2);
x= MIN(x, theMap.mapSize.width * theMap.tileSize.width - screenSize.width/2);
y= MIN(y, theMap.mapSize.height * theMap.tileSize.height - screenSize.height/2);
CGPoint goodPoint =ccp(x,y);
CGPoint centerOfScreen = ccp(screenSize.width/2, screenSize.height/2);
CGPoint difference = ccpSub(centerOfScreen, goodPoint);
self.position=difference;
}
- (void)update:(CCTime)dt{
[self setCenterOfScreen:hero.position];
}
I want to know how to disappear certain sprite(star) once the MainPlayer touches the Star.
Thanks. By the way, I'm new to Cocos2d and I'm doing it just for fun and educational purpose.
Thanks.
If you want to be able to detect touches in cocos2d, you need to set the isTouchEnabled property to YES in your init method. You can now take advantage of touch events.
Next, create the new method:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//This method gets triggered every time a tap is detected
NSSet *allTouches = [event allTouches]; //Get all the current touches in the event
UITouch *aTouch = [allTouches anyObject]; //Get one of the touches, multitouch is disabled, so there is only always going to be one.
CGPoint pos = [aTouch locationInView:touch.view]; //Get the location of the touch
CGPoint ccPos = [[CCDirector sharedDirector] convertToGL:pos]; //Convert that location to something cocos2d can use
if (CGRectContainsPoint(yourSprite.boundingBox, ccPos)) //Method to check if a rectangle contains a point
{
yourSprite.visible = NO; //Make your sprite invisible
}
}
Other methods that you may want to take advantage of eventually are the following:
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
Hope this helped.
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.
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.