So I have been trying to create a menu for a game I have developed.
I am using Cocos2d and the game is set in portrait orientation. The menu.m file that I have written looks like this.
// Import the interfaces
#import "Menu.h"
#import "BankerInfo.h"
// HelloWorldLayer implementation
#implementation MenuLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
MenuLayer *layer = [MenuLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
// ask director the the window size
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *menubackground = [CCSprite spriteWithFile:#"Ninja Menu Background.png"];
menubackground.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:menubackground z:-1];
CCLabelTTF *title = [CCLabelTTF labelWithString:#"Catch It If You Can!" fontName:#"Zapfino" fontSize:22];
title.position = ccp(160, 420);
[self addChild: title];
CCLayer *menuLayer = [[CCLayer alloc] init];
[self addChild:menuLayer];
CCMenuItem *Bankerbutton = [CCMenuItemImage
itemFromNormalImage:#"Bankernotpressed.png"
selectedImage:#"Bankerpressed.png"
target:self
selector:#selector(startBanker:)];
//Bankerbutton.position = ccp(100, 175);
CCMenuItem *Babybutton = [CCMenuItemImage
itemFromNormalImage:#"Babynotpressed.png"
selectedImage:#"Babypressed.png"
target:self
selector:#selector(startBaby:)];
//Babybutton.position = ccp(100, 75);
CCMenuItem *Mommaduckbutton = [CCMenuItemImage
itemFromNormalImage:#"Mommaducknotpressed.png"
selectedImage:#"Mommaduckpressed.png"
target:self
selector:#selector(startMommaduck:)];
//Mommaduckbutton.position = ccp(350, 175);
CCMenuItem *Baseballbutton = [CCMenuItemImage
itemFromNormalImage:#"Baseballnotpressed.png"
selectedImage:#"Baseballpressed.png"
target:self
selector:#selector(startArcher:)];
//Baseballbutton.position = ccp(350, 75);
CCMenuItem *Newtonbutton = [CCMenuItemImage
itemFromNormalImage:#"Newtonnotpressed.png"
selectedImage:#"Newtonpressed.png"
target:self
selector:#selector(startArcher:)];
//Newtonbutton.position = ccp(350, 75);
CCMenu *menu = [CCMenu menuWithItems: Bankerbutton, Babybutton, Mommaduckbutton, Baseballbutton, Newtonbutton, nil];
menu.position = ccp(winSize.width/2, (winSize.height/2)-30);
[menu alignItemsInRows:
[NSNumber numberWithInt:2], [NSNumber numberWithInt:2], nil];
[menuLayer addChild: menu];
}
return self;
}
- (void) startBanker: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[BankerInfoLayer scene]];
}
/*- (void) startBaby: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Soldier scene]];
}
- (void) startMommaduck: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Mage scene]];
}
- (void) startBaseball: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Archer scene]];
}
- (void) startNewton: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Archer scene]];
}
*/
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
[super dealloc];
}
#end
And the error I'm getting looks like this.
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '+[NSInvocation invocationWithMethodSignature:]:
method signature argument cannot be nil'
Any Ideas?
The error states that thi is happening because of a bad call to an unexisting method signature. If you provide the functions used on the menu creation, does it still crash?
STEP 1: Make sure that the baseball button and newton button direct to the right selector, and not just the "startArcher:" that doesnt exist.
CCMenuItem *Baseballbutton = [CCMenuItemImage
itemFromNormalImage:#"Baseballnotpressed.png"
selectedImage:#"Baseballpressed.png"
target:self
selector:#selector(startBaseball:)]; // CHANGED HERE
//Baseballbutton.position = ccp(350, 75);
CCMenuItem *Newtonbutton = [CCMenuItemImage
itemFromNormalImage:#"Newtonnotpressed.png"
selectedImage:#"Newtonpressed.png"
target:self
selector:#selector(startNewton:)]; // CHANGED HERE
STEP 2: Uncomment the functions so you actually have valid selectors
- (void) startBanker: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[BankerInfoLayer scene]];
}
- (void) startBaby: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Soldier scene]];
}
- (void) startMommaduck: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Mage scene]];
}
- (void) startBaseball: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Archer scene]];
}
- (void) startNewton: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Backgroundinfo_Archer scene]];
}
Related
I'm building a game with Cocos2d for iPhone, and right now I'm trying to get Touch input working. I've enabled touch response on an independent control layer in a multi-layer scene, and it's working fine - except it ONLY fires the touch methods if the touch was on top the sprite that I have on a separate layer(the separate layer is actually just a node). I don't have any other on-screen content aside from that sprite.
here's my control Layer implementation:
#import "ControlLayer2.h"
extern int CONTROL_LAYER_TAG;
#implementation ControlLayer2
+(void)ControlLayer2WithParentNode:(CCNode *)parentNode{
ControlLayer2 *control = [[self alloc] init];
[parentNode addChild:control z:0 tag:CONTROL_LAYER_TAG];
}
-(id)init{
if (self=[super init]){
[[[CCDirector sharedDirector]touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
return self;
}
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CCLOG(#"touchbegan");
return YES;
}
#end
and here's the layer with the child node that has a sprite inside it:
extern int PLAYER_LAYER_TAG;
int PLAYER_TAG = 1;
#implementation PlayerLayer
//reduces initializing and adding to the gamescene to one line for ease of use
+(void)PlayerLayerWithParentNode:(CCNode *)parentNode{
PlayerLayer *layer = [[PlayerLayer alloc] init];
[parentNode addChild:layer z:1 tag:PLAYER_LAYER_TAG];
}
-(id)init{
if(self = [super init]){
//add the player to the layer, know what I'm sayer(ing)?
[Player playerWithParentNode:self];
}
return self;
}
#end
and finally, the scene that contains them both:
int PLAYER_LAYER_TAG = 1;
int CONTROL_LAYER_TAG = 2;
#implementation GameScene
+(id)scene{
CCScene *scene = [CCScene node];
CCLayer *layer = [GameScene node];
[scene addChild:layer z:0 tag:0];
return scene;
}
-(id)init{
if(self = [super init]){
//[[[CCDirector sharedDirector]touchDispatcher] addTargetedDelegate:[self getChildByTag:0] priority:0 swallowsTouches:YES];
//add the player layer to the game scene (this contains the player sprite)
[ControlLayer2 ControlLayer2WithParentNode:self];
[PlayerLayer PlayerLayerWithParentNode:self];
}
return self;
}
#end
how can I make it so that the control layer responds to ALL touch input?
In init method add this code.
self.touchEnabled = YES;
And use this ccTouchesBegan
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//handle touch
}
Remove this line in your code:
[[[CCDirector sharedDirector]touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
UPDATE: HERE IS FULL CODE
How to add a magnifier to custom control? Control is a child of UIView. (It's a UIWebView - but native magnification functionality doesn't work at some pages.)
UPDATED:
Maybe it's possible to force a draw of magnifier on UIWebView?
1. Add the following files to your project:
MagnifierView.h:
//
// MagnifierView.h
// SimplerMaskTest
//
#import <UIKit/UIKit.h>
#interface MagnifierView : UIView {
UIView *viewToMagnify;
CGPoint touchPoint;
}
#property (nonatomic, retain) UIView *viewToMagnify;
#property (assign) CGPoint touchPoint;
#end
MagnifierView.m:
//
// MagnifierView.m
// SimplerMaskTest
//
#import "MagnifierView.h"
#import <QuartzCore/QuartzCore.h>
#implementation MagnifierView
#synthesize viewToMagnify;
#dynamic touchPoint;
- (id)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame radius:118];
}
- (id)initWithFrame:(CGRect)frame radius:(int)r {
int radius = r;
if ((self = [super initWithFrame:CGRectMake(0, 0, radius, radius)])) {
//Make the layer circular.
self.layer.cornerRadius = radius / 2;
self.layer.masksToBounds = YES;
}
return self;
}
- (void)setTouchPoint:(CGPoint)pt {
touchPoint = pt;
// whenever touchPoint is set, update the position of the magnifier (to just above what's being magnified)
self.center = CGPointMake(pt.x, pt.y-66);
}
- (CGPoint)getTouchPoint {
return touchPoint;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect bounds = self.bounds;
CGImageRef mask = [UIImage imageNamed: #"loupe-mask#2x.png"].CGImage;
UIImage *glass = [UIImage imageNamed: #"loupe-hi#2x.png"];
CGContextSaveGState(context);
CGContextClipToMask(context, bounds, mask);
CGContextFillRect(context, bounds);
CGContextScaleCTM(context, 1.2, 1.2);
//draw your subject view here
CGContextTranslateCTM(context,1*(self.frame.size.width*0.5),1*(self.frame.size.height*0.5));
//CGContextScaleCTM(context, 1.5, 1.5);
CGContextTranslateCTM(context,-1*(touchPoint.x),-1*(touchPoint.y));
[self.viewToMagnify.layer renderInContext:context];
CGContextRestoreGState(context);
[glass drawInRect: bounds];
}
- (void)dealloc {
[viewToMagnify release];
[super dealloc];
}
#end
TouchReader.h:
//
// TouchReader.h
// SimplerMaskTest
//
#import <UIKit/UIKit.h>
#import "MagnifierView.h"
#interface TouchReader : UIView {
NSTimer *touchTimer;
MagnifierView *loop;
}
#property (nonatomic, retain) NSTimer *touchTimer;
- (void)addLoop;
- (void)handleAction:(id)timerObj;
#end
TouchReader.m:
//
// TouchReader.m
// SimplerMaskTest
//
#import "TouchReader.h"
#import "MagnifierView.h"
#implementation TouchReader
#synthesize touchTimer;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.touchTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(addLoop) userInfo:nil repeats:NO];
// just create one loop and re-use it.
if (loop == nil) {
loop = [[MagnifierView alloc] init];
loop.viewToMagnify = self;
}
UITouch *touch = [touches anyObject];
loop.touchPoint = [touch locationInView:self];
[loop setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self handleAction:touches];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self.touchTimer invalidate];
self.touchTimer = nil;
[loop removeFromSuperview];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self.touchTimer invalidate];
self.touchTimer = nil;
[loop removeFromSuperview];
}
- (void)addLoop {
// add the loop to the superview. if we add it to the view it magnifies, it'll magnify itself!
[self.superview addSubview:loop];
// here, we could do some nice animation instead of just adding the subview...
}
- (void)handleAction:(id)timerObj {
NSSet *touches = timerObj;
UITouch *touch = [touches anyObject];
loop.touchPoint = [touch locationInView:self];
[loop setNeedsDisplay];
}
- (void)dealloc {
[loop release];
loop = nil;
[super dealloc];
}
#end
Based on: http://coffeeshopped.com/2010/03/a-simpler-magnifying-glass-loupe-view-for-the-iphone
2. Add the following images:
Used images on the code:
loupe-hi#2x.png:
loupe-mask#2x.png:
Original but centered images with a shadow (not used at this moment):
loupe-shadow-hi#2x.png:
loupe-shadow-mask#2x.png:
3. Replace the main UIView on your xib-file by TouchReader
The magnifier will work automaticaly except controls that captures touch events themselfs (for example, UIWebView). And the code above doesn't support the images with a shadow. Please add new answer to the qustion if you successfully fix this issue.
UPDATED:
Change the following code to add UIWebView support. UIView should remain UIView.
#interface TouchReader : UILongPressGestureRecognizer
And add a gesture to webView:
TouchReader* gestureMagnifier = [[[TouchReader alloc] initWithTarget:self action:#selector(handleMagnifier:)] autorelease];
gestureMagnifier.webView = editSource;
gestureMagnifier.delegate = self;
gestureMagnifier.minimumPressDuration = 0.5;
[webView addGestureRecognizer:gestureMagnifier];
TouchReader.h:
//- (void)handleAction:(id)timerObj;
-(void) handleGestureAction:(CGPoint)location;
TouchReader.m:
-(void)awakeFromNib
{
UILongPressGestureRecognizer * longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self addGestureRecognizer:longPressGesture];
}
-(void)handleGesture:(UILongPressGestureRecognizer *)longPressGesture
{
CGPoint location = [longPressGesture locationInView:self];
switch (longPressGesture.state) {
case UIGestureRecognizerStateBegan:
self.touchTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(addLoop)
userInfo:nil
repeats:NO];
// just create one loop and re-use it.
if(loop == nil){
loop = [[MagnifierView alloc] init];
loop.viewToMagnify = self;
}
loop.touchPoint = location;
[loop setNeedsDisplay];
break;
case UIGestureRecognizerStateChanged:
[self handleGestureAction:location];
break;
case UIGestureRecognizerStateEnded:
[self.touchTimer invalidate];
self.touchTimer = nil;
[loop removeFromSuperview];
loop=nil;
break;
default:
break;
}
}
- (void)addLoop {
// add the loop to the superview. if we add it to the view it magnifies, it'll magnify itself!
[self.superview addSubview:loop];
}
-(void) handleGestureAction:(CGPoint)location
{
loop.touchPoint = location;
[loop setNeedsDisplay];
}
You don't need the touches... methods any more.
i have install cocos2d v2.0, and i am working a little on it, to see what changed against v1, i have create a simple cocos2d + box2d project, and i run it and all work fine, i have deleted the IntroLayer and the Helloworld Layer, i have tried to display a simple background layer, so i have do this:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface BackgroundLayer : CCLayer
#end
#import "BackgroundLayer.h"
#implementation BackgroundLayer
-(id)init {
self = [super init];
if (self != nil) {
CCSprite *backgroundImage = [CCSprite spriteWithFile:#"background.png"];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
backgroundImage.position = ccp(screenSize.width/2, screenSize.height/2);
[self addChild:backgroundImage z:0 tag:0];
}
return self;
}
#end
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "BackgroundLayer.h"
#interface GameScene : CCScene
#end
#import "GameScene.h"
#implementation GameScene
-(id)init {
self = [super init];
if (self != nil) {
BackgroundLayer *backgroundLayer = [BackgroundLayer node];
[self addChild:backgroundLayer z:0];
}
return self;
}
#end
and then in the app delegate i have changed this:
[director_ pushScene: [IntroLayer scene]];
in this:
[director_ pushScene: [GameScene node]];
but the seem scaled of the 0.5, i have created the hd and the not hd image, for retina and not retina, what i wrong? this is the result:
http://img706.imageshack.us/img706/4778/schermata072456124alle1.png
EDIT:
if i change the BackgroundLayer.m in this way, all work fine:
#implementation BackgroundLayer
/*-(id)init {
self = [super init];
if (self != nil) {
CCSprite *backgroundImage = [CCSprite spriteWithFile:#"background.png"];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
backgroundImage.position = ccp(screenSize.width/2, screenSize.height/2);
[self addChild:backgroundImage z:0 tag:0];
}
return self;
}*/
-(void) onEnter
{
[super onEnter];
CCSprite *backgroundImage = [CCSprite spriteWithFile:#"background.png"];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
backgroundImage.position = ccp(screenSize.width/2, screenSize.height/2);
[self addChild:backgroundImage z:0 tag:0];
}
#end
anyone can explain me why? i remember that in the old version of cocos2d i can add the layer in the init method...
Use this style, worked in cocos2d 2.0 also.
#interface GameScene : CCLayer
{
}
+(CCScene *) scene;
#end
#import "GameScene.h"
#implementation GameScene
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
GameScene *gameScenelayer = [GameScene node];
// add layer as a child to scene
[scene addChild: gameScenelayer];
// return the scene
return scene;
}
-(id)init {
self = [super init];
if (self != nil) {
CCSprite *backgroundImage = [CCSprite spriteWithFile:#"background.png"];
CGSize screenSize = [[CCDirector sharedDirector] winSize];
backgroundImage.position = ccp(screenSize.width/2, screenSize.height/2);
[self addChild:backgroundImage z:0 tag:0];
}
return self;
}
#end
//Call this
[director_ pushScene: [GameScene scene]];
I have a CCScene. In its right side I need to have a UIScrollView with some menu elements. I did it this way as I have explained in this previous question Cocos2d and UIScrollView
here is the method creating my scene
+(id) scene: (int) wld{
CCScene *scene = [CCScene node];
LevelsMenu *layer = [LevelsMenu node];
layer = [layer init:wld];
[scene addChild: layer];
[layer setScrollView:[LevelMenuControlView alloc]];
[[[CCDirector sharedDirector] openGLView] addSubview:layer.scrollView.view];
return scene;
}
notice that LevelMenuControlView is just an UIViewController implemented this way:
- (void)loadView{
LevelMenuView *scrollView = [[LevelMenuView alloc] initWithFrame:[UIScreen
mainScreen].applicationFrame];
scrollView.contentSize = CGSizeMake(862, 480);
scrollView.delegate = scrollView;
[scrollView setUserInteractionEnabled:TRUE];
[scrollView setScrollEnabled:TRUE];
[scrollView setShowsVerticalScrollIndicator:FALSE];
[scrollView setShowsHorizontalScrollIndicator:FALSE];
self.view = scrollView;
[scrollView release];
}
While LevelMenuView is the UIScrollView containing the menu elements
It works quite fine. Now the problem is that in the left side of the scene I have a sprite animation that, If I do not touch the screen fine but as soon as I drag the scroll view up or down stops or goes at the same speed of my scrolling finger!!!
Any idea?
I have found this link where someone already experienced the same problem and posted a solution which actually works
http://www.cocos2d-iphone.org/forum/topic/11645
It basically consists in adding this code to the scroll view:
// This should go in your interface.
NSTimer *timer;
// Override
- (void)setContentOffset:(CGPoint)contentOffset {
// UIScrollView uses UITrackingRunLoopMode.
// NSLog([[NSRunLoop currentRunLoop] currentMode]);
// If we're dragging, mainLoop is going to freeze.
if (self.dragging && !self.decelerating) {
// Make sure we haven't already created our timer.
if (timer == nil) {
// Schedule a new UITrackingRunLoopModes timer, to fill in for
CCDirector while we drag.
timer = [NSTimer scheduledTimerWithTimeInterval:[[CCDirector sharedDirector] animationInterval] target:self selector:#selector(animateWhileDragging) userInfo:nil repeats:YES];
// This could also be NSRunLoopCommonModes
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopModes];
}
}
// If we're decelerating, mainLoop is going to stutter.
if (self.decelerating && !self.dragging) {
// Make sure we haven't already created our timer.
if (timer == nil) {
// Schedule a new UITrackingRunLoopMode timer, to fill in for CCDirector while we decellerate.
timer = [NSTimer scheduledTimerWithTimeInterval:[[CCDirector sharedDirector] animationInterval] target:self selector:#selector(animateWhileDecellerating) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
}
}
[super setContentOffset:contentOffset];
}
- (void)animateWhileDragging {
// Draw.
[[CCDirector sharedDirector] drawScene];
if (!self.dragging) {
// Don't need this timer anymore.
[timer invalidate];
timer = nil;
}
}
- (void)animateWhileDecellerating {
// Draw.
[[CCDirector sharedDirector] drawScene];
if (!self.decelerating) {
// Don't need this timer anymore.
[timer invalidate];
timer = nil;
}
}
Thanks a lot to these guys
Today i got a cocos2d question!
I got a few shapes and the space-manager set up in my .m file by using nodes:
- (CCNode*) createBlockAt:(cpVect)pt
width:(int)w
height:(int)h
mass:(int)mass
{
cpShape *shape = [smgr addRectAt:pt mass:mass width:w height:h rotation:0];
cpShapeNode *node = [cpShapeNode nodeWithShape:shape];
node.color = ccc3(56+rand()%200, 56+rand()%200, 56+rand()%200);
[self addChild:node];
return node;
}
- (CCNode*) createCircleAt:(cpVect)pt
mass:(int)mass
radius:(int)radius
{
cpShape *shape = [smgr addCircleAt:pt mass:mass radius:radius];
cpShapeNode *node1 = [cpShapeNode nodeWithShape:shape];
CCSprite *sprt = [CCSprite spriteWithFile:#"fire.png"];
node1.color = ccc3(56+rand()%200, 56+rand()%200, 56+rand()%200);
[self addChild:node1];
return node1;
}
then i actually make the shapes, set up a background, alloc and start the space-manager in my init method:
- (id) init
{
[super init];
CCSprite *background = [CCSprite spriteWithFile:#"BGP.png"];
background.position = ccp(240,160);
[self addChild:background];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
//allocate our space manager
smgr = [[SpaceManagerCocos2d alloc] init];
smgr.constantDt = 1/55.0;
[smgr addWindowContainmentWithFriction:1.0 elasticity:1.0 inset:cpvzero];
[self createBlockAt:cpv(160,50) width:50 height:100 mass:100];
[self createBlockAt:cpv(320,50) width:50 height:100 mass:100];
[self createBlockAt:cpv(240,110) width:210 height:20 mass:100];
[self createCircleAt:cpv(240,140) mass:25 radius:20];
[smgr start];
return self;
}
Now, i want a shape to be removed if it's touched. What is the best way to do that???
I hope that somebody out there can help me :)
Edit:
Plz somebody, start a bounty! Or i never get this answered :(
-DD
How about like this?
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint point = [self convertTouchToNodeSpace:touch];
cpShape *shape = [smgr getShapeAt:point];
if (shape) {
[self removeChild:shape->data cleanup:YES];
[smgr removeAndFreeShape:shape];
}
return YES;
}