SpriteKit animateWithTextures in iOS7 not working - ios

I'm trying to add a little animation based on two pngs, where I create two SKTextures with two images and create an SKAction, and have it run forever with [SKAction repeatActionForever] but nothing is happening, nothing is appearing on the screen.
Here's my code:
_planePropeller = [SKSpriteNode spriteNodeWithImageNamed:#"PLANE PROPELLER 1.png"];
_planePropeller.xScale = 0.2;
_planePropeller.yScale = 0.2;
_planePropeller.position = CGPointMake(screenWidth/2, _plane.size.height+10);
SKTexture *propeller1 = [SKTexture textureWithImageNamed:#"PLANE PROPELLER 1.png"];
SKTexture *propeller2 = [SKTexture textureWithImageNamed:#"PLANE PROPELLER 2.png"];
SKAction *spin = [SKAction animateWithTextures:#[propeller1, propeller2] timePerFrame:0.1];
SKAction *spinForever = [SKAction repeatActionForever:spin];
[_planePropeller runAction:spinForever];
[self addChild:_planePropeller];
Any ideas? Thanks a lot in advance!

could be your positioning details, are you sure they are correct? I've changed your code slightly (self.frame.size.width instead of screenWidth and the same for height, to position it in the centre of the view) and it works for me:
- (SKNode *)propellorNode
{
SKNode *planePropeller = [SKSpriteNode spriteNodeWithImageNamed:#"image1.png"];
planePropeller.xScale = 0.2;
planePropeller.yScale = 0.2;
planePropeller.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
SKTexture *propeller1 = [SKTexture textureWithImageNamed:#"image1.png"];
SKTexture *propeller2 = [SKTexture textureWithImageNamed:#"image2.png"];
SKAction *spin = [SKAction animateWithTextures:#[propeller1, propeller2] timePerFrame:0.1];
SKAction *spinForever = [SKAction repeatActionForever:spin];
[planePropeller runAction:spinForever];
return planePropeller;
}

So my problem was, actually, my own ignorance, since I first was adding my SKNodes, and the last, when the background should have been added the first, so it could be on the background :)
thanks a lot everybody for the answers!

Related

Sprites spawning in incorrect position

I have a row of 5 sprites and they spawn every 4 seconds and move down along the Y-axis. The sprites are spawning the correct amount each time, I have 5 sprites equal spaced apart across the screen, they're all center perfectly.
However when the performSelector action is called, when it spawns them in they don't go to the right position. The move over to the left so far that I can only see half a sprite on the left side of the screen. After testing it, it seems they are all stacked on top of each other at the wrong position.
Any idea whats going on? I'd appreciate any help. Here's all the code I'm using in the scene.
-(void) addBricks:(CGSize)size {
for (int i = 0; i < 5; i++) {
//create brick sprite from image
SKSpriteNode *brick = [SKSpriteNode spriteNodeWithImageNamed:#"brick"];
//resize bricks
brick.size = CGSizeMake(60, 30);
//psoition bricks
int xPos = size.width/7.5 * (i+.5);
int yPos = 450;
brick.position = CGPointMake(xPos, yPos);
//add move action
SKAction *wait = [SKAction waitForDuration:3];
SKAction *move = [SKAction moveByX:0 y:-36.9 duration:1];
SKAction *sequence = [SKAction sequence:#[wait, move]];
SKAction *repeatMove = [SKAction repeatActionForever:sequence];
[brick runAction:repeatMove];
[self addChild:brick];
}
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:(243.0f/255) green:(228.0f/255) blue:(165.0f/255) alpha:1.0];
//add action to spawn bricks
SKAction *spawn = [SKAction performSelector:#selector(addBricks:) onTarget:(self)];
SKAction *delay = [SKAction waitForDuration:4];
SKAction *delayThenSpawn = [SKAction sequence:#[delay, spawn]];
[self runAction:[SKAction repeatActionForever:delayThenSpawn]];
[self addBricks:size];
}
return self;
}
as LearnCocos2D mentioned in your last question.. you cant use a selector when youre passing a parameter into a method.
addBricks expects size .. you arent passing size into it.
change your spawn action to
SKAction *spawn = [SKAction runBlock:^{
// make this whatever size you want, i'm just using the scene's size
[self addBricks:self.size];
}];
that should get you started

Spawning sprites not working

Ok I'm fairly new to coding with sprite kit so I don't know too much. I'm trying to make 5 bricks spawn above the scene and then slide down into the scene every 5 seconds. I thought this code would work but it does absolutely nothing to my scene.
I have another method that has bricks already loaded into the scene and that works so I don't think that would affect this much but not really sure.
-(void) spawnMoreBricks:(CGSize)size {
for (int i = 0; i < 5; i++) {
SKSpriteNode *brick = [SKSpriteNode spriteNodeWithImageNamed:#"brick"];
//resize bricks
brick.size = CGSizeMake(60, 30);
//position it
brick.position = CGPointMake(self.size.width/2, self.size.height);
SKAction *wait = [SKAction waitForDuration:5];
SKAction *spawn = [SKAction scaleTo:1 duration:0];
SKAction *move = [SKAction moveByX:0 y:-80 duration:3];
SKAction *spawnSequence = [SKAction sequence:#[wait, spawn, move]];
[self runAction:spawnSequence];
}
}
SKAction *wait = [SKAction waitForDuration:5];
SKAction *spawn = [SKAction runBlock:^{[self addChild: brick];
SKAction *move = [SKAction moveByX:0 y:-80 duration:3];
[brick runAction: move];
}];
SKAction *spawnSequence = [SKAction sequence:#[wait, spawn]];
[self runAction:spawnSequence];
Here is a modified set of actions to use. The problem was that you were running all the actions on the scene itself. The code provided runs a sequence on the scene that waits 5 seconds (acting as the delay), and then runs a spawn action. runBlock allows us to add the brick to the scene, create the move action, and apply that action to the brick (not the scene)

Possible way to move Nodes in a set duration without varying speeds?

I am trying move nodes to a set X distance using an SKAction with the same duration. The Nodes are in different X positions so the speed of how the node moves is different, is there a way to make the speed the same without affecting the positioning of the nodes?
Example.
-(void)beginningGamePlatforms {
SKSpriteNode *beginningPlatform = [SKSpriteNode spriteNodeWithImageNamed:#"PlatformBeginning"];
beginningPlatform.zPosition = 2;
beginningPlatform.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:beginningPlatform.size];
beginningPlatform.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
beginningPlatform.position = CGPointMake(beginningPlatform.position.x - 20, beginningPlatform.position.y - 129);
beginningPlatform.physicsBody.dynamic = NO;
SKSpriteNode *platformSpawn1 = [SKSpriteNode spriteNodeWithImageNamed:#"platformSpawn1"];
platformSpawn1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:platformSpawn1.size];
platformSpawn1.position = CGPointMake(beginningPlatform.position.x, CGRectGetMidY(self.frame));
platformSpawn1.position = CGPointMake(platformSpawn1.position.x + 196, platformSpawn1.position.y - 129);
platformSpawn1.physicsBody.dynamic = NO;
SKSpriteNode *platformSpawn2 = [SKSpriteNode spriteNodeWithImageNamed:#"platformSpawn1"];
platformSpawn2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:platformSpawn2.size];
platformSpawn2.position = CGPointMake(platformSpawn1.position.x,CGRectGetMidY(self.frame));
platformSpawn2.position = CGPointMake(platformSpawn2.position.x + 196, platformSpawn2.position.y - 129);
platformSpawn2.physicsBody.dynamic = NO;
SKAction *moveLeft = [SKAction moveTo:CGPointMake(-100 , beginningPlatform.position.y) duration:9];
SKAction *removeFromParent = [SKAction removeFromParent];
SKAction *AllTwo = [SKAction sequence:#[moveLeft,removeFromParent]];
[self addChild:beginningPlatform];
[self addChild:platformSpawn1];
[self addChild:platformSpawn2];
[beginningPlatform runAction:AllTwo];
[platformSpawn1 runAction:AllTwo];
[platformSpawn2 runAction:AllTwo];
}
In my code I created 3 platforms with a set distance within each other that when the sprite images combined, it creates the illusion of a single wide platform. However when running the actions, the illusion breaks. Any information will be appreciated.
You can try replacing the moveTo: in:
SKAction *moveLeft = [SKAction moveTo:CGPointMake(-100 , beginningPlatform.position.y) duration:9];
with a moveBy: varient. Currently, the different platforms start at different positions to make the illusion of a continuous platform, but by moving all of them to the same place, they won't maintain their original position intervals.

Implement my enemy class to the Game Scene

I'm still fairly new to programming and what I tried to do is the following: So I separated my Enemies from my game scene to a different class.
In the Enemy class.m file I declared 6 methods. Every method represents a new level, which will get called from the game scene.
So in the methods I declare the sprite's image, path, shooting particle type, etc..
Here's an example of the level 1 method in the EnemyClass.m file:
+(void)enemiesLevel1
{
EnemyName = #"enemy1";
SKSpriteNode* enemy = [SKSpriteNode spriteNodeWithImageNamed:EnemyName];
pathSpeed = 3;
CGPathRef path = CGPathCreateWithEllipseInRect(CGRectMake(0,0,400,400), NULL);
SKAction *followTrack = [SKAction followPath:path
asOffset:NO
orientToPath:YES
duration:pathSpeed];
SKAction *forever = [SKAction repeatActionForever:followTrack];
SKAction *addEnemy = [SKAction runBlock:^{
[GameScene addChild: enemy];
}];
SKAction *enemySequence = [SKAction sequence:#[addEnemy, forever]];
[GameScene runAction: enemySequence];
}
However, Xcode is states two issues:
No known class method for selector "addChild"
and
No known class method for selector "runAction"
I'm calling the method from GameScene.m with:
[EnemyClass enemiesLevel1]
It may seem like a dumb question, but I am still new and I would greatly appreciate any help!
The problem is, you should create instance of EnemyClasss in your GameScene and then use it; your code should look like this;
In EnemyClass.m:
-(void)enemiesLevel1
{
EnemyName = #"enemy1";
SKSpriteNode* enemy = [SKSpriteNode spriteNodeWithImageNamed:EnemyName];
pathSpeed = 3;
CGPathRef path = CGPathCreateWithEllipseInRect(CGRectMake(0,0,400,400), NULL);
SKAction *followTrack = [SKAction followPath:path
asOffset:NO
orientToPath:YES
duration:pathSpeed];
SKAction *forever = [SKAction repeatActionForever:followTrack];
SKAction *addEnemy = [SKAction runBlock:^{
[self addChild: enemy];
}];
SKAction *enemySequence = [SKAction sequence:#[addEnemy, forever]];
[self runAction: enemySequence];
}
In GameScene.m:
EnemyClass *enemy= [[EnemyClass alloc] initWithSize:self.size];
and then you can use:
[self addChild: [enemy enemiesLevel1]];

Setting the Physics Body, of a Sprite Node, starts flickering the animation

I have set the a sprite node, which is set to move in a circular motion.
Here is the code.
-(void) setUpMonkey{
SKTexture * monkey1 =[SKTexture textureWithImageNamed:#"monkey_walk_right_1_angle.png"];
SKTexture *monkey2= [SKTexture textureWithImageNamed:#"monkey_walk_right_2_angle.png"];
monkey1.filteringMode = SKTextureFilteringNearest;
monkey2.filteringMode = SKTextureFilteringLinear;
SKAction *_walking = [SKAction repeatActionForever: [SKAction animateWithTextures:#[monkey1,monkey2] timePerFrame:0.2]];
_monkey =[SKSpriteNode spriteNodeWithTexture:monkey1];
[_monkey runAction:_walking];
[_monkey setScale:0.5];
[self addChild:_monkey];
CGMutablePathRef circleMonkey = CGPathCreateMutable();
CGPathAddArc(circleMonkey, NULL, CGRectGetMidX(self.frame), CGRectGetMidY(self.frame), 80 + _monkey.frame.size.height/2, 0, M_PI*2, YES);
SKAction *followTrack = [SKAction followPath:circleMonkey asOffset:NO orientToPath:YES
duration:5.0];
SKAction *forever = [SKAction repeatActionForever:followTrack];
[_monkey runAction:forever];
}
This works well.
But once I set the Physics Body property of the _monkey (SKSpriteNode),
-(void) setUpMonkey{
SKTexture * monkey1 =[SKTexture textureWithImageNamed:#"monkey_walk_right_1_angle.png"];
SKTexture *monkey2= [SKTexture textureWithImageNamed:#"monkey_walk_right_2_angle.png"];
monkey1.filteringMode = SKTextureFilteringNearest;
monkey2.filteringMode = SKTextureFilteringLinear;
SKAction *_walking = [SKAction repeatActionForever: [SKAction animateWithTextures:#[monkey1,monkey2] timePerFrame:0.2]];
_monkey =[SKSpriteNode spriteNodeWithTexture:monkey1];
[_monkey runAction:_walking];
[_monkey setScale:0.5];
_monkey.physicsBody =[SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(_monkey.frame.size.width , _monkey.frame.size.height)];
[self addChild:_monkey];
CGMutablePathRef circleMonkey = CGPathCreateMutable();
CGPathAddArc(circleMonkey, NULL, CGRectGetMidX(self.frame), CGRectGetMidY(self.frame), 80 + _monkey.frame.size.height/2, 0, M_PI*2, YES);
SKAction *followTrack = [SKAction followPath:circleMonkey asOffset:NO orientToPath:YES
duration:5.0];
SKAction *forever = [SKAction repeatActionForever:followTrack];
[_monkey runAction:forever];
}
The whole animation is messed up. It starts flickering, and also the sprite starts moving in an eliptical motion.
What happens when I set the PhysicsBody?
P.S
I am a beginner at iOS Development.
Don't use physics and move/follow actions together.
The physics body will move your node through forces and manual velocity changes. Using actions that change the position of the node will mess with the physics behavior, and vice versa. Stick to one or the other.
At best you can disable gravity for the physics body, preferably also disable any collision feedback. Then you can move the node with physics body through actions and still be able to rely on physics contact callbacks to report contacts (but the body should resolve the collision forces, otherwise you get the same problem again).

Resources