Why is my SKAction not functioning properly? - ios

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.

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];

disable play multiple sound in the same time

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.

adding second to timer iOS game sprite kit

I am trying to add a few seconds to countdown timer each time when enemy and player node contacts.
Also when the player reach to some certain point I want player to pass to another level. I am sending part of the code . Could anybody help me to solve this problem. By the way because I am new to programming my code is a little hard to read . Sorry for that.
Thanks
-(void)update:(CFTimeInterval)currentTime{
if (startGamePlay){
startTime = currentTime;
startGamePlay = NO;
}
countDownInt = 10.0 - (int)(currentTime-startTime);
if(countDownInt > 0 ){ //if counting down to 0 show counter
countDown.text = [NSString stringWithFormat:#"%i", countDownInt];
}
else if (countDownInt == 0){
countDown.text =#"0";
Level2 *level2 = [Level2 sceneWithSize:self.frame.size];
SKTransition *transition = [SKTransition fadeWithDuration:0.5];
[self.view presentScene:level2 transition:transition];
}
}
- (void) didBeginContact:(SKPhysicsContact *)contact {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ( firstBody.categoryBitMask == CollisionCategoryBrick && secondBody.categoryBitMask == CollisionCategoryShark ) {
NSLog(#"BRICK");
[contact.bodyB.node removeFromParent];
} else if ( firstBody.categoryBitMask == CollisionCategoryWaterBall && secondBody.categoryBitMask == CollisionCategoryShark ) {
NSLog(#"BALL");
countDownInt = [countDown.text intValue];
[contact.bodyA.node removeFromParent];
[self addPoints:PointsPerHit];
if (![ self childNodeWithName:#"WATERBALLTL"]) {
[self addWaterBallTopLeft];
}
if (![ self childNodeWithName:#"WATERBALLTR"]) {
[self addWaterBallTopRight];
}
if (![ self childNodeWithName:#"WATERBALLBL"]) {
[self addWaterBallBottomLeft];
}
if (![ self childNodeWithName:#"WATERBALLBR"]) {
[self addWaterBallBottomRight];
}
}
NSLog(#"%lu", (unsigned long)[self.children count]);
}
#import "HudNode.h"
#implementation HudNode
{
SKLabelNode *countDown;
BOOL startGamePlay;
NSTimeInterval startTime;
}
+ (instancetype) hudAtPosition:(CGPoint)position inFrame:(CGRect)frame {
HudNode *hud = [self node];
hud.position = position;
hud.zPosition = 10;
hud.name = #"HUD";
SKLabelNode *scoreLabel = [SKLabelNode labelNodeWithFontNamed:#"Futura-CondensedExtraBold"];
scoreLabel.name = #"Score";
scoreLabel.text = #"0";
scoreLabel.fontSize = 24;
scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
scoreLabel.position = CGPointMake(frame.size.width-20, -10);
scoreLabel.zPosition = 12;
[hud addChild:scoreLabel];
SKLabelNode *countDown = [SKLabelNode labelNodeWithFontNamed:#"Futura-Medium"];
countDown.fontSize = 50;
countDown.position = CGPointMake(30, -10);
countDown.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter; //good for positioning with other sprites
countDown.fontColor = [SKColor whiteColor ];
countDown.name = #"countDown";
countDown.zPosition = 100;
[hud addChild:countDown];
return hud;
}
- (void) addPoints:(NSInteger)points {
self.score += points;
SKLabelNode *scoreLabel = (SKLabelNode *) [self childNodeWithName:#"Score"];
scoreLabel.text = [NSString stringWithFormat:#"Score:%li", (long)self.score];
}
Create a boolean flag that the update method checks to see if it should add seconds.
Add the following variable and set self.addSeconds = NO; initially:
#property (nonatomic) BOOL addSeconds;
Set self.addSeconds =YES; in the method where your player hits your enemy:
Add the following to the very beginning of the Update:
if(self.addSeconds == YES)
{
CountDownInt+= 5 //Change this to add as many seconds as you want
self.addSeconds=NO;
}
This should do the trick.

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

SKAction building a timer/score counter

so I am trying to make a game with a timer and a score counter in the bottom right of the screen. but it is not appearing and I am not sure as to why
in - (void)didMoveToView:(SKView *)view
I have the code
SKAction *wait = [SKAction waitForDuration:1.0f];
SKAction *sequence = [SKAction sequence:#[[SKAction performSelector:#selector(timer) onTarget:self], wait]];
SKAction *repeat = [SKAction repeatActionForever:sequence];
[self runAction:repeat];
and timer looks like
-(void)timer
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
float multi = [defaults floatForKey:#"multi"];
if(!_time)
{
_time=0;
}
else if(_time == 30)
{
multi = 1.5;
}
else if(_time == 60)
{
multi = 2;
}
else if(_time == 90)
{
multi = 2.5;
}
else if(_time == 120)
{
multi = 3.0;
}
else if(_time == 150)
{
multi = 3.5;
}
else if(_time == 180)
{
multi = 4.0;
}
else if(_time == 210)
{
multi = 4.5;
}
[defaults setFloat:multi forKey:#"multi"];
_time++;
_score = multi * (float)_time;
SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
myLabel.fontSize = 30;
myLabel.position = CGPointMake(150,850);
myLabel.text = [NSString stringWithFormat:#"Time %d Score %f",_time,_score];
}
_timer and _score are properties I have created for this scene
any help would be awesome thank you
You forgot to add the label to the node graph. For example:
[self addChild:myLabel];

Resources