can't remove target from the self in cocos2d-iphone - cocos2d-iphone

I use following code to create some sprites
-(void)dologic
{
for (int i = 0; i < 3; i ++) {
CCSprite *target = [CCSprite spriteWithFile:#"pig.png"];
int x = arc4random() % 320;
int y = arc4random() % 300;
target.position = ccp(x, y);
[self addChild:target];
[_targets addObject:target];//_targets is nsmutablearray
}
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [self convertTouchToNodeSpace: touch];
for (CCSprite *target in _targets) {
if (CGRectContainsPoint(target.boundingBox, location)) {
[_targets removeAllObjects];
[self removeChild:target cleanup:YES];
[self dologic];
}
}
when touch any sprite, all sprites will be removed from the self first, and then call dologic to create three new sprites again, but my code can only remove the target that i touched, how can i remove all sprites when i touch the screen?

First off, you are modifying the array while iterating it, which is not a good practice.
If you want to remove all targets upon touching any of them, you can try this:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [self convertTouchToNodeSpace: touch];
BOOL touchedASprite = NO;
for (int i = 0; i < [_targets count] && !touchedASprite; ++i) {
if (CGRectContainsPoint((CCSprite*)[_targets objectAtIndex:i].boundingBox, location)) {
touchedASprite = YES;
}
}
if (touchedASprite) {
for (CCSprite *target in _targets) {
[self removeChild:target cleanup:YES];
}
[_targets removeAllObjects];
[self doLogic];
}
}

When you want to remove objects in a array while browsing all objects of it, you should do like this:
for (int i = (int)_targets.count - 1 ; i >= 0 ; i--) {
CCSprite *target = _targets[i];
if (CGRectContainsPoint(target.boundingBox, location)) {
[_targets removeAllObjects];
[self removeChild:target cleanup:YES];
[self dologic];
}
}
Be careful: [NSArray count] returns a unsigned number, when [NSArray count] returns 0, ([NSArray count]-1) is NOT -1, should cast it to int

Related

Cocos2d Using 1 class for multiple enemies Score error

Thank you for taking the time to look at my question, As I am very new to programming any help or pointers in the right direction is much appreciated.
Overview...
I have a simple game I am trying to create and it includes a class for 'Ball' sprite that is fired from the left of the screen to the right. The speed at which this "Ball" sprite is created is random and each time the "Ball" moves past the right of the screen a point is added to the score.
Problem....
The problem I have is when 2 "Balls" fire at almost the same time (which happens some times as its random) they pass the right hand of the screen less then a second apart and when this happens it only seems to add 1 when it should be adding 2 to the score (as 2 balls has passed the right side).
Below is the code for my Ball launcher class (use this class to call the ball randomly).
If you have used or gone through 'Ray Wenderlichs' Learn Cocos2D then allot of this will look familiar as after going through his book I have tried to edit his code to do what I want (to me after reading the book its the best way to learn, by messing with the code etc).
#implementation BL
#synthesize delegate;
#synthesize lauchingAnim;
#synthesize afterlauchingAnim;
-(void) dealloc {
delegate = nil;
[lauchingAnim release];
[afterlauchingAnim release];
[super dealloc];
}
//--The below shootPhaser method takes the current direction the launcher is facing and asks the delegate (gameplaylayer) to create the ball moving in that direction.
//--The below createPhaserWithDirection method was declared (created) in the GamePlayLayerDelegate protocol.
-(void)shootPhaser {
CGPoint phaserFiringPosition;
PhaserDirection phaserDir;
CGPoint position = [self position];
float xPosition = position.x + position.x * 0.51f;
float yPosition = position.y + position.y * 0.045f;
{
phaserDir = kDirectionRight;
}
phaserFiringPosition = ccp(xPosition, yPosition);
[delegate createPhaserWithDirection:phaserDir andPosition:phaserFiringPosition];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
characterState = newState;
switch (newState) {
case kStatespawning:
// CCLOG(#“launcher->Changing State to Spwaning");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#“lancher_1.png"]];
break;
case kStateIdle:
// CCLOG(#“laucher->Changing state to idle");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"lancher_1.png"]];
break;
case kStateFiring:
// CCLOG(#“launcher->Changing State to firing");
action = [CCSequence actions:
[CCAnimate actionWithAnimation:lauchingAnim],
[CCCallFunc actionWithTarget:self
selector:#selector(shootPhaser)],
[CCAnimate actionWithAnimation:afterlauchingAnim],
[CCDelayTime actionWithDuration:2.0f],
nil];
lauchingAnim.restoreOriginalFrame = NO;
afterlauchingAnim.restoreOriginalFrame = NO;
[self changeState:kStateIdle];
break;
case kStateDead:
CCLOG(#“launcher->changing state to dead");
break;
default:
CCLOG(#"unhandled state %d in launcher", newState);
break;
}
if (action !=nil) {
[self runAction:action];
}
}
-(void)updateStateWithDeltaTime: (ccTime)deltaTime andListOfGameObjects:(CCArray*)listOfGameObjects {
if (characterState == kStateFiring) {
// 5
if (characterState != kStateFiring) {
// If RadarDish is NOT already taking Damage
[self changeState:kStateFiring];
return;
}
}
if ((([self numberOfRunningActions] == 0) && (characterState != kStateDead)) ) {
// CCLOG(#"launcher Going to Idle!!!");
[self changeState:kStateIdle];
return;
}
}
-(void)initAnimations {
[self setLauchingAnim:[self loadPlistForAnimationWithName:#"lauchingAnim" andClassName:NSStringFromClass([self class])]];
[self setAfterlauchingAnim:[self loadPlistForAnimationWithName:#"afterlauchingAnim" andClassName:NSStringFromClass([self class])]];
}
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(#"### Laauncher initialized");
[self initAnimations];
characterHealth = 3.0f;
gameObjectType = kBallLaucher;
// 3
[self changeState:kStateIdle];
}
}
return self;
}
#end
Below is the code for my "Ball" class...
#import “Ball.h"
#implementation Ball
#synthesize delegate;
#synthesize myDirection;
#synthesize travelingAnim;
#synthesize ScoreAnim;
-(void) dealloc {
delegate = nil;
[travelingAnim release];
[ScoreAnim release];
[super dealloc];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
[self setCharacterState:newState];
CGSize screenSize1 = [CCDirector sharedDirector].winSize;
CGPoint position = [self position];
CGPoint endPosition = ccp(screenSize1.width*1.5f, screenSize1.height*0.20f);
id action = nil;
//id action1 = nil;
switch (newState) {
case kStatespawning:
CCLOG(#“Spawning Ball");
[self setDisplayFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:#"Ball_1.png"]];
break;
case kStateTravelling: {
movementAction = [CCMoveTo actionWithDuration:5.0f
position:endPosition];
}
break;
case kStateScore:
PLAYSOUNDEFFECT(SCORE);
CCLOG(#“Ball Past Left Of Screen => Add 1 to Score");
action = [CCSequence actions:
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
break;
default:
CCLOG(#“Ball -> Unknown CharState %d",
characterState);
break;
}
if (action !=nil)
[self runAction:action];
}
-(void)removeSelf{
CCLOG(#"Removing Ball Object Has Scored.");
[self setVisible:NO];
[self removeFromParentAndCleanup:YES];
return;
}
-(void)updateStateWithDeltaTime:(ccTime)deltaTime andListOfGameObjects:(CCArray *)listOfGameObjects {
CGPoint currentSpitePosition = [self position];
CGSize screenSize = [CCDirector sharedDirector].winSize;
if (currentSpitePosition.x > screenSize.width*1.1f) {{
[self changeState:kStateScore];
}
}
return;
}
if ([self numberOfRunningActions] == 0) {
if (characterState == kStatespawning) {
[self changeState:kStateTravelling];
return;
}
}
}
-(void)initAnimations {
[self setTravelingAnim:[self loadPlistForAnimationWithName:#"travelingAnim" andClassName:NSStringFromClass([self class])]];
[self setScoreAnim:[self loadPlistForAnimationWithName:#"ScoreAnim" andClassName:NSStringFromClass([self class])]];
}
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(#"### Ball Initialised");
[self initAnimations];
characterHealth = 3.0f;
gameObjectType = kEnemyTypeBall;
[self changeState:kStatespawning];
}
}
return self;
}
#end
Below is the code for my "GameplayLayer" class...
#import "GamePlayLayer.h"
#import “Ball.h"
#import “BL.h"
#implementation GamePlayLayer
#synthesize delegate;
-(void) dealloc {
delegate = nil;
[super dealloc];
}
-(void) update:(ccTime)deltaTime {
CCArray *listOfGameObjects =
[sceneSpriteBatchNode children];
for (GameCharacter *tempChar in listOfGameObjects) {
[tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects];
}
GameCharacter *tempChar = (GameCharacter*)[sceneSpriteBatchNode
getChildByTag:kEnemyTypeBall];
if ([tempChar characterState] == kStateScore) <==HERE I AM SEEING IF THE BALL HAS SCORED - THIS IS ALSO WHERE I THINK I MAY BE GOING WRONG SOMEHOW.
{
CCLOG(#"Add 1 Points To Score");
[self addPoint];
return;
}
}
-(void)addPoint
{
score = score + 1;
[scoreLabel setString:[NSString stringWithFormat:#"$%i", score]]; <===ADDING THE POINT TO THE SCORE
return;
}
-(void) createObjectOfType: (GameObjectType)objectType
withHealth:(int)initialHealth atLocation:(CGPoint)spawnLocation withZValue:(int)ZValue {
if (kBallLaucher == objectType) {
CCLOG(#"Creating launcher Object");
BL *ballLauncher = [[[BL alloc] init] initWithSpriteFrameName:#“launcher_1.png"];
[ballLauncher setCharacterHealth:initialHealth];
[ballLauncher setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:tBT z:ZValue tag:kBallLaucher ];
[ballLauncher setDelegate:self];
[ballLauncher release];
}
}
**BELOW IS HOW I CONTROL WHEN THE BALL IS FIRED**
-(void)ChangeStateLaucher:(int)brandnewState withState:(CharacterStates)newState andObject:(GameObjectType)objectType; {
BL *bL = (BL*)
[sceneSpriteBatchNode getChildByTag:kBallLaucher];
int x = (arc4random() % 2);
if (x==0) {
CCLOG(#"Start Laucher Firing");
[bL changeState:kStateFiring];
count = 0;
}
if (x==1) {
CCLOG(#"No Laucher Firing");
count = count + 1;
if (count == 2) {
CCLOG(#"No Laucher Firing x2 - Start Laucher Firing");
[bL changeState:kStateFiring];
} else if (count > 3) {
CCLOG(#"No Laucher Firing x3 - Start Laucher Firing");
[bL changeState:kStateFiring];
}
}
[delegate ChangeStateLaucher:x withState:kStateFiring andObject:objectType];
}
-(void)createPhaserWithDirection:(PhaserDirection)phaserDirection andPosition:(CGPoint)spawnPosition {
CCLOG(#"Creating Ball from Gameplay Layer");
Ball *ballSprite = [[Ball alloc]initWithSpriteFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:#"Ball_1.png"]];
[ballSprite setPosition:spawnPosition];
[ballSprite setMyDirection:phaserDirection];
[ballSprite setCharacterState:kStatespawning];
[ballSprite setCharacterHealth:3.0f];
[sceneSpriteBatchNode addChild:ballSprite z:20 tag:kEnemyTypeBall];
[ballSprite release];
}
-(id)init {
self = [super init];
if (self !=nil) {
CGSize screenSize = [CCDirector sharedDirector]. winSize;
self.TouchEnabled = YES;
srandom(arc4random()); // Seeds the random number generator
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"scene1atlas.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"scene1atlas.png"]; // 2
[self createObjectOfType:kBallLaucher withHealth:3 atLocation:ccp(screenSize.width * 0.05f, screenSize.height * 0.822f) withZValue:10];
[gameBeginLabel setPosition:ccp(screenSize.width/2,screenSize.height/2)]; // 2
[self addChild:gameBeginLabel]; // 3
id labelAction = [CCSpawn actions:
[CCFadeOut actionWithDuration:2.5f],
nil]; // 4
[gameBeginLabel runAction:labelAction];
lives = 3;
scoreLabel = [CCLabelBMFont labelWithString:#"$0"
fntFile:#“BallTest.fnt"];
scoreLabel.position = ccp(screenSize.width * 0.5f, screenSize.height * 0.9f);
[self addChild:scoreLabel
z:-1 tag:kNewScoreTagValue];
[self scheduleUpdate];
}
return self;
}
#end
Once again I would like to thank anyone that has taken the time to look at this question regardless if you have posted a pointer or answer or not.
Thanks.
I think that when there are more than one Ball objects on the screen, the GamePlayLayer update method is unable to pick up on the state change on one of the balls at times because that ball is removed as soon as it enters kStateScore.
If you add a certain delay before removing the ball , the update method should pick up the changes in all the balls and your problem should be resolved.
In your Ball.m -(void)changeState:(CharacterStates)newState function , modify the action on state kStateScore like
action = [CCSequence actions:[CCDelayTime actionWithDuration:0.2],
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
Try this out and let me know if this worked for you!
EDIT
The above solution would end up adding more than one point as the ball would remain in kStateScore state for a long time due to delay. In order to counter that problem , we can introduce a new state call kStateDead and change the ball state to kStateDead after adding the point. This will ensure a point is added only once and also we can put the responsibility of removing the ball in kStateDead state. The new code would like as follows :
Ball.m
case kStateScore:
PLAYSOUNDEFFECT(SCORE);
CCLOG(#“Ball Past Left Of Screen => Add 1 to Score");
break;
case kStateDead:
action = [CCSequence actions:
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
default:
CCLOG(#“Ball -> Unknown CharState %d",
characterState);
break;
and in your Gameplayer.m
if ([tempChar characterState] == kStateScore) <==HERE I AM SEEING IF THE BALL HAS SCORED - THIS IS ALSO WHERE I THINK I MAY BE GOING WRONG SOMEHOW.
{
CCLOG(#"Add 1 Points To Score");
[self addPoint];
[tempChar changeState:kStateDead]; //change the state to dead after the point is added
return;
}

cocos2d multi-touch and CCMotionStreak

I'm trying to use multitouch in my app....but I have to display a streak when the finger move on the screen... but I see only ONE streak, instead of TWO! how can I create and move 2 streaks together??
Here is my code:
-(void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
for (int n=0; n < [allTouches count]; n++)
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:n];
CGPoint touchLoc = [touch locationInNode:self];
streak = [CCMotionStreak streakWithFade:0.3 minSeg:20 width:13 color:[CCColor colorWithUIColor:[UIColor whiteColor]] textureFilename:#"scia.png"];
[streak setPosition:touchLoc];
[self addChild:streak z:30];
}
}
-(void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
for (int n=0; n < [allTouches count]; n++)
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:n];
CGPoint touchLoc = [touch locationInNode:self];
[streak setPosition:touchLoc];
[self detectObjects:touchLoc];
}
}
for multitouch inside CCLayer you can use multitouch by CCStandardTouchDelegate function.
build in cocos2d
if you are looking for Fruit Ninja Blade effect.. use CCBlade instead of CCMotionStreak
https://github.com/hiepnd/CCBlade
/// .h File
CFMutableDictionaryRef map;
// .m File
void releaseStreak(CFAllocatorRef allocator, const void *value)
{
[(CCMotionStreak*)value removeFromParentAndCleanup:YES];
}
CFDictionaryValueCallBacks valueCallbacks = {
0,
NULL,
releaseStreak,
NULL,
NULL
};
-(id) init
{
if( (self=[super init])) {
isTouchEnabled_ = 1;
[[[CCDirector sharedDirector] openGLView] setMultipleTouchEnabled:YES];
map = CFDictionaryCreateMutable(NULL,0,NULL,&valueCallbacks);
}
}
- (void) ccTouchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
for (UITouch *touch in touches) {
CCMotionStreak *streak = [CCMotionStreak streakWithFade:0.3 minSeg:20 width:13 color:[CCColor colorWithUIColor:[UIColor whiteColor]] textureFilename:#"scia.png"];
CFDictionaryAddValue(map,touch,streak);
CGPoint pos = [touch locationInView:touch.view];
pos = [[CCDirector sharedDirector] convertToGL:pos];
[streak setPosition: pos];
[self addChild:streak z:30];
}
}
- (void) ccTouchesMoved:(NSSet *) touches withEvent:(UIEvent *) event{
{
for (UITouch *touch in touches) {
CGPoint pos = [touch locationInView:touch.view];
pos = [[CCDirector sharedDirector] convertToGL:pos];
CCMotionStreak *_streak = (CCMotionStreak *)CFDictionaryGetValue(map, touch);
[streak setPosition:pos];
[self detectObjects:pos];
}
}
- (void) ccTouchesEnded:(NSSet *) touches withEvent:(UIEvent *) event{
for (UITouch *touch in touches) {
CCMotionStreak *_streak = (CCMotionStreak *)CFDictionaryGetValue(map, touch);
CFDictionaryRemoveValue(map,touch);
//i already added removeFromParent above no need to add release code.
}
}
let me know if the above code work for you.

Should I need to unschedule my tick method?

I'm trying to simulate a flick in cocos2d and I need to create a ball every time the users touch is ended, but I can't get the ball to move during the tick method, and I can't destroy the ball (which is a b2body) afterwards without unscheduling the method every time.
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
touch = [touches anyObject];
location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
endPoint = location;
force = b2Vec2(endPoint.x - startPoint.x ,endPoint.y - startPoint.y);
if ((force.x != 0) || (force.y != 0)) {
if (ballCount == 0) {
ball.position = startPoint;
[self createBall]; - Here i create the ball every time
[self schedule: #selector(tick:)]; -I schedule the tick method right after the ball is created
[self scheduleOnce:#selector(kick) delay:0]; - This is the only place the ball will launch. For some reason I can't get the kick method to work any where else
}
}
- (void)kick
{
int speed = 30;
float32 setSpeed = speed/sqrt(powf(force.x,2) + powf(force.y, 2));
b2Vec2 ballSpeed = b2Vec2(force.x * setSpeed, force.y * setSpeed);
_ballBody->SetLinearVelocity(ballSpeed);
}
- (void)tick:(ccTime) dt {
_world->Step(dt, 10, 10);
ballData = (__bridge CCSprite *)_ballBody->GetUserData();
ballData.position = ccp(_ballBody->GetPosition().x * PTM_RATIO,
_ballBody->GetPosition().y * PTM_RATIO);
ballData.rotation = -1 * CC_RADIANS_TO_DEGREES(_ballBody->GetAngle());
std::set<b2Body *>toDestroy;
//takes collisions from contact listener
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
bodyA = contact.fixtureA->GetBody();
bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
spriteA = (__bridge CCSprite *) bodyA->GetUserData();
spriteB = (__bridge CCSprite *) bodyB->GetUserData();
contactPositionX = spriteA.position.x;
contactPositionY = spriteB.position.y;
if (spriteA.tag == kCurrentItem && spriteB.tag == 8)
{
NSLog(#"contact");
[self removeChild:spriteA cleanup:YES];
[self removeChild:spriteB cleanup:YES];
toDestroy.insert(bodyA);
toDestroy.insert(bodyB);
[self unschedule:#selector(tick:)]; (i unschedule the tick method every time which in turn messes up my other sprites.)
}
}
}
for(std::set<b2Body *>::iterator pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2)
{
b2Body *body = *pos2;
_world->DestroyBody(body);
}
toDestroy.clear();
}

How to detect touch outside (empty space) - cocos2d

This is my code for detect that if touch on a specific sprite
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(CCSprite *sprite in shapeArray)
{
if(CGRectContainsPoint(sprite.boundingBox, location))
{
//There is a sprite that is touched
mSpriteOnHand = sprite;
currentPoint = mSpriteOnHand.position;
break;
}
//This part didn't work
else
{
NSLog(#"Touch outside);
}
}
}
Now I want to detect if touch is outside(not on any sprite or empty space) but I don't know how to do it.
If your touches are working, than I think adding a BOOL and then an if statement outside the for loop, like this will work.
BOOL itemFound = NO;
for(CCSprite *sprite in shapeArray)
{
if(CGRectContainsPoint(sprite.boundingBox, location))
{
//There is a sprite that is touched
mSpriteOnHand = sprite;
currentPoint = mSpriteOnHand.position;
NSLog(#"item TOUCHED");
itemFound = YES;
break;
}
}
if (itemFound == NO)
{
NSLog(#"Touch outside");
}

serious multitouch problem

I am almost done with my game but I can't get my multi touch working :
I got in my appdelegate
[glView setMultipleTouchEnabled:YES];
(also tried [window setMultiTouchEnabled:YES];)
In my Bomb.h
#interface Bomb : CCLayer (I also tried CCNode with <ccTargetTouchDelegate>)
Bomb.m
-(void)onEnter
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority swallowsTouches:YES];
[super onEnter];
}
-(void)onExit
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
[super onExit];
}
(Also tried registerWithTouchDispatcher withouth onEnter and onExit and also tried with [super registerWithTouchDispatcher])
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if(isPaused || !canBeDragged || LOST)
return NO;
//take the coordinates of the touch and transform them into the OpenGL system.
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
CGRect frame = CGRectMake(self.position.x, self.position.y, self.contentSize.width, self.contentSize.height);
if(!CGRectContainsPoint(frame, location))
return NO;
location.x *= factor;
location.y *= factor;
if(BombShape)
{
offsetX = BombShape->body->p.x – location.x;
offsetY = BombShape->body->p.y – location.y;
BombShape->body->v = cpvzero;
BombShape->collision_type++; //make it ‘Dragged’. For example RedNinja++ is DraggedRedNinja
}
return YES;
}
//****************************************************************************************
- (void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if(isPaused || !canBeDragged)
return;
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
CGPoint prevLocation = [touch previousLocationInView: [touch view]];
prevLocation = [[CCDirector sharedDirector] convertToGL: prevLocation];
location.x *= factor;
location.y *= factor;
prevLocation.x *= factor;
prevLocation.y *= factor;
if(BombBody)
{
//during the dragging, the bomb must not have velocity. Otherwise, it will “run” beneath your finger.
//so we are constantly calculating the velocity and ,when you end the draging, assign that value to the velocity of the bomb.
velocity = cpv((location.x – prevLocation.x) * 30 , (location.y – prevLocation.y)*30);
CGPoint newPosition = cpv(location.x + offsetX, location.y + offsetY);
//test per X
canMoveOnX = CheckOnX(BombBody->p , newPosition,radius);
canMoveOnY = CheckOnY(BombBody->p , newPosition,radius);
if(canMoveOnX)
BombBody->p.x = newPosition.x;
if(canMoveOnY)
BombBody->p.y = newPosition.y;
}
}
//****************************************************************************************
- (void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if(!canBeDragged || isPaused)
return;
//set velocity back
BombShape->body->v = velocity;
BombShape->collision_type–;
offsetX = 0;
offsetY = 0;
}
//****************************************************************************************
-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event
{
}
Somehow I can't seem to detect my second touch :S.
I am loading my Bomb.h in a GameScene that is a CCLayer without touches.
Please help. Thanks.
I had the same problem.
If you have another view, like a view for ad, you should do the same thing to that.
ex.
[yourAnotherView setMultipleTouchEnabled:YES];
If you don't, sorry I cannot answer any more...