I am developing Iphone app and using Google map.Draw Multiple Polygon on google Map. but than deleting the polygon on map that deleting the last polygon not delete all draw polygon on google map.please help thanks in advance.
code..
// Draw Polygon
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
if (buttonClicked == true) {
NSLog(#"You tapped at %f,%f", coordinate.latitude, coordinate.longitude);
_latLongDict = #{#"lat":#(coordinate.latitude), #"long":#(coordinate.longitude)};
[_clickCoordinate addObject:_latLongDict];
NSLog(#"%#",_clickCoordinate);
_path = [GMSMutablePath path];
CLLocationCoordinate2D event;
for (NSDictionary *dic in _clickCoordinate) {
event.latitude = [[dic valueForKey:#"lat"] floatValue];
event.longitude = [[dic valueForKey:#"long"] floatValue];
[_path addCoordinate:event];
}
_polygun = [GMSPolygon polygonWithPath:_path];
_polygun.fillColor = [UIColor colorWithRed:0.25 green:0 blue:0 alpha:0.05];
_polygun.strokeColor = [UIColor blackColor];
_polygun.strokeWidth = 2;
_polygun.map = mapView;
}
// Delete Polygon
- (IBAction)cancelButton:(id)sender {
for (int i = 0; i < _path.count; i++) {
_polygun.map = nil;
[_clickCoordinate removeAllObjects];
[_path removeAllCoordinates];
NSLog(#"%#",_clickCoordinate);
}
}
How to draw an arrow between two points on the map?
I try calc latitude and longitude, but something goes wrong.
Best regards, Max
This is my code and result picture
int currpoints1 = 2;
NSLog(#"!!!!!!!!%d ",numPoints);
while(currpoints1 < numPoints)
{
TrackPoint* current = nil;
CLLocationCoordinate2D* coordsArrrow = malloc((3) * sizeof(CLLocationCoordinate2D));
for (int i =currpoints1, j=0; i < numPoints; i=i+1, j++)
{
current = [cashpoints objectAtIndex:i];
coordsArrrow[j] = current.coordinate;
if (i % 2 !=0) {
int Gug = 30;
int ug;
float bx, by, ex, ey;
bx = coordsArrrow[0].latitude;by = coordsArrrow[0].longitude;
ex = coordsArrrow[1].latitude;ey = coordsArrrow[1].longitude;
float Lstr = sqrt((ex-ey)*(ex-ey)+(bx-by)*(bx-by));
ug = [self RetGradW:(abs(coordsArrrow[1].latitude-coordsArrrow[0].latitude)) height:abs(coordsArrrow[1].longitude-coordsArrrow[0].longitude)];
ug = ug - Gug;
coordsArrrow[0].latitude = ex;
coordsArrrow[0].longitude = ey;
coordsArrrow[1].latitude = ex+Lstr*cos(ug*M_PI/180);
coordsArrrow[1].longitude = ey+Lstr*sin(ug*M_PI/180);
ug=ug+2*Gug;
coordsArrrow[2].latitude = ex+Lstr*cos(ug*M_PI/180);
coordsArrrow[2].longitude = ey+Lstr*sin(ug*M_PI/180);
MKPolyline *points = [MKPolyline polylineWithCoordinates:coordsArrrow count:3];
points.subtitle = #"arrow";
[map addOverlay:points];
break;
}
}
free(coordsArrrow);
currpoints1 = currpoints1 +14;
}
Oh guys. I change other way. Make annotation and rotate with direction between two point.
metods :
calc direction:
int currpoints1 = 2;
NSLog(#"!!!!!!!!%d ",numPoints);
while(currpoints1 < numPoints)
{
TrackPoint* current = nil;
CLLocationCoordinate2D* coordsArrrow = malloc((2) * sizeof(CLLocationCoordinate2D));
for (int i =currpoints1, j=0; i < numPoints; i=i+1, j++)
{
current = [cashpoints objectAtIndex:i];
coordsArrrow[j] = current.coordinate;
if (i % 2 !=0) {
DirectAnnotation *placemark=[[DirectAnnotation alloc] initWithCoordinate: coordsArrrow[0]];
CLLocationCoordinate2D coord1 = coordsArrrow[0];
CLLocationCoordinate2D coord2 = coordsArrrow[1];
CLLocationDegrees deltaLong = coord2.longitude - coord1.longitude;
CLLocationDegrees yComponent = sin(deltaLong) * cos(coord2.latitude);
CLLocationDegrees xComponent = (cos(coord1.latitude) * sin(coord2.latitude)) - (sin(coord1.latitude) * cos(coord2.latitude) * cos(deltaLong));
CLLocationDegrees radians = atan2(yComponent, xComponent);
CLLocationDegrees degrees = radiansToDegrees(radians) + 360;
self.dir = fmod(degrees, 360);
NSLog(#"%f,%f %f,%f",coordsArrrow[0].latitude,coordsArrrow[0].longitude,coordsArrrow[1].latitude,coordsArrrow[1].longitude);
[self.map addAnnotation:placemark];
break;
}
}
free(coordsArrrow);
currpoints1 = currpoints1 +14;
}
and
annotation:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[DirectAnnotation class]]) {
arrow=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"parkingloc"];
arrow.image = [UIImage imageNamed:#"userLocationCompass.png"];
CGAffineTransform transform = CGAffineTransformMakeRotation(degreesToRadians(dir));
arrow.transform = transform;
return arrow;
}else {
return nil;
}}
But i have some problem
before zoom:
after zoom :
direction is confused.
Your arrows change the angle because you don't reuse them in viewForAnnotation correctly.
Just make some unique id for each arrow like this in viewForAnnotation:
routeAnnotationView = (MKAnnotationView *)[lmapView dequeueReusableAnnotationViewWithIdentifier:[NSString stringWithFormat:#"%f%f",annotation.coordinate.latitude, annotation.coordinate.longitude]];
if (!routeAnnotationView)
{
routeAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:[NSString stringWithFormat:#"%f%f",annotation.coordinate.latitude, annotation.coordinate.longitude]];
UIImage *image = [self rotateImage:[UIImage imageNamed:#"arrpix11.png"] onDegrees:RADIANS_TO_DEGREES(curAngle)+90];
routeAnnotationView.image = image;
}
else
{
routeAnnotationView.annotation = annotation;
}
routeAnnotationView.canShowCallout = NO;
Use this for draw path between two location in Map.
http://code.google.com/p/ashiphone/downloads/detail?name=MapWithRoutes.zip&can=2&q=
I am working with MKMapView to draw route using MKPolyline, I am able to draw single route with an array of waypoints.Now I want to draw multiple MKPolylines on the MKMapView for instance, A blue MKPolyline from 28.102021, 77.10129 to 28.20320, 77.3021 and A red MKPolyline from 28.50930, 77.89192 to 28.60291, 77.87328. How can I achieve this ?
Code:
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = 6.0;
locationManager.distanceFilter = 1.0;
[locationManager startUpdatingLocation];
locationManager.delegate = self;
map.delegate = self;
[map setShowsUserLocation:YES];
[map setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
wayPoints = [[NSMutableArray alloc] initWithCapacity:30];
newWayPoints = [[NSMutableArray alloc]initWithCapacity:10];
totalDistance = 0.0;
stopTime = [NSDate dateWithTimeIntervalSinceNow:100];
startTime = [NSDate date];
SEL sel = #selector(timerTargetMethod);
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:
[self methodSignatureForSelector:sel]];
[inv setTarget:self];
[inv setSelector:sel];
stopTimer = [NSTimer scheduledTimerWithTimeInterval:5 invocation:inv repeats:true];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if(newLocation != nil && oldLocation != newLocation)
{
tempNewLocation = newLocation;
tempOldLocation = oldLocation;
}
}
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *annotationView = [views objectAtIndex:0];
id<MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate] ,4000,4000);
[mv setRegion:region animated:YES];
}
// MKMapViewDelegate
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
MKPolylineView * routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
routeLineView.fillColor = [UIColor colorWithRed:0.0-1.0 green:0.0-1.0 blue:0.0-1.0 alpha:1.0f];
routeLineView.strokeColor = [UIColor colorWithRed:0.0-1.0 green:0.0-1.0 blue:0.0-1.0 alpha:1.0f];
routeLineView.lineWidth = 3;
routeLineView.lineCap = kCGLineCapSquare;
overlayView = routeLineView;
return overlayView;
}
//define the targetmethod
-(void) timerTargetMethod
{
if([[NSDate date] timeIntervalSinceDate:startTime] >= 100)
{
[stopTimer invalidate];
[locationManager stopUpdatingLocation];
NSLog(#"Time started at %#", startTime);
NSLog(#"Time up at %#", stopTime);
}
else if (tempOldLocation.coordinate.latitude == tempNewLocation.coordinate.latitude && tempNewLocation.coordinate.longitude == tempOldLocation.coordinate.longitude)
{
NSLog(#" Fix location found ");
}
else if( [[NSDate date] timeIntervalSinceDate:startTime] >= 19 )
{
if(roundf([[NSDate date] timeIntervalSinceDate:startTime]) == 20)
{
NSLog(#"First Time Location Update");
latitudeLongitude.text = [[ NSString alloc] initWithFormat:#"%g , %g", tempNewLocation.coordinate.latitude, tempNewLocation.coordinate.longitude];
float interval = [[NSDate date] timeIntervalSinceDate:startTime];
int okInterval = roundf(interval);
NSLog(#"Interval 1 , %d", okInterval );
time.text = [[ NSString alloc] initWithFormat:#"%d", okInterval - 20];
speed.text = #"0";
totalDistance = 0;
distance.text = #"0 meters";
}
else
{
latitudeLongitude.text = [[ NSString alloc] initWithFormat:#"%g , %g", tempNewLocation.coordinate.latitude, tempNewLocation.coordinate.longitude];
float interval = [[NSDate date] timeIntervalSinceDate:startTime];
int okInterval = roundf(interval);
time.text = [[ NSString alloc] initWithFormat:#"%d", okInterval - 20];
NSLog(#"Interval 2 , %d , %f", okInterval , interval);
if((tempNewLocation.coordinate.latitude == tempOldLocation.coordinate.latitude && tempNewLocation.coordinate.longitude == tempOldLocation.coordinate.longitude) || tempNewLocation.speed < 0)
speed.text = #"0";
else
speed.text = [[ NSString alloc] initWithFormat:#"%g meters/sec", tempNewLocation.speed];
if(tempNewLocation.coordinate.latitude == tempOldLocation.coordinate.latitude && tempNewLocation.coordinate.longitude == tempOldLocation.coordinate.longitude)
{
}
else if ([tempNewLocation distanceFromLocation:tempOldLocation] - tempNewLocation.horizontalAccuracy >= 0)
totalDistance += [tempNewLocation distanceFromLocation:tempOldLocation] - (tempNewLocation.horizontalAccuracy / 2);
else
totalDistance += [tempNewLocation distanceFromLocation:tempOldLocation];
if (totalDistance < 0)
distance.text = #"0 meters";
else
distance.text = [[ NSString alloc] initWithFormat:#"%g meters", totalDistance];
}
[wayPoints addObject:tempNewLocation];
MKMapPoint * pointsArray =
malloc(sizeof(CLLocationCoordinate2D)*2);
pointsArray[0]= MKMapPointForCoordinate(tempOldLocation.coordinate);
pointsArray[1]= MKMapPointForCoordinate(tempNewLocation.coordinate);
routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
free(pointsArray);
if (tempNewLocation.coordinate.latitude - tempOldLocation.coordinate.latitude < 1) {
[map addOverlay:routeLine];
}
}
}
Thanks
That's a lot of code you've shown there, the only bit that is relevant is viewForOverlay. In there you are given an object that conforms to the MKOverlay protocol and if you have created your own class to implement that you could add a variable that could be used to identify which overlay you were dealing with at that point and thus adjust your colours. Further down your code I see you are creating MKPolylines, those are the overlays passed in to viewForOverlay and because they inherit from MKShape they have title and subTitle attributes you can use.
So when you create the MKPolyline you could set the title, maybe to "typeA" and "typeB", then in viewForOverlay you need to cast the overlay to a MKPolyline and check which title it has to decide which colour to use:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
if([overlay class] == MKPolyline.class)
{
MKOverlayView* overlayView = nil;
MKPolyline* polyline = (MKPolyline *)overlay;
MKPolylineView * routeLineView = [[MKPolylineView alloc] initWithPolyline:polyline];
if([polyline.title isEqualToString:#"typeA"])
{
routeLineView.fillColor = [UIColor redColor];
routeLineView.strokeColor = [UIColor redColor];
} else {
routeLineView.fillColor = [UIColor blueColor];
routeLineView.strokeColor = [UIColor blueColor];
}
routeLineView.lineWidth = 3;
routeLineView.lineCap = kCGLineCapSquare;
overlayView = routeLineView;
return overlayView;
} else {
return nil;
}
}
I have used MKMapView to show map and current user location which is working correctly.
Now I want to draw a polyline as user moves but it is not working I tried follwing code:
for(int i = 0; i < [longarray count]; i++)
{
NSNumber *latt=[latarray objectAtIndex:i];
NSNumber *lonn=[longarray objectAtIndex:i];
sklat =[[NSString stringWithFormat:#"%#",latt]doubleValue];
sklongi =[[NSString stringWithFormat:#"%#",lonn]doubleValue];
CLLocationCoordinate2D coordinate1 = CLLocationCoordinate2DMake(sklat,sklongi);
// break the string down even further to latitude and longitude fields.
MKMapPoint point = MKMapPointForCoordinate(coordinate1);
// if it is the first point, just use them, since we have nothing to compare to yet.
pointsArray[i] = point;
}
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:[latarray count]];
free(pointsArray);
[mapview addOverlay:self.routeLine];
then i usedd overlay function as
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine] ;
routeLineView.fillColor = [UIColor colorWithRed:0.000 green:5.100 blue:0.100 alpha:1];
routeLineView.strokeColor = [UIColor colorWithRed:0.000 green:5.100 blue:0.100 alpha:1];
routeLineView.lineWidth = 4;
overlayView = routeLineView;
}
return overlayView;
}
I'm new to cocos2d so excuse my ignorance, but I would like to know how to detect when a sprite has been touched and call a method when it has been touched.
I've defined and added my sprite like this:
CCSprite *infoButton = [CCSprite spriteWithFile: #"info.png"];
[infoButton setPosition:CGPointMake(450, 290)];
[menuBG addChild:infoButton];
I've followed various resources but they have been very vague, most of which the sprite was set in its own class.
Thanks in advance.
In regular Cocos2D:
-(void) ccTouchesBegan:(NSSet*)touches withEvent:(id)event
{
CCDirector* director = [CCDirector sharedDirector];
UITouch* touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:director.openGLView];
CGPoint locationGL = [director convertToGL:touchLocation];
CGPoint locationInNodeSpace = [infoButton convertToNodeSpace:locationGL];
CGRect bbox = CGRectMake(0, 0,
infoButton.contentSize.width,
infoButton.contentSize.height);
if (CGRectContainsPoint(bbox, locationInNodeSpace))
{
// code for when user touched infoButton sprite goes here ...
}
}
To demonstrate how much Kobold2D simplifies this over Cocos2D's approach:
-(void) update:(ccTime)delta
{
KKInput* input = [KKInput sharedInput];
if ([input isAnyTouchOnNode:infoButton touchPhase:KKTouchPhaseBegan])
{
// code for when user touched infoButton sprite goes here ...
}
}
Why dont you use CCMenuItemImage?
CCMenuItemImage* info = [CCMenuItemImage itemFromNormalImage:#"info.png" selectedImage:#"info.png" target:self selector:#selector(pressed:)];
CCMenu* menu = [CCMenu menuWithItems:info, nil];
menu.position = ccp(450,290);
[menuBG addChild:menu];
and another function whenever the user pressed the button..
-(void)pressed:(id)sender
{
// whatever you would like to do here...
}
The solution depends on your code architecture. For menu items use xuanweng variant. Alternatively you may check intersection of touch point with sprite bounds in ccTouchBegan method of parent layer. You need to transform touch point to layer space (in common case this transform is identity) and check CGRectContainsPoint ([sprite boundingBox], touchPos)
I made this custom event listener a while ago
This is the CCNode+events.h file(the header file)
//
// CCNode+events.h
// Save the world´s
//
// Created by Sebastian Winbladh on 2013-10-14.
// Copyright (c) 2013 Sebastian Winbladh. All rights reserved.
//
#import "cocos2d.h"
#import <objc/runtime.h>
//We are using CCLayer so we can capture events that occurs on top of it
#interface EventLayer : CCLayer
#property (nonatomic,assign) NSMutableArray *nodes;
#property (nonatomic,assign) void (^callback)(NSArray*nodeArray,NSSet*touches,NSString *event);
+(id)sharedEventLayer:(CCNode *)on callback:(void(^)(NSArray*nodeArray,NSSet*touches,NSString *event))block node:(NSArray *)addNode;
#end
#interface CCNode (props)
#property (nonatimic,assign) id rotationCX;
#property (nonatomic,assign) id rotationCY;
#property (nonatomic,assign) id scaleCX;
#property (nonatomic,assign) id scaleCY;
#end
//Sprite category
//Used to capture sprite cords and eval events
#interface CCNode (events)
-(void)addEventWithEvent:(NSString *)event callback:(void(^)(CCNode*node))back useDispatcher:(BOOL)disp;
#end
This is the CCNode+events.m file(Main file)
//
// Created by Sebastian Winbladh on 2013-10-14.
// Copyright (c) 2013 Sebastian Winbladh. All rights reserved.
//
#import "CCNode+events.h"
#implementation EventLayer
#synthesize callback,nodes;
//Shared instance
+(id)sharedEventLayer:(CCNode *)on callback:(void (^)(NSArray*nodeArray,NSSet*touches,NSString *event))block node:(NSArray *)addNode{
static dispatch_once_t onceToken;
static EventLayer *eventLayer;
dispatch_once(&onceToken, ^{
eventLayer = [[[EventLayer alloc]init]autorelease];
eventLayer.callback = block;
[[eventLayer getParent:on] addChild:eventLayer];
});
[eventLayer.nodes addObject:addNode];
return eventLayer;
}
//Find top level parent child
-(id)getParent:(CCNode*)on{
id ret=on;
BOOL done=false;
while(done == false){
ret = [ret parent];
if(![[ret parent] children]){
done = true;
}
}return ret;
}
-(void)callbackWithEvent:(NSString*)event nsSet:(NSSet *)set{
for(NSArray *lNodeArray in nodes){
self.callback(lNodeArray,set,event);
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self callbackWithEvent:#"touchBegan" nsSet:touches];
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self callbackWithEvent:#"touchEnded" nsSet:touches];
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[self callbackWithEvent:#"touchDrag" nsSet:touches];
}
//Initilize
-(id)init{
if(self = [super init]){
[self setTouchEnabled:YES];
nodes = [[NSMutableArray alloc]init];
}
return self;
}
-(void)dealloc{
//Dealloc nodes
[nodes release];
nodes = nil;
[super dealloc];
}
#end
#implementation CCNode (props)
#dynamic rotationCX,rotationCY,scaleCX,scaleCY;
-(void)setRotationCX:(id)rotationCX{
objc_setAssociatedObject(self, #selector(rotationCX), rotationCX, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)rotationCX{return objc_getAssociatedObject(self, #selector(rotationCX));}
-(void)setRotationCY:(id)rotationCY{
objc_setAssociatedObject(self, #selector(rotationCY), rotationCY, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)rotationCY{return objc_getAssociatedObject(self, #selector(rotationCY));}
//Scales
-(void)setScaleCX:(id)scaleCX{
objc_setAssociatedObject(self, #selector(scaleCX), scaleCX, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)scaleCX{return objc_getAssociatedObject(self, #selector(scaleCX));}
-(void)setScaleCY:(id)scaleCY{
objc_setAssociatedObject(self, #selector(scaleCY), scaleCY, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)scaleCY{return objc_getAssociatedObject(self, #selector(scaleCY));}
#end
#implementation CCNode (events)
-(void)createEventLayerWithEvent:(void(^)(NSArray*nodeArray,NSSet*touches,NSString *event))block node:(NSArray *)addNode{
[EventLayer sharedEventLayer:self callback:block node:addNode];
}
//Get top level child parent
-(id)getParent:(CCNode*)on{
id ret=on;
BOOL done=false;
while(done == false){
ret = [ret parent];
if(![[ret parent] children]){
done = true;
}
}return ret;
}
//This function creates a custom bounding box.
//It takes all childrens in the loop and calculate widths, hights, anchorPoints, positions, scales and rotations
//to get the exact bounding box of the node.
-(void)toggleRotationOnItems:(NSMutableArray *)items func:(NSString*)type{
for(NSArray *item in items){
CCNode *innerItems=[item objectAtIndex:0];
if([type isEqualToString:#"zero"]){
innerItems.rotationX=0;
innerItems.rotationY=0;
}
if([type isEqualToString:#"reset"]){
innerItems.rotationX=((NSNumber*)innerItems.rotationCX).floatValue;
innerItems.rotationY=((NSNumber*)innerItems.rotationCY ).floatValue;
}
}
}
-(CGPoint)getScalesOnChild:(CCNode *)item mother:(CCNode *)items{
CCNode *i=item;
BOOL didFinish=false;
CGPoint scales;
scales.x = item.scaleX;
scales.y = item.scaleY;
while(didFinish == false){
if([i isEqual:items])didFinish=true;
i = [i parent];
scales.x *= i.scaleX;
scales.y *= i.scaleY;
}
return scales;
}
-(BOOL)isVisible:(CCNode*)node mother:(CCNode*)m{
CCNode *i=node;
BOOL didFinish=false;
while(didFinish == false){
if(i.visible == false){
return false;
continue;
}
if([i isEqual:m])didFinish=true;
i = [i parent];
}
return true;
}
-(NSMutableArray*)createBoundingBox:(CCNode *)node{
node.rotationCX = [NSNumber numberWithFloat:node.rotationY ];
node.rotationCY = [NSNumber numberWithFloat:node.rotationY ];
node.scaleCX = [NSNumber numberWithFloat:node.scaleX ];
node.scaleCY = [NSNumber numberWithFloat:node.scaleY];
NSMutableArray *l=[[[NSMutableArray alloc]initWithObjects:node, nil]autorelease];
int c=1;
NSMutableArray *ret=[[[NSMutableArray alloc]init]autorelease];
if(node.visible == true)ret=[[[NSMutableArray alloc]initWithObject:[NSArray arrayWithObjects:node,nil]]autorelease];
//This first loop will loop until the count var is stable//
for(int r=0;r<c;r++){
//This loop will loop thru the child element list//
for(int z=0;z<[[l objectAtIndex:r] children].count;z++){
//Push the element to the return array.
CCNode *nodeItem = ((CCNode*)[[[l objectAtIndex:r] children] objectAtIndex:z]);
nodeItem.rotationCX = [NSNumber numberWithFloat:nodeItem.rotationX ];
nodeItem.rotationCY = [NSNumber numberWithFloat:nodeItem.rotationY ];
nodeItem.scaleCX = [NSNumber numberWithFloat:nodeItem.scaleX ];
nodeItem.scaleCY = [NSNumber numberWithFloat:nodeItem.scaleY];
if([self isVisible:nodeItem mother:node])[ret addObject:[NSArray arrayWithObjects:nodeItem, nil]];
if([[[[[l objectAtIndex:r] children] objectAtIndex:z] children] objectAtIndex:0]){
[l addObject:[[[l objectAtIndex:r] children] objectAtIndex:z]];
c++;
}//IF
}//FOR
}//FOR
NSMutableArray *statickPoints = [[[NSMutableArray alloc]init]autorelease];
NSMutableArray *dynamicPoints = [[[NSMutableArray alloc]init]autorelease];
//Set the rotation to 0 so we can calculate the values better
[self toggleRotationOnItems:ret func:#"zero"];
for(NSArray *items in ret){
//Create variables to hold the node point and the item it self
CGPoint nodePoint;
CCNode *innerItems=[items objectAtIndex:0];
//Check wich node world we will use
nodePoint = [[innerItems parent] convertToWorldSpace:innerItems.position];
CGPoint scales=[self getScalesOnChild:innerItems mother:node];
float widthOffsetP1 = innerItems.contentSize.width*innerItems.anchorPoint.x*scales.x;
float heightOffsetP1 = innerItems.contentSize.height*innerItems.anchorPoint.y*scales.y;
float widthOffsetP1Flip = innerItems.contentSize.width*(1-innerItems.anchorPoint.x)*scales.x;
float heightOffsetP1Flip = innerItems.contentSize.height*(1-innerItems.anchorPoint.y)*scales.y;
//statick positions
CGPoint point1 = CGPointMake(nodePoint.x-widthOffsetP1,nodePoint.y+heightOffsetP1Flip);
CGPoint point2 = CGPointMake(nodePoint.x-widthOffsetP1+innerItems.contentSize.width*scales.x,
nodePoint.y-heightOffsetP1+innerItems.contentSize.height*scales.y);
CGPoint point3 = CGPointMake(nodePoint.x-widthOffsetP1+innerItems.contentSize.width*scales.x,
nodePoint.y-heightOffsetP1);
CGPoint point4 = CGPointMake(nodePoint.x-widthOffsetP1,nodePoint.y-heightOffsetP1);
//Append to array
[statickPoints addObject:[NSArray arrayWithObjects:innerItems,
[NSValue valueWithCGPoint:point1],
[NSValue valueWithCGPoint:point2],
[NSValue valueWithCGPoint:point3],
[NSValue valueWithCGPoint:point4],nil]];
}
//Callculate mother and child rotations
for(NSArray *items in statickPoints){
NSValue *point1 = [items objectAtIndex:1];
NSValue *point2 = [items objectAtIndex:2];
NSValue *point3 = [items objectAtIndex:3];
NSValue *point4 = [items objectAtIndex:4];
int matrix_length=3;
CGPoint points[matrix_length];
points[0] = [point1 CGPointValue];
points[1] = [point2 CGPointValue];
points[2] = [point3 CGPointValue];
points[3] = [point4 CGPointValue];
// Seting the statick positions to the rotations
for(int i=0;i<=matrix_length;i++){
CGPoint nodePoint;
CCNode *item = [items objectAtIndex:0];
BOOL didFinish = false;
while(didFinish == false){
nodePoint = [[item parent] convertToWorldSpace:item.position];
float widthOffsetP1 = (points[i].x - (nodePoint.x));
float heightOffsetP1 = (points[i].y - (nodePoint.y));
float radians1=sqrt(fabs(powf(widthOffsetP1, 2))+fabs(powf(heightOffsetP1,2)));
float newRotation1 =CC_RADIANS_TO_DEGREES(atan2(widthOffsetP1,heightOffsetP1)) + ((NSNumber*)item.rotationCX).floatValue ;
float p1RotApplyed=(radians1) * sinf(CC_DEGREES_TO_RADIANS(newRotation1));
float p2RotApplyed=(radians1) * cosf(CC_DEGREES_TO_RADIANS(newRotation1));
points[i].x-=-p1RotApplyed+(widthOffsetP1);
points[i].y-=-p2RotApplyed+(heightOffsetP1);
if([item isEqual:node]){
didFinish=true;
}
item = [item parent];
}
}
[dynamicPoints addObject:[NSArray arrayWithObjects:[NSValue valueWithCGPoint:points[0]],
[NSValue valueWithCGPoint:points[1]],
[NSValue valueWithCGPoint:points[2]],
[NSValue valueWithCGPoint:points[3]],
nil]];
/* CCLabelTTF *la=[CCLabelTTF labelWithString:#"O" fontName:#"Arial" fontSize:6];
la.anchorPoint=ccp(0.5,0.5);
la.position=points[3];
[[self getParent:node ]addChild:la];
CCLabelTTF *la1=[CCLabelTTF labelWithString:#"O" fontName:#"Arial" fontSize:6];
la1.anchorPoint=ccp(0.5,0.5);
la1.position=points[2];
[[self getParent:node ]addChild:la1];
CCLabelTTF *la2=[CCLabelTTF labelWithString:#"O" fontName:#"Arial" fontSize:6];
la2.anchorPoint=ccp(0.5,0.5);
la2.position=points[1];
[[self getParent:node ]addChild:la2];
CCLabelTTF *la3=[CCLabelTTF labelWithString:#"O" fontName:#"Arial" fontSize:6];
la3.anchorPoint=ccp(0.5,0.5);
la3.position=points[0];
[[self getParent:node ]addChild:la3];*/
}
//Reset rotations
[self toggleRotationOnItems:ret func:#"reset"];
return dynamicPoints;
}
-(BOOL)boxContainsPoint:(CGPoint)p box:(NSMutableArray*)a test:(CCNode*)t{
BOOL returns=false;
NSMutableArray *ret=[[[NSMutableArray alloc]init]autorelease];
for(NSArray *items in a){
NSValue *point1 = [items objectAtIndex:0];
NSValue *point2 = [items objectAtIndex:1];
NSValue *point3 = [items objectAtIndex:2];
NSValue *point4 = [items objectAtIndex:3];
int matrix_length=4;
CGPoint points[matrix_length*2+1];
points[8] = points[4] = points[0] = [point1 CGPointValue];
points[5] = points[1] = [point2 CGPointValue];
points[6] = points[2] = [point3 CGPointValue];
points[7] = points[3] = [point4 CGPointValue];
NSMutableArray *hits=[[[NSMutableArray alloc]init]autorelease];
int p1=0;
float max=0;
for(int i=0;i<=matrix_length;i++){if(points[i].y>=max)p1=i;max=points[i].y;}
for(int i=0;i<matrix_length;i+=2){
CGPoint graphOrigo = ccp(points[p1+i+1].x,points[p1+i].y);
double x = (graphOrigo.x-p.x);
double k = (graphOrigo.y-points[p1+i+1].y)/(graphOrigo.x-points[p1+i].x);
double m = (graphOrigo.y-points[p1+i+1].y);
double y = (-k*x+m);
if((graphOrigo.y-p.y)>(y) && i <=1){
[hits addObject:[NSNumber numberWithBool:YES]];
}else if((graphOrigo.y-p.y)<(y) && i >=1){
[hits addObject:[NSNumber numberWithBool:YES]];
}else{
[hits addObject:[NSNumber numberWithBool:NO]];
}
graphOrigo = ccp(points[p1+i+1].x,points[p1+i+2].y);
y = (graphOrigo.y-p.y);
k = (graphOrigo.x-points[p1+i+2].x)/(graphOrigo.y-points[p1+i+1].y);
m = (graphOrigo.x-points[p1+i+2].x);
x = (-k*y+m);
if((graphOrigo.x-p.x)>(x) && i <=1){
[hits addObject:[NSNumber numberWithBool:YES]];
}else if((graphOrigo.x-p.x)<(x) && i >=1){
[hits addObject:[NSNumber numberWithBool:YES]];
}else{
[hits addObject:[NSNumber numberWithBool:NO]];
}
}
BOOL hit=YES;
for(NSNumber *bools in hits){
if(bools.boolValue == NO){
hit=NO;
}
}
[ret addObject:[NSNumber numberWithBool:hit]];
}
for(NSNumber *b in ret){
if(b.boolValue == YES){
returns=true;
}
}
return returns;
}
-(BOOL)validateToush:(NSSet *)touches nodePoint:(CCNode *)node{
UITouch *touch = [touches anyObject];
id parent = [self getParent:self];
//Touch to global node space
CGPoint touchPoint = [parent convertTouchToNodeSpace:touch];
NSMutableArray *nodeBox = [self createBoundingBox:(CCNode *)node];
//Validating of hit point
if([self boxContainsPoint:touchPoint box:nodeBox test:node])return true;
return false;
}
-(void)addEventWithEvent:(NSString *)event callback:(void (^)(CCNode*node))back useDispatcher:(BOOL)disp{
//Add a cc layer so we can capture toushes
[self createEventLayerWithEvent:^(NSArray*nodeArray,NSSet*touches,NSString *event) {
//Calback block
NSArray *lNodeArray=nodeArray;
CCNode *lNode = [lNodeArray objectAtIndex:0];
void(^nodeBack)(CCNode*node) =[nodeArray objectAtIndex:2];
BOOL disp =((NSNumber *)[nodeArray objectAtIndex:3]).boolValue;
if([[lNodeArray objectAtIndex:1] isEqualToString:#"touchBegan"]){
//Return to callback block
if([event isEqualToString:#"touchBegan"] && [lNode validateToush:touches nodePoint:lNode] || disp==NO && [event isEqualToString:#"touchBegan"])nodeBack((CCNode*)[nodeArray objectAtIndex:0]);
}else if([[lNodeArray objectAtIndex:1] isEqualToString:#"touchEnded"]){
//Return to callback block
if([event isEqualToString:#"touchEnded"] && [lNode validateToush:touches nodePoint:lNode] || disp==NO && [event isEqualToString:#"touchEnded"])nodeBack((CCNode*)[nodeArray objectAtIndex:0]);
}else if([[lNodeArray objectAtIndex:1]isEqualToString:#"touchDrag"]){
//Return to callback block
if([event isEqualToString:#"touchDrag"] && [lNode validateToush:touches nodePoint:lNode] || disp==NO && [event isEqualToString:#"touchDrag"])nodeBack((CCNode*)[nodeArray objectAtIndex:0]);
}
} node:[NSArray arrayWithObjects:self,event,Block_copy(back),[NSNumber numberWithBool:disp], nil]];
}
#end
To use this event listener is very simple
Include the CCSprite+events.h file in your project.
Create a CCNode/CCSprite(yourNode) that you like to add an eventlistener on.
Then your create the event by coding this
[yourNode addEventWithEvent:#"touchBegan" callback:^(CCNode *node) {
NSLog(#"Touch began on node");
} useDispatcher:YES];
The addEventWithEvent parameter takes three types
touchBegan = fired when your finger touches the node
touchEnded = fired when your finger releases the node
touchDrag == fired when moving you finger on the node
The callback takes a callback block that will be fired on the event above.
The useDispatcher takes a BOOL value(YES or NO).
If it get´s set to YES the event will fire on the CCNode.
If it get´s set to NO the event will fire on the screen