disable play multiple sound in the same time - ios

I have an app with 4 tabs.
In all view controllers i have costoum cells with CircularProgressView:
#implementation CircularProgressView
- (id)initWithFrame:(CGRect)frame
backColor:(UIColor *)backColor
progressColor:(UIColor *)progressColor
lineWidth:(CGFloat)lineWidth
audioURL:(NSURL *)audioURL {
self = [super initWithFrame:frame];
if (self) {
[self setUp];
_backColor = backColor;
_progressColor = progressColor;
self.lineWidth = lineWidth;
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
_audioURL = audioURL;
_player.delegate = self;
[_player prepareToPlay];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
[self setUp];
}
return self;
}
- (void)setUp{
self.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
[self addGestureRecognizer:tapGesture];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self addGestureRecognizer:panGesture];
}
- (void)setLineWidth:(CGFloat)lineWidth{
CAShapeLayer *backgroundLayer = [self createRingLayerWithCenter:CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2) radius:CGRectGetWidth(self.bounds) / 2 - lineWidth / 2 lineWidth:lineWidth color:self.backColor];
_lineWidth = lineWidth;
[self.layer addSublayer:backgroundLayer];
_progressLayer = [self createRingLayerWithCenter:CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2) radius:CGRectGetWidth(self.bounds) / 2 - lineWidth / 2 lineWidth:lineWidth color:self.progressColor];
_progressLayer.strokeEnd = 0;
[self.layer addSublayer:_progressLayer];
}
- (void)setAudioURL:(NSURL *)audioURL{
if (audioURL) {
[self.player stop];
self.progress = 0;
NSData *data = [NSData dataWithContentsOfURL:audioURL];
self.player = [[AVAudioPlayer alloc] initWithData:data error:nil];
self.duration = self.player.duration;
[self.player prepareToPlay];
}
_audioURL = audioURL;
}
- (CAShapeLayer *)createRingLayerWithCenter:(CGPoint)center radius:(CGFloat)radius lineWidth:(CGFloat)lineWidth color:(UIColor *)color {
UIBezierPath *smoothedPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:- M_PI_2 endAngle:(M_PI + M_PI_2) clockwise:YES];
CAShapeLayer *slice = [CAShapeLayer layer];
slice.contentsScale = [[UIScreen mainScreen] scale];
slice.frame = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
slice.fillColor = [UIColor clearColor].CGColor;
slice.strokeColor = color.CGColor;
slice.lineWidth = lineWidth;
slice.lineCap = kCALineJoinBevel;
slice.lineJoin = kCALineJoinBevel;
slice.path = smoothedPath.CGPath;
return slice;
}
- (void)setProgress:(float)progress{
if (progress == 0) {
self.progressLayer.hidden = YES;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.progressLayer.strokeEnd = 0;
});
}else {
self.progressLayer.hidden = NO;
self.progressLayer.strokeEnd = progress;
}
}
- (void)updateProgressCircle{
//update progress value
self.progress = (float) (self.player.currentTime / self.player.duration);
if (self.delegate && [self.delegate conformsToProtocol:#protocol(CircularProgressViewDelegate)]) {
[self.delegate updateProgressViewWithPlayer:self.player];
}
}
- (void)play{
if (!self.player.playing) {
if (!self.displayLink) {
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(updateProgressCircle)];
self.displayLink.frameInterval = 6;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
} else {
self.displayLink.paused = NO;
}
[self.player play];
}
}
- (void)pause{
if (self.player.playing) {
self.displayLink.paused = YES;
[self.player pause];
}
}
- (void)stop{
[self.player stop];
self.progress = 0;
self.player.currentTime = 0;
// [self.displayLink invalidate];
// self.displayLink = nil;
}
#pragma mark AVAudioPlayerDelegate method
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
if (flag) {
[self.displayLink invalidate];
self.displayLink = nil;
//restore progress value
self.progress = 0;
[self.delegate playerDidFinishPlaying];
}
}
//calculate angle between start to point
- (CGFloat)angleFromStartToPoint:(CGPoint)point{
CGFloat angle = [self angleBetweenLinesWithLine1Start:CGPointMake(CGRectGetWidth(self.bounds) / 2,CGRectGetHeight(self.bounds) / 2)
Line1End:CGPointMake(CGRectGetWidth(self.bounds) / 2,CGRectGetHeight(self.bounds) / 2 - 1)
Line2Start:CGPointMake(CGRectGetWidth(self.bounds) / 2,CGRectGetHeight(self.bounds) / 2)
Line2End:point];
if (CGRectContainsPoint(CGRectMake(0, 0, CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame)), point)) {
angle = 2 * M_PI - angle;
}
return angle;
}
//calculate angle between 2 lines
- (CGFloat)angleBetweenLinesWithLine1Start:(CGPoint)line1Start
Line1End:(CGPoint)line1End
Line2Start:(CGPoint)line2Start
Line2End:(CGPoint)line2End{
CGFloat a = line1End.x - line1Start.x;
CGFloat b = line1End.y - line1Start.y;
CGFloat c = line2End.x - line2Start.x;
CGFloat d = line2End.y - line2Start.y;
return acos(((a * c) + (b * d)) / ((sqrt(a * a + b * b)) * (sqrt(c * c + d * d))));
}
and this lines i add :
cell.circularProgressView.audioURL = url;
[cell.circularProgressView play];
everything work , but when i am in another view controller and i want to start a new song, the first is not stoped. Any idea what can i do to play only one song ?
I was trying to make a delegate method :
-(void)musicSearchStop{
selectedIndex = [NSIndexPath indexPathForRow:indexButtonSearch inSection:0];
musicTableViewCell* cell = [self.tableView cellForRowAtIndexPath:selectedIndex];
[cell.circularProgressView stop];
CircularProgressView *circular=[[CircularProgressView alloc]init];
[circular stop];
}
but no results.

-(void)viewWillDisappear {
[_player stop];
}
Have your tried adding the above code. Also do check if your - (void)viewWillDisappear function is getting called properly.

Related

Image moving while rotating

I just move sticker after rotate, but the direction of the moved sticker is changed as much as the rotation angle and moves
please help me, i don't know why this happen
panGesture:
UIView *gestureView = gesture.view;
CGPoint point = [gesture translationInView:gestureView];
// react native 단에서 쓰레기 위치를 바텀 기준 10%로 잡음
// height은 top 기준
double trashBottomPosition = round(self.bounds.size.height * 0.90);
double trashCenterPosition = round(self.bounds.size.width / 2);
double nextXPosition = gestureView.center.x + (_currentTextScale * point.x);
double nextYPosition = gestureView.center.y + (_currentTextScale * point.y);
bool isXTrashArea = trashCenterPosition - 40 < nextXPosition && trashCenterPosition + 40 > nextXPosition;
bool isYTrashArea = trashBottomPosition - 40 < nextYPosition && trashBottomPosition + 40 > nextYPosition;
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
break;
case UIGestureRecognizerStateChanged:
{
if (isXTrashArea && isYTrashArea) {
_openTrash = true;
if (!_isScaleDown && _isTrashMode) {
_prevScale = gestureView.transform.a;
gestureView.transform = CGAffineTransformMakeScale(0.5, 0.5);
_isScaleDown = true;
}
} else {
_openTrash = false;
if (_isScaleDown && _isTrashMode) {
gestureView.transform = CGAffineTransformMakeScale(_prevScale, _prevScale);
_isScaleDown = false;
}
}
gestureView.center = CGPointMake(nextXPosition, nextYPosition);
[gesture setTranslation:CGPointZero inView:gestureView];
break;
}
case UIGestureRecognizerStateEnded: {
if (_openTrash && _isTrashMode) {
[gestureView removeFromSuperview];
}
_openTrash = false;
break;
}
default:
break;
}
rotate:
UIView *gestureView = gesture.view;
if (_isActiveText) return;
switch (gesture.state) {
case UIGestureRecognizerStateBegan: {
gestureView.layer.anchorPoint = CGPointMake(0.5, 0.5);
break;
}
case UIGestureRecognizerStateChanged:
{
// CGPoint point = [gesture locationInView:self];
gestureView.transform = CGAffineTransformRotate(gestureView.transform, gesture.rotation);
_currentTextRotate = gesture.rotation;
gesture.rotation = 0;
break;
}
case UIGestureRecognizerStateEnded: {
break;
}
default:
break;
}
add image:
bool isNetwork = [RCTConvert BOOL:[sticker objectForKey:#"isNetwork"]];
bool isAsset = [RCTConvert BOOL:[sticker objectForKey:#"isAsset"]];
NSString *uri = [sticker objectForKey:#"uri"];
NSString *type = [sticker objectForKey:#"type"];
NSURL *url = isNetwork || isAsset
? [NSURL URLWithString:uri]
: [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
UIImageView *imgView = [[UIImageView alloc] initWithImage: img];
imgView.frame = CGRectMake(150, 150, 130, 130);
imgView.userInteractionEnabled = true;
imgView.multipleTouchEnabled = true;
// rotation
UIRotationGestureRecognizer *stickerRotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(stickerRotationGesture:)];
stickerRotationGestureRecognizer.delegate = self;
[imgView addGestureRecognizer:stickerRotationGestureRecognizer];
// pan gesture
UIPanGestureRecognizer *stickerPanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(stickerPanGesture:)];
[stickerPanGestureRecognizer setMinimumNumberOfTouches:1];
[stickerPanGestureRecognizer setMaximumNumberOfTouches:1];
stickerPanGestureRecognizer.delegate = self;
[imgView addGestureRecognizer:stickerPanGestureRecognizer];
// pinch
UIPinchGestureRecognizer *stickerPinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(stickerPinchGesture:)];
stickerPinchGestureRecognizer.delegate = self;
[imgView addGestureRecognizer:stickerPinchGestureRecognizer];
// longpress stickerLongPressGesture
UILongPressGestureRecognizer *stickerLongPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(stickerLongPressGesture:)];
stickerLongPressGestureRecognizer.delegate = self;
stickerLongPressGestureRecognizer.minimumPressDuration = 0.02;
[imgView addGestureRecognizer:stickerLongPressGestureRecognizer];
[self addSubview:imgView];

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.

IOS - Collision Detection on Sprites using Cocos2d

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

Tap gesture causes strange behavior

I’m building a reaction test that requires the user to tap on the target dot, while other non-target dots come down. It works most of the time but sometimes after tapping on a target dot it will display several other dots with weird behavior. I’ve been looking at the code for days and I can’t find the problem. Does anyone have any suggestions?
Thanks much. Here’s the code.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// single tap gesture recognizer
self.myTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(theTap:)];
self.myTap.numberOfTapsRequired = 1;
[self.firstView addGestureRecognizer:self.myTap];
self.myTap.enabled = NO;
self.colorToHit = self.colorFromPreviousController;
[self KickOff];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.holdTheReactionTimes = [[NSMutableArray alloc] initWithCapacity:50];
self.firstTime = YES;
numberOfTries = 0;
}
#pragma mark - Utility Methods
- (void)setRandomLocationForView:(UIView *)view
{
CGRect sinkBounds = CGRectInset(self.firstView.bounds, view.frame.size.width/2, view.frame.size.height/2);
CGFloat x = arc4random() % (int)sinkBounds.size.width + view.frame.size.width/2;
CGFloat y = arc4random() % (int)sinkBounds.size.height + view.frame.size.height/2;
view.center = CGPointMake(x, y);
}
- (void)addLabel
{
[self stopDraining];
static NSArray *buttons = nil;
buttons = [[NSArray alloc] initWithObjects:
#"XX.png",
#"YY.png",
#"ZZ.png",
nil];
int theIndex = arc4random()%[buttons count];
NSLog(#"the index: %d", theIndex);
NSString *theImageName = [buttons objectAtIndex:theIndex];
CGRect anotherFrame = CGRectMake(10, 10, 64, 64);
UIView *anotherView = [[UIView alloc] initWithFrame:anotherFrame]
UIImageView *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(-2, -2, 64, 64)];
imageView1.image = [UIImage imageNamed:theImageName];
[anotherView addSubview:imageView1];
[self setRandomLocationForView:anotherView];
[self.firstView addSubview:anotherView];
NSDate *date = [NSDate date];
timeOne = [date timeIntervalSince1970];
if (theIndex == self.colorToHit) {
NSLog(#"the right color");
self.isThisTheRightColor = YES;
self.myTap.enabled = YES;
numberOfTries += 1;
} else {
NSLog(#"the wrong color");
self.isThisTheRightColor = NO;
self.myTap.enabled = NO;
[self startDraining];
}
}
#pragma mark - View Animation
#define ANIMATE_DURATION 6.0
#define SLEEP_INTERVAL 0.5
- (void)theTap:(UITapGestureRecognizer *)gesture
{
NSLog(#"Tapped");
float tapInterval = 0;
CGPoint tapLocation = [gesture locationInView:self.firstView];
for (UIView *view in self.firstView.subviews) {
if (CGRectContainsPoint(view.frame, tapLocation)) {
NSLog(#"we hit one");
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); // added this 4-27
if (self.firstTime) {
NSDate *date = [NSDate date];
timeTwo = [date timeIntervalSince1970];
NSLog(#"TAP First time: %f", timeTwo);
self.firstTime = NO;
} else {
NSDate *date = [NSDate date];
timeTwo = [date timeIntervalSince1970];
NSLog(#"Second time: %f", timeTwo);
}
tapInterval = (timeTwo - timeOne);
NSLog(#"Time Interval: %f", tapInterval);
[view removeFromSuperview];
[self writeTimeStampToArray:tapInterval];
}
}
}
- (void)KickOff
{
for (UIView *view in self.firstView.subviews) {
[view removeFromSuperview];
}
if (self.firstView.window) {
[self addLabel];
}
}
- (void)writeTimeStampToArray:(float)timeStamp
{
NSNumber *timeObject = [NSNumber numberWithFloat: timeStamp];
[self.holdTheReactionTimes addObject:timeObject];
if (numberOfTries < NUMBER_OF_TRIES) {
[self addLabel];
} else {
[self nextScreen];
}
}
- (void)nextScreen
{
[self performSegueWithIdentifier: #"viewsummary" sender: self];
}
}
}
#pragma mark - Flipside View
- (void)ReactionViewControllerDidFinish:(int)trynumber
{
self.tryNumberInt = trynumber;
[self dismissViewControllerAnimated:YES completion:nil];
}
#define COUNTER 4
//////////////
// drain logic
- (void)drain:(NSTimer *)timer
{
[self drain];
}
#define DRAIN_DURATION 2.0
- (void)startDraining
{
self.drainTimer = [NSTimer scheduledTimerWithTimeInterval:DRAIN_DURATION/3
target:self
selector:#selector(drain:)
userInfo:nil
repeats:YES];
}
- (void)stopDraining
{
[self.drainTimer invalidate];
}
- (void)drain
{
for (UIView *view in self.firstView.subviews) {
CGAffineTransform transform = view.transform;
if (CGAffineTransformIsIdentity(transform)) {
UIViewAnimationOptions options = UIViewAnimationOptionCurveLinear;
[UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
view.transform = CGAffineTransformRotate(CGAffineTransformScale(transform, 0.7, 0.7), 2*M_PI/3);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
view.transform = CGAffineTransformRotate(CGAffineTransformScale(transform, 0.4, 0.4), -2*M_PI/3);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
view.transform = CGAffineTransformScale(transform, 0.1, 0.1);
} completion:^(BOOL finished) {
if (finished) [view removeFromSuperview];
}];
}
}];
}
}];
}
}
[self addLabel];
}

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);
}
}
}
}

Resources