IOS - Collision Detection on Sprites using Cocos2d - ios

In this game I have asteroids flying down from to top of screen, and a ship you can move freely, but I have added some collision detection and it does not seem to work in the update method when I call [self scheduleupdate];
// Import the interfaces
#import "HelloWorldLayer.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
// HelloWorldLayer implementation
#implementation HelloWorldLayer
// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer 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
{
if( (self=[super init]) ) {
self.isTouchEnabled = YES;
moveLeft = NO;
moveRight = NO;
speed = 3;
fireSpeed = 8;
fireArray = [[NSMutableArray alloc] init];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *bg = [[CCSprite alloc] initWithFile:#"space_bg.jpg"];
[bg setPosition:ccp(160, 240)];
CGSize imageSize = bg.contentSize;
bg.scaleX = winSize.width / imageSize.width;
bg.scaleY = winSize.height / imageSize.height;
bg.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:bg];
ship = [[CCSprite alloc] initWithFile:#"ship.png"];
[ship setPosition:ccp(100, 100)];
[self addChild:ship];
[self schedule:#selector(fireLoop:)];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(fireCreate)
userInfo:nil
repeats:YES];
asteroidArray = [[NSMutableArray alloc] init];
for(int i = 0; i < 100; ++i) {
CCSprite *asteroid = [[CCSprite alloc] initWithFile:#"asteroid1.png"];
[asteroidArray addObject:asteroid];
}
[self asteroidCreate];
[self scheduleUpdate];
}
return self;
}
CCSpriteBatchNode *spriteSheet;
NSMutableArray *asteroidAnimFrames;
- (float)randomValueBetween:(float)low andValue:(float)high {
return (((float) arc4random() / 0xFFFFFFFFu) * (high - low)) + low;
}
-(void)updtate:(ccTime)dt{
CGPoint shipPosition = [ship position];
for(int i = 0; i < asteroidArray.count; i++){
CCSprite *asteroid = [asteroidArray objectAtIndex:i];
if (CGRectIntersectsRect(ship.boundingBox, asteroid.boundingBox)) {
NSLog(#"hit");
}
}
}
- (void)countDownToCreateNextAsteroid {
int minTime = 1;
int maxTime = 10;
int randomTime = (arc4random() % (3));
id countdownDelay = [CCDelayTime actionWithDuration:randomTime];
id creationMethod = [CCCallFunc actionWithTarget:self selector:#selector(asteroidCreate)];
id countdownToCreateSeq = [CCSequence actions:countdownDelay, creationMethod, nil];
[self stopAllActions];
[self runAction:countdownToCreateSeq];
}
-(void)asteroidCreate {
CGSize winSize = [[CCDirector sharedDirector] winSize];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"asteroids.plist"];
spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"asteroids.png"];
asteroidAnimFrames = [NSMutableArray array];
for(int i=1; i <= 8; i++) {
[asteroidAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"asteroid%d.png", i]]];
}
CCAnimation *moveAsteroidAnim = [CCAnimation animationWithFrames:asteroidAnimFrames delay:0.1f];
CCSprite *asteroid = [CCSprite spriteWithSpriteFrameName:#"asteroid1.png"];
int x = arc4random() % 320;
int y = arc4random() % 480;
asteroid.position = ccp(x, 480);
CCAction *asteroidAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:moveAsteroidAnim restoreOriginalFrame:NO]];
[asteroidArray addObject:asteroid];
int q = arc4random() % 320;
int r = arc4random() % 10;
CCAction *moveAction = [CCMoveTo actionWithDuration:r position:ccp(q, -50)];
id asteroidRemove = [CCCallBlock actionWithBlock:^
{
[asteroid removeFromParentAndCleanup:YES];
[asteroidArray removeObject:asteroid];
}];
id asteroidSeq = [CCSequence actions:moveAction, asteroidRemove, nil];
[asteroid runAction:asteroidSeq];
[asteroid runAction:asteroidAction];
[spriteSheet addChild:asteroid];
[self addChild:spriteSheet];
[self countDownToCreateNextAsteroid];
}
-(void)fireLoop:(ccTime)fl {
if(fireArray.count > 0){
for(int i = 0; i < fireArray.count; i++){
CCSprite *tmpFire = [fireArray objectAtIndex:i];
if(tmpFire.position.y < 500){
[tmpFire setPosition:ccp([tmpFire position].x, [tmpFire position].y + fireSpeed)];
}else{
[fireArray removeObjectAtIndex:i];
}
}
} else {
}
}
-(void)fireCreate{
int shootPositionX = [ship position].x;
int shootPositionY = ([ship position].y) + 35;
CCSprite *fire;
fire = [[CCSprite alloc] initWithFile:#"fire.png"];
[fire setPosition:ccp(shootPositionX, shootPositionY)];
[fireArray addObject:fire];
[self addChild:fire];
[fire release];
}
-(void)gameLoop:(ccTime)dt {
int shipPositionX = 41/2;
if([ship position].x > shipPositionX){
[ship setPosition:ccp([ship position].x - speed, [ship position].y)];
}
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
//if(point.x <= 160){
// moveRight = NO;
// moveLeft = YES;
//}else{
// moveRight =YES;
// moveLeft = NO;
//}
if(allowedToMove)
[ship setPosition:ccp(point.x, point.y + 76)];
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
int shipX = [ship position].x;
int shipY = [ship position].y;
if (CGRectContainsPoint(CGRectMake (shipX - 20.5, shipY - 96, 50, 50), point))
{
allowedToMove = true;
}
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *t in touches){
CGPoint point = [self convertTouchToNodeSpace:t];
allowedToMove = false;
}
}
// 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];
}
#pragma mark GameKit delegate
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
#end

Related

Why is my SKAction not functioning properly?

Okay, so in my SpriteKit game, I have an SKAction that waits and then calls a method. I have this action repeating forever. The methods spawns sprites. When I press a button (another sprite) the game pauses, and stops the action by removing it. When either resume or restart (also sprites) is pressed the action starts again and the sprites spawn.
However, when returning from the background (after the app is left) and the pause menu method automatically gets called, when I press the resume or restart button, the action does not run for some reason. Here's my code:
In GameScene.m:
-(void)createSceneContents {
self.isPaused = NO;
self.world = [SKNode node];
[self createUI];
[self createPauseMenu];
self.spawningSpeed = 1.5;
self.enemyData = [[Enemy alloc]init];
SKAction *wait = [SKAction waitForDuration:self.spawningSpeed];
SKAction *run = [SKAction performSelector:#selector(spawningEnemy) onTarget:self];
self.spawnAction = [SKAction repeatActionForever:[SKAction sequence:#[wait,run]]];
[self.world runAction:self.spawnAction withKey:#"spawn"];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(wentToForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
[self addChild:self.world];
[self.world addChild:bottom];
[self.world addChild:self.player];
[self addChild:left];
[self addChild:right];
[self addChild:self.pause];
[self addChild:self.scoreLabelInGame];
[self addChild:self.actualScore];
}
-(void)createUI {
self.pause = [SKSpriteNode spriteNodeWithImageNamed:#"pausebutton.png"];
self.pause.size = CGSizeMake(self.customUnit,self.customUnit);
self.pause.name = #"pauseButton";
self.pause.position = CGPointMake(30, self.frame.size.height - 30);
self.scoreLabelInGame = [SKLabelNode labelNodeWithFontNamed:#"Futura"];
self.scoreLabelInGame.text = #"";
self.scoreLabelInGame.fontSize = 25;
self.scoreLabelInGame.position = CGPointMake(self.frame.size.width - 100, self.frame.size.height - 40);
self.actualScore = [SKLabelNode labelNodeWithFontNamed:#"Futura"];
self.actualScore.text = #"SCORE: 0";
self.actualScore.fontSize = 25;
self.actualScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
self.actualScore.position = CGPointMake(self.frame.size.width - 20, self.frame.size.height - 40);
self.deathImage = [SKSpriteNode spriteNodeWithImageNamed:#"youdied.png"];
self.deathImage.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)*1.5);
}
-(void)createPauseMenu {
self.pausedImage = [SKSpriteNode spriteNodeWithImageNamed:#"paused.png"];
self.pausedImage.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)*1.5);
self.restart = [SKLabelNode labelNodeWithFontNamed:#"Futura"];
self.restart.text = #"RESTART";
self.restart.fontSize = 25;
self.restart.position = CGPointMake(CGRectGetMidX(self.frame), self.pausedImage.position.y - self.pausedImage.position.y/5);
self.resume = [SKLabelNode labelNodeWithFontNamed:#"Futura"];
self.resume.text = #"RESUME";
self.resume.fontSize = 25;
self.resume.position = CGPointMake(self.restart.position.x, self.restart.position.y - self.customUnit);
}
-(void)spawningEnemy {
NSLog(#"spawned");
SKSpriteNode *aNewEnemy = [self.enemyData createEnemyWithSize:self.customUnit andWidth:self.frame.size.width andHeight:self.frame.size.height + self.player.position.y];
aNewEnemy.physicsBody.allowsRotation = NO;
aNewEnemy.physicsBody.categoryBitMask = self.enemyCategory;
aNewEnemy.physicsBody.collisionBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
aNewEnemy.physicsBody.contactTestBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
[self.world addChild:aNewEnemy];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if([self.pause containsPoint:location] && self.isPaused == NO){
[self pauseGame];
}else if([self.resume containsPoint:location] && self.isPaused == YES) {
[self resumeGame];
}else if ([self.restart containsPoint:location] && self.isPaused == YES){
[self restartGame];
}else if (self.isTouchingGround == YES && self.isPaused == NO) {
[self.playerData jump:self.player];
NSLog(#"GOD YES");
self.isTouchingGround = NO;
}
}
-(void)pauseGame {
[self createPauseMenu];
NSLog(#"Pausing...");
[self removeActionForKey:#"spawn"];
self.world.paused = YES;
[self addChild:self.pausedImage];
[self addChild:self.restart];
[self addChild:self.resume];
NSString *path = [NSString stringWithFormat:#"%#/menu_music.mp3", [[NSBundle mainBundle]resourcePath]];
NSURL *pauseMusicURL = [NSURL fileURLWithPath:path];
self.pauseMusicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pauseMusicURL error:nil];
self.pauseMusicPlayer.numberOfLoops = -1;
[self.pauseMusicPlayer play];
[self.pause removeFromParent];
self.scoreLabelInGame.position = CGPointMake(self.restart.position.x, self.resume.position.y - self.customUnit);
self.actualScore.position = CGPointMake(self.restart.position.x, self.scoreLabelInGame.position.y - self.customUnit);
self.isPaused = YES;
[self.mainMusicPlayer pause];
}
-(void)restartGame {
[self removeAllChildren];
[self removeAllActions];
self.enemyData = nil;
self.isPaused = NO;
[self.pauseMusicPlayer stop];
[self createSceneContents];
[self runAction:self.spawnAction withKey:#"spawn"];
}
-(void)resumeGame {
self.isPaused = NO;
[self.pauseMusicPlayer stop];
[self runAction:self.spawnAction withKey:#"spawn"];
self.scoreLabelInGame.position = CGPointMake(self.frame.size.width - 100, self.frame.size.height - 40);
self.actualScore.position = CGPointMake(self.frame.size.width - 20, self.frame.size.height - 40);
[self.mainMusicPlayer play];
[self.restart removeFromParent];
[self.resume removeFromParent];
[self.pausedImage removeFromParent];
[self addChild:self.pause];
}
-(void)gameOver {
NSLog(#"Game Over");
GameDataHelper *gameData = [[GameDataHelper alloc]init];
[self removeActionForKey:#"spawn"];
[self addChild:self.restart];
[self addChild:self.deathImage];
SKAction *gameOverSound = [SKAction playSoundFileNamed:#"gameover_tune.mp3" waitForCompletion:NO];
[self runAction:gameOverSound];
NSString *path = [NSString stringWithFormat:#"%#/menu_music.mp3", [[NSBundle mainBundle]resourcePath]];
NSURL *pauseMusicURL = [NSURL fileURLWithPath:path];
self.pauseMusicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pauseMusicURL error:nil];
self.pauseMusicPlayer.numberOfLoops = -1;
[self.pauseMusicPlayer play];
[self.pause removeFromParent];
SKLabelNode *highScore = [SKLabelNode labelNodeWithFontNamed:#"Futura"];
NSString *highScoreText = [NSString stringWithFormat:#"HIGHSCORE: %ld",[GameDataHelper sharedGameData].highScore];
highScore.text = highScoreText;
highScore.fontSize = 25;
highScore.position = CGPointMake(self.frame.size.width/2, self.restart.position.y - (2*self.customUnit));
[self addChild:highScore];
self.scoreLabelInGame.position = CGPointMake(self.restart.position.x, self.resume.position.y - self.customUnit);
self.actualScore.position = CGPointMake(self.restart.position.x, self.scoreLabelInGame.position.y - self.customUnit);
self.isPaused = YES;
[self.mainMusicPlayer pause];
[gameData save];
}
-(void)wentToForeground {
[self pauseGame];
}
In Enemy.m:
-(SKSpriteNode *)createEnemyWithSize:(float)size andWidth:(float)width andHeight:(float)height {
self.enemy = [SKSpriteNode spriteNodeWithImageNamed:#"block.png"];
self.enemy.size = CGSizeMake(size - 5, size - 5);
self.enemy.name = #"fallingEnemy";
self.enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(size - 3, size - 3)];
self.enemy.physicsBody.restitution = 0;
self.enemy.physicsBody.allowsRotation = NO;
int randomSection = arc4random_uniform(7);
switch (randomSection) {
case 0:
self.enemy.position = CGPointMake(2.5 + self.enemy.size.width/2, height-5);
break;
case 1:
self.enemy.position = CGPointMake(width/7 + self.enemy.size.width/2, height-5);
break;
case 2:
self.enemy.position = CGPointMake((width/7*2) + self.enemy.size.width/2, height-5);
break;
case 3:
self.enemy.position = CGPointMake((width/7*3) + self.enemy.size.width/2, height-5);
break;
case 4:
self.enemy.position = CGPointMake((width/7*4) + self.enemy.size.width/2, height-5);
break;
case 5:
self.enemy.position = CGPointMake((width/7*5) + self.enemy.size.width/2, height-5);
break;
case 6:
self.enemy.position = CGPointMake((width/7*6) + self.enemy.size.width/2, height-5);
break;
default:
break;
}
return self.enemy;
}
Even though you might have found the answer already i see some problems with your code:
Note: self.spawnAction needs to be a Strong property so maintain the reference when it's removed.
You are running the action on self.world, but removing it on self.
[self.world runAction:self.spawnAction withKey:#"spawn"];
[self removeActionForKey:#"spawn"];
self.world.paused = YES;
If you set the paused property of self.world to YES you do not need to remove the action as pause will immediately pause all actions.
You do not set the paused property to NO again on -(void)resumeGame
And you run it on self instead of self.world on resume.
Overall I would try to avoid using paused properties which might behave different and not give the results you want.
Also, keep in mind that removing nodes and actions don't happen instantly so if you pause nodes afterwards you might not get expected results.
Also, there is a limited amount of time you have on didEnterBackground to do your stuff before the it actually goes to background.
Hope it helps.

multiple Animation Cocos2d 3.0

I have tried to run multiple animation 1.Player will stand on screen loading 2.Then he starts running when his frames finish 3.Player will stop and Go action performed
problem is go action is executed before run action finishes
can any one help me to perform this task like player run 0.6 secs then he stops running action and Go action execute and after 4 sec it stops
- (void)didLoadFromCCB
{
CGSize winSize = [[CCDirector sharedDirector] viewSize];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"cc_player.plist"];
NSMutableArray *runAnimFrames = [NSMutableArray array];
for(int i = 0; i <= 12; i++)
{
[runAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"cc_player/cc_player_run_pistol_%d.png", i]]];
}
NSMutableArray *goAnimFrames = [NSMutableArray array];
for(int i = 0; i <= 11; i++)
{
[goAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"cc_player/cc_player_go_%d.png", i]]];
}
CCSprite *playerSprite = [CCSprite spriteWithImageNamed:#"cc_player/cc_player_idle_0.png"];
playerSprite.scale = 1.3;
playerSprite.position = CGPointMake(100, ( winSize.height / 2) - 60);
[self addChild:playerSprite z:3];
CCActionMoveTo *moveTo = [CCActionMoveTo actionWithDuration:8 position:CGPointMake(winSize.width+100 / 2, playerSprite.position.y)];
CCAnimation *runAnim = [CCAnimation animationWithSpriteFrames:runAnimFrames delay:0.06];
CCAnimation *goAnim = [CCAnimation animationWithSpriteFrames:goAnimFrames delay:0.06];
CCActionAnimate *runAnimationAction = [CCActionAnimate actionWithAnimation:runAnim];
CCActionAnimate *goAnimationAction = [CCActionAnimate actionWithAnimation:goAnim];
CCActionCallBlock *next=[CCActionCallBlock actionWithBlock:^
{
playerSprite.position = CGPointMake(playerSprite.position.x - 8, playerSprite.position.y + 6);
id goAction = [CCActionRepeat actionWithAction:goAnimationAction times:1];
CCActionCallBlock *nextStep=[CCActionCallBlock actionWithBlock:^
{
NSLog(#"***********not done");
// [playerSprite stopAllActions];
}];
CCActionSpawn *groupAction1 = [CCActionSpawn actionWithArray:#[goAction,nextStep]];
CCActionSequence *sequence2 = [CCActionSequence actionWithArray:#[groupAction1]];
// [playerSprite stopAllActions];
//CCActionSequence *goSequence = [CCActionSequence actions:moveTo,repeatingAnimation, nil];
[playerSprite runAction:sequence2];
}];
CCActionSpawn *groupAction = [CCActionSpawn actionWithArray:#[moveTo, next]];
CCActionSequence *sequence = [CCActionSequence actionWithArray:#[groupAction]];
[playerSprite runAction:sequence];
[playerSprite runAction:[CCActionRepeatForever actionWithAction:runAnimationAction]];
}
i have removed opticity line from code animation started showing now i have change sequance of my animation and its now working nice
(void)didLoadFromCCB
{
CGSize winSize = [[CCDirector sharedDirector] viewSize];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"cc_player.plist"];
NSMutableArray *runAnimFrames = [NSMutableArray array];
for(int i = 0; i <= 12; i++)
{
[runAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"cc_player/cc_player_run_pistol_%d.png", i]]];
}
NSMutableArray *goAnimFrames = [NSMutableArray array];
for(int i = 0; i <= 11; i++)
{
[goAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"cc_player/cc_player_go_%d.png", i]]];
}
CCSprite *playerSprite = [CCSprite spriteWithImageNamed:#"cc_player/cc_player_idle_0.png"];
playerSprite.scale = 1.3;
playerSprite.position = CGPointMake(100, ( winSize.height / 2) - 60);
[self addChild:playerSprite z:3];
CCActionMoveTo *moveTo = [CCActionMoveTo actionWithDuration:3 position:CGPointMake(300, playerSprite.position.y)];
CCAnimation *runAnim = [CCAnimation animationWithSpriteFrames:runAnimFrames delay:0.06];
CCAnimation *goAnim = [CCAnimation animationWithSpriteFrames:goAnimFrames delay:0.06];
CCActionAnimate *runAnimationAction = [CCActionAnimate actionWithAnimation:runAnim];
CCActionAnimate *goAnimationAction = [CCActionAnimate actionWithAnimation:goAnim];
CCActionCallBlock *next=[CCActionCallBlock actionWithBlock:^
{
playerSprite.position = CGPointMake(playerSprite.position.x - 8, playerSprite.position.y + 6);
id goAction = [CCActionRepeat actionWithAction:goAnimationAction times:1];
CCActionCallBlock *nextStep=[CCActionCallBlock actionWithBlock:^
{
// [playerSprite stopAllActions];
}];
CCActionSpawn *groupAction1 = [CCActionSpawn actionWithArray:#[goAction,nextStep]];
CCActionSequence *sequence2 = [CCActionSequence actionWithArray:#[groupAction1]];
// [playerSprite stopAllActions];
//CCActionSequence *goSequence = [CCActionSequence actions:moveTo,repeatingAnimation, nil];
[playerSprite runAction:sequence2];
}];
[playerSprite runAction:[CCActionRepeatForever actionWithAction:runAnimationAction]];
CCActionSpawn *groupAction = [CCActionSpawn actionWithArray:#[moveTo,runAnimationAction]];
CCActionSequence *sequence = [CCActionSequence actionWithArray:#[groupAction,next]];
[playerSprite runAction:sequence];
}

How to make a sprite jump inside update loop in Cocos2D

I have a ball sprite that falls from the top and a boy underneath it. When the ball hits the boy's head I want it to follow a parabolic path. I tried using CCJumpTo as follows but I cannot get it to work. I'm calling the action inside the update loop. Am I not allowed to do that? Cant I call CCJumpTo inside the update loop?
- (void) jump
{
if(!method_called)
{
method_called=TRUE;
CCActionInterval *jump1 = [CCJumpTo actionWithDuration:3 position:CGPointMake(400, 400) height:150 jumps:1];
[_ball runAction:jump1];
NSLog(#"something");
}
else
{
NSLog(#"do nothing");
}
}
- (void)update:(ccTime)dt
{
time ++;
if ( dpad.leftJoystick.velocity.x > 0 && x < 2000 ) {
x = x + 10;
} else if ( dpad.leftJoystick.velocity.x < 0 && x > 0 ) {
x = x - 10;
}
if (x > 10 && x < 2000)
_boy.position = ccp(x, 100);
_ball.position = ccp(ball_x, ball_y);
ball_y = _ball.position.y - (speed * rebound);
_boy.anchorPoint = ccp(0, 0);
CGRect boyBox = CGRectMake(_boy.position.x, _boy.position.y, [_boy boundingBox].size.width, [_boy boundingBox].size.height);
_ball.anchorPoint = ccp(0, 0);
CGRect ballBox = CGRectMake(_ball.position.x, _ball.position.y, [_ball boundingBox].size.width, [_ball boundingBox].size.height);
if (CGRectIntersectsRect(boyBox, ballBox) && flag == 0)
{
rebound = -rebound;
flag = 1;
topFlag = 0;
[_ball stopAllActions];
[self jump];
}
if (_ball.position.y > 700 && topFlag == 0)
{
rebound = -rebound;
flag = 0;
topFlag = 1;
}
}
Thanks in advance.
EDIT:
Here's my init method
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
self.ball = [CCSprite spriteWithFile:#"ball.png"
rect:CGRectMake(0, 0, 50, 50)];
self.ball.position = ccp(275, 999);
[self addChild:self.ball];
x = 0;
ball_y = 650;
ball_x = 300;
rebound = 1;
flag = 0;
topFlag = 0;
speed = 5;
time = 0;
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"boy.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"boy.png"];
//spriteSheet.scaleX = 0.5;
//spriteSheet.scaleY = 0.5;
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i) {
[walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"boy%d.png", i]]];
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:.1f];
self.boy = [CCSprite spriteWithSpriteFrameName:#"boy1.png"];
_boy.position = ccp(100000, 100000);
self.walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
[_boy runAction:_walkAction];
_boy.flipX = YES;
[spriteSheet addChild:_boy];
dpad = [[MyJoystick alloc] init];
[self addChild:dpad z:10];
[self schedule:#selector(update:)];
}
[self addChild:spriteSheet];
}
return self;
}
Keep your action code inside a method and call it from update method using a boolean variable so that it would be called once only. Something like this:
take a boolean variable method_called in .h file:
-(void)update:(ccTime)dt
{
_boy.anchorPoint = ccp(0, 0);
CGRect boyBox = CGRectMake(_boy.position.x, _boy.position.y, [_boy boundingBox].size.width, [_boy boundingBox].size.height);
_ball.anchorPoint = ccp(0, 0);
CGRect ballBox = CGRectMake(_ball.position.x, _ball.position.y, [_ball boundingBox].size.width, [_ball boundingBox].size.height);
if (CGRectIntersectsRect(boyBox, ballBox) && flag == 0)
{
flag = 1; topFlag = 0;
[self callJumpAction];
}
}
-(void)callJumpAction
{
if(!method_called)
{
method_called=true;
CCActionInterval *jump1 = [CCJumpTo actionWithDuration:3 position:CGPointMake(400, 400) height:150 jumps:1];
[_ball runAction:jump1];
}
else
{
NSLog(#"do nothing");
}
}
Hope this will help.

Issue with Drawing on UIImage

I am using the following code to Draw over an image. All the touch delegates are working, but the drawing is not rendered over the UIImage. Here is the code. I am not able to identify the issue. Thanks in advance.
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self setupVariables];
}
return self;
}
- (void)drawPic:(UIImage *)thisPic {
myPic = thisPic;
[myPic retain];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
float newHeight;
float newWidth;
float xPos;
float yPos;
float ratio;
if (myPic != NULL) {
ratio = myPic.size.height/460;
if (myPic.size.width/320 > ratio) {
ratio = myPic.size.width/320;
}
newHeight = myPic.size.height/ratio;
newWidth = myPic.size.width/ratio;
xPos = (320 - newWidth) / 2;
yPos = (460 - newHeight) / 2;
[myPic drawInRect:CGRectMake(xPos, yPos, newWidth, newHeight)];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *allTouches = [[event allTouches] allObjects];
if ([allTouches count] > 1) {
return;
}
else {
[self drawPoint:[allTouches objectAtIndex:0]];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *allTouches = [[event allTouches] allObjects];
if ([allTouches count] > 1) {
return;
}
else {
[self drawPoint:[allTouches objectAtIndex:0]];
self.previousPoint = nil;
self.point = nil;
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *allTouches = [[event allTouches] allObjects];
if ([allTouches count] > 1) {
return;
}
else {
[self drawPoint:[allTouches objectAtIndex:0]];
self.previousPoint = nil;
self.point = nil;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *allTouches = [[event allTouches] allObjects];
if ([allTouches count] > 1) {
return;
}
else {
[self drawPoint:[allTouches objectAtIndex:0]];
}
}
- (void)dealloc {
CGContextRelease(offScreenBuffer);
[point release];
[previousPoint release];
[super dealloc];
}
- (void)setupVariables {
self.point = nil;
self.previousPoint = nil;
offScreenBuffer = [self setupBuffer];
}
- (CGContextRef)setupBuffer {
CGSize size = self.bounds.size;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,size.width,size.height,8,size.width*4, colorSpace,kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
return context;
}
- (void)drawToBuffer {
// Red Gr Blu Alpha
CGFloat color[4] = {0.0, 1.0, 0.0, 1.0};
if (self.previousPoint != nil) {
CGContextSetRGBStrokeColor(offScreenBuffer, color[0], color[1], color[2], color[3]);
CGContextBeginPath(offScreenBuffer);
CGContextSetLineWidth(offScreenBuffer, 10.0);
CGContextSetLineCap(offScreenBuffer, kCGLineCapRound);
CGContextMoveToPoint(offScreenBuffer, previousPoint.location.x, previousPoint.location.y);
CGContextAddLineToPoint(offScreenBuffer, point.location.x, point.location.y);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeColor);
CGContextDrawPath(offScreenBuffer, kCGPathStroke);
}
}
- (void)drawPoint:(UITouch *)touch {
PointLocation *currentLoc = [[PointLocation alloc] init];
currentLoc.location = [touch locationInView:self];
self.previousPoint = self.point;
self.point = currentLoc;
[self drawToBuffer];
[self setNeedsDisplay];
[currentLoc release];
}
It's very simple. You need to do all your drawing in drawRect: and you're only drawing the image in drawRect:, so that's why you only see the image.
-(void)drawPic:(UIImage *)thisPic {
//code for UIViewContentModeScaleAspectFit if needed
self.backgroundColor = [UIColor colorWithPatternImage:thisPic];
[self setNeedsDisplay];
}
Do Not use this in drawRect Method:
[myPic drawInRect:CGRectMake(xPos, yPos, newWidth, newHeight)];
Edit
- (void)drawRect:(CGRect)rect {
if (!myDrawing) {
// CGFloat scale = 0.5;
// CATransform3D transform = CATransform3DMakeScale(scale, scale, scale);
// [self layer].transform = transform;
myDrawing = [[NSMutableArray alloc] initWithCapacity:0];
self.lineOnOffArray = [[NSMutableArray alloc] initWithCapacity:0];
//arrPenThickness = [[NSMutableArray alloc] initWithCapacity:0];
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
if ([myDrawing count] > 0) {
for (int i = 0 ; i < [myDrawing count] ; i++) {
NSArray *thisArray = [myDrawing objectAtIndex:i];
NSString *onOffFlag = [self.lineOnOffArray objectAtIndex:i];
if (([thisArray count] > 2) && (onOffFlag == #"1")){
float penT = [[arrPenThickness objectAtIndex:i] floatValue];
NSString* penC = [arrPenColors objectAtIndex:i];
NSArray *arr = [penC componentsSeparatedByString:#","];
float r = [[arr objectAtIndex:0]floatValue];
float g = [[arr objectAtIndex:1]floatValue];
float b = [[arr objectAtIndex:2]floatValue];
float a = [[arr objectAtIndex:3]floatValue];
CGContextSetRGBStrokeColor(ctx,
r/255.0,
g/255.0,
b/255.0,
a);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, penT);
float thisX = [[thisArray objectAtIndex:0] floatValue];
float thisY = [[thisArray objectAtIndex:1] floatValue];
CGContextBeginPath(ctx);
for (int j = 2; j < [thisArray count] ; j+=2) {
CGContextMoveToPoint(ctx, thisX, thisY);
thisX = [[thisArray objectAtIndex:j] floatValue];
thisY = [[thisArray objectAtIndex:j+1] floatValue];
CGContextAddLineToPoint(ctx, thisX,thisY);
}
CGContextStrokePath(ctx);
}
}
}
}

Detect Touch on CCSprite

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

Resources