How can I stop SKAction - sprite-kit

_pipeTexture1 = [SKTexture textureWithImageNamed:#"p2"];
_pipeTexture1.filteringMode = SKTextureFilteringNearest;
_pipeTexture2 = [SKTexture textureWithImageNamed:#"p1"];
_pipeTexture2.filteringMode = SKTextureFilteringNearest;
CGFloat distanceToMove = self.frame.size.width + 2 * _pipeTexture1.size.width;
SKAction* movePipes = [SKAction moveByX:-distanceToMove y:0 duration:0.01 * distanceToMove];
SKAction* removePipes = [SKAction removeFromParent];
_movePipesAndRemove = [SKAction sequence:#[movePipes, removePipes]];
SKAction* spawn = [SKAction performSelector:#selector(spawnPipes) onTarget:self];
SKAction* delay = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelay = [SKAction sequence:#[spawn, delay]];
SKAction* spawnThenDelayForever = [SKAction repeatActionForever:spawnThenDelay];
[self runAction:spawnThenDelayForever];
How can i stop the animation action For some certain scenes?

Per the SKNode documentation you can use -(void)runAction:(SKAction *)action withKey:(NSString *)key to assign a name to the action when you first run it. Then you can later remove it with - (void)removeActionForKey:(NSString *)key.

Related

Rotate sprite with path

Hi i have a sprite following a path that is a bezier curve and id like the sprite to rotate to the direction it is currently moving, i can tell it to follow the path by setting orientToPath to YES in
SKaction *enemyCurve = [SKAction followpath:cgpath asOffset:NO orientToPath:YES duration:5];
but this just results in the sprite facing the final point of movement. Any suggestions on how i can make it rotate to the current direction its traveling in?
I have included the code i use for the path below. Thank you for any help and suggestions.
-(void)AddEnemy:(MotionType *)motion :(CGPoint*)Start :(CGPoint*)Finish :(EnemyType)enemyType{
double curTime = CACurrentMediaTime();
if (enemyType == One) {
if(curTime > _nextAsteroidspawn)
{
float randSecs = [self randomValueBetween:0.20 andValue:1.0];
_nextAsteroidspawn = randSecs + curTime;
float randY = [self randomValueBetween:0.0 andValue:self.frame.size.height];
float randDuration = [self randomValueBetween:2.0 andValue:10.0];
SKSpriteNode *asteroid = [_Asteroids objectAtIndex:_nextAsteroid];
_nextAsteroid++;
if(_nextAsteroid >= _Asteroids.count){
_nextAsteroid = 0;
}
[asteroid removeAllActions];
asteroid.position = CGPointMake(self.frame.size.width+asteroid.size.width/2, 50);
asteroid.hidden = NO;
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPoint startingPoint = CGPointMake(self.frame.size.width+asteroid.size.width/2 , 50);
CGPoint controlPoint1 = CGPointMake(160, 300);
CGPoint controlPoint2 = CGPointMake(200, 600);
CGPoint endingPoint = CGPointMake(0, self.frame.size.width - self.frame.size.width - asteroid.size.width / 2);
CGPathMoveToPoint(cgpath, NULL, startingPoint.x, startingPoint.y);
CGPathAddCurveToPoint(cgpath, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x
, controlPoint2.y, endingPoint.x
, endingPoint.y);
SKAction *enemyCurve = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5];
CGPoint location = CGPointMake(-self.frame.size.width-asteroid.size.width, randY);
SKAction *moveAction = [SKAction moveTo:location duration:randDuration];
SKAction *doneAction = [SKAction runBlock:(dispatch_block_t)^(){
asteroid.hidden = YES;
}];
SKAction *moveAsteroidActionWithDone = [SKAction sequence:#[enemyCurve,moveAction, doneAction]];
[asteroid runAction:moveAsteroidActionWithDone withKey:#"asteroidMoving"];
CGPathRelease(cgpath);
//[asteroid runAction: [SKAction repeatActionForever:[SKAction animateWithTextures:_Asteroids timePerFrame:0.1f]]];
}
The code that creates the enemy node can be seen bellow, i do not apply any rotations to the node.
In initWithSize:
_Asteroids = [[NSMutableArray alloc] initWithCapacity:knumAsteroids];
for(int i = 0; i < knumAsteroids; i++)
{
SKSpriteNode *asteroid = [SKSpriteNode spriteNodeWithImageNamed:#"enemyBasic1"];
asteroid.hidden = YES;
[_Asteroids addObject:asteroid];
[self addChild:asteroid];
}
In Update:
[self AddEnemy:BezierCurve :NULL :NULL:One];
The method in update just links to the code posted at the top which determines the path the enemy will take i have also updated it to include the entire method.

Background of 4 images added for each other

Please help.
I have 4 pictures.
I wanna show background with animation.
Each picture should fall over the previous animation alpha. As a result, I got a background of 4 images added for each other.
first show 1.png fade alpha to 1.
until one has not appeared until the end, starts the second image, etc.
var waitTime:NSTimeInterval = 0
var durTime:NSTimeInterval = 4.4
for var i = 0; i < 4; i++ {
let frostImage = SKSpriteNode(imageNamed: "a\(i)")
frostImage.position = CGPointMake(0, 0)
frostImage.zPosition = -1
frostImage.alpha = 0
frostImage.anchorPoint = CGPointZero
frostImage.size = CGSizeMake(256, 384)
self.addChild(frostImage)
self.array.addObject(frostImage)
let w = SKAction.waitForDuration(waitTime)
let s = SKAction.fadeAlphaTo(0.6, duration: durTime)
let a = SKAction.repeatAction(SKAction.sequence([w, s]), count: 1)
durTime -= 0.4
waitTime += 0.2
self.arrayAnim.addObject(a)
}
then
for node in self.array {
node.runAction(self.arrayAnim[ind1] as SKAction, completion: nil)
ind1++
}
I wrote for you but in objective-c, I think you can convert it to swift.
SKSpriteNode *bg1 = [SKSpriteNode spriteNodeWithImageNamed:#"bg1"];
bg1.zPosition = 1;
SKSpriteNode *bg2 = [SKSpriteNode spriteNodeWithImageNamed:#"bg2"];
bg2.zPosition = 2;
SKSpriteNode *bg3 = [SKSpriteNode spriteNodeWithImageNamed:#"bg3"];
bg3.zPosition = 3;
SKSpriteNode *bg4 = [SKSpriteNode spriteNodeWithImageNamed:#"bg4"];
bg4.zPosition = 4;
SKAction *action = [SKAction fadeAlphaTo:1.0 duration:1];
SKAction *wait = [SKAction waitForDuration:1];
SKAction *resetAlpha = [SKAction fadeAlphaBy:0.0 duration:0];
[self runAction:[SKAction repeatActionForever:[SKAction sequence:#[[SKAction runBlock:^{
[bg1 runAction:resetAlpha];
[bg2 runAction:resetAlpha];
[bg3 runAction:resetAlpha];
[bg4 runAction:resetAlpha];
}], [SKAction runBlock:^{
[bg1 runAction:action];
}], wait, [SKAction runBlock:^{
[bg2 runAction:action];
}], wait, [SKAction runBlock:^{
[bg3 runAction:action];
}], wait, [SKAction runBlock:^{
[bg4 runAction:action];
}], wait]]]];

Spritekit - Spawn waves of monsters

I'm making a simple racing game in which the monsters are spawned (randomly) from 3 out of the 5 lanes in the portrait mode.
-(void)addEnemy
{
SKSpriteNode *Enemy;
Enemy = [SKSpriteNode spriteNodeWithImageNamed:#"Enemy1"];
[Enemy setScale:.65];
Enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Enemy.size];
Enemy.physicsBody.categoryBitMask = obstacleCategory;
Enemy.physicsBody.dynamic = YES;
Enemy.zPosition = 2;
Enemy.physicsBody.contactTestBitMask = TurtleCategory;
Enemy.physicsBody.collisionBitMask = 0;
Enemy.physicsBody.usesPreciseCollisionDetection = YES;
Enemy.name = #"Enemy";
//selecting random y position for Enemy
int r = (arc4random() % 5) ;
Enemy.position = CGPointMake(48+r*56,self.frame.size.height);
[self addChild:Enemy];
SKAction *actionMove =
[SKAction moveTo:CGPointMake(Enemy.position.x,-80)
duration:1.43];
[Enemy runAction:actionMove];
SKSpriteNode *Enemy2;
Enemy2 = [SKSpriteNode spriteNodeWithImageNamed:#"Enemy1"];
[Enemy2 setScale:.65];
//Adding SpriteKit physicsBody for collision detection
Enemy2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Enemy.size];
Enemy2.physicsBody.categoryBitMask = obstacleCategory;
Enemy2.physicsBody.dynamic = YES;
Enemy2.zPosition = 2;
Enemy2.physicsBody.contactTestBitMask = TurtleCategory;
Enemy2.physicsBody.collisionBitMask = 0;
Enemy2.physicsBody.usesPreciseCollisionDetection = YES;
Enemy2.name = #"Enemy2";
//selecting random y position for Enemy
int r2 = (arc4random() % 5) ;
Enemy2.position = CGPointMake(48+r2*56,self.frame.size.height);
[self addChild:Enemy2];
SKAction *actionMove2 =
[SKAction moveTo:CGPointMake(Enemy2.position.x,-80)
duration:1.43];
[Enemy2 runAction:actionMove2];
SKSpriteNode *Enemy1;
Enemy1 = [SKSpriteNode spriteNodeWithImageNamed:#"boss1"];
[Enemy1 setScale:.65];
//Adding SpriteKit physicsBody for collision detection
Enemy1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Enemy1.size];
Enemy1.physicsBody.categoryBitMask = obstacleCategory;
Enemy1.physicsBody.dynamic = YES;
Enemy1.zPosition =2;
Enemy1.physicsBody.contactTestBitMask = TurtleCategory;
Enemy1.physicsBody.collisionBitMask = 0;
Enemy1.physicsBody.usesPreciseCollisionDetection = YES;
Enemy1.name = #"Enemy1";
int r1 = (arc4random() % 5) ;
Enemy1.position = CGPointMake(48+r1*56,self.frame.size.height);
[self addChild:Enemy1];
SKAction *actionMove1 =
[SKAction moveTo:CGPointMake(Enemy1.position.x,-80)
duration:1.43];
[Enemy1 runAction:actionMove1];
However, one of problem of this code is that monsters are sometimes spawned on top of each other. Is there a better way to do this?
Thanks
- (CGFloat)randomValueBetween:(CGFloat)low andValue:(CGFloat)high {
return (((CGFloat) arc4random() / 0xFFFFFFFFu) * (high - low)) + low;
}
I found this piece of code from a raywenderlich tutorial I think.
What u can do is call,
CGFloat r1 = [self randomValueBetween:0 andValue:3];
CGFloat r2 = [self randomValueBetween:3 andValue:6]; etc
that might give you different values that u can use as offset.

How to synchronize circle (with SKAction by SKShapeNode) to ball (by SKShapeNode)?

I try to synchronize circle (create with SKAction by SKShapeNode) to ball (create by SKShapeNode).
Here is this code. But it couldn't work well.
What should I do?
-(void)makeContents{
//make ground
UIBezierPath *groundPath = [UIBezierPath bezierPath];
[groundPath moveToPoint:CGPointMake(0,250)];
[groundPath addLineToPoint:CGPointMake(568,100)];
SKShapeNode *ground = [[SKShapeNode alloc] init];
ground.path = groundPath.CGPath;
[self addChild:ground];
//make ball
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball.jpeg"];
ball.position = CGPointMake(10, 320);
ball.size = CGSizeMake(20, 20);
ball.physicsBody.dynamic = YES;
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:3];
[self addChild:ball];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//make circle
UIBezierPath *circlePath = [UIBezierPath bezierPath];
[circlePath addArcWithCenter:ball.position radius:10 startAngle:0 endAngle:2*M_PI clockwise:NO];
circle = [[SKShapeNode alloc] init];
circle.path = circlePath.CGPath;
circle.strokeColor = [SKColor blackColor];
//this line added after first post.
circle.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10 center:ball.postion];
[self addChild:circle];
//make action
SKAction *scale = [SKAction sequence:#[[SKAction scaleBy:0.1 duration:2],
[SKAction scaleBy:0 duration:0.01]]];
[circle runAction:[SKAction repeatActionForever:scale]];
}
Thank you in advance for your help.

How to add to ammo if item collected sprite kit

i have a game where the guy runs around and collects stuff. So I want the score keeper to update and increase if he collects an item and decrease if he uses the item. For example, life item. so here is the code I got so far for labels but that works with text score not integers. any ideas? thanks
- (void)setupUI
{
int barHeight = 45;
CGSize backgroundSize = CGSizeMake(self.size.width, barHeight);
SKColor *backgroundColor = [SKColor colorWithWhite:10 alpha:50];
SKSpriteNode *hudBarBackground = [SKSpriteNode spriteNodeWithColor:backgroundColor size:backgroundSize];
hudBarBackground.position = CGPointMake(0, self.size.height - barHeight);
hudBarBackground.anchorPoint = CGPointZero;
[_hudLayerNode addChild:hudBarBackground];
// 1
SKLabelNode *scoreLabel = [SKLabelNode labelNodeWithFontNamed:#"AvenirNextCondensed-HeavyItalic"];
// 2
scoreLabel.fontSize = 20.0;
scoreLabel.text = #"Score: 0";
scoreLabel.name = #"scoreLabel";
scoreLabel.fontColor = [SKColor orangeColor];
// 3
scoreLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
// 4
scoreLabel.position = CGPointMake(self.size.width - self.size.width / 4, self.size.height - scoreLabel.frame.size.height + 3);
// 5
[_hudLayerNode addChild:scoreLabel];
_scoreFlashAction = [SKAction sequence: #[[SKAction scaleTo:1.5 duration:0.1],
[SKAction scaleTo:1.0 duration:0.1]]];
[scoreLabel runAction: [SKAction repeatAction:_scoreFlashAction count:10]];
}
double score; //property
-(void)setupUI {
//...
SKAction *tempAction = [SKAction runBlock:^{
scoreLabel.text = [NSString stringWithFormat:#"Score: 3.0f", self.score];
}];
SKAction *waitAction = [SKAction waitForDuration:0.2];
[scoreLabel runAction:[SKAction repeatActionForever:[SKAction sequence:#[tempAction,waitAction]]]];
//...
}