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).
Related
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)
In my game i move many skspritenode along the same cgpath by :
[SKAction followPath:APath asOffset:NO orientToPath:YES duration:68]
If i add in scene all my skpritenodes at the same time they overlapping during followpath animation, so i have to add each sprite with some delay... In this way the sprites can't overlap but during the game i have "jittering" every time i had one of this sprite. I use something like this:
SKAction *InsertSpriteAction=[SKAction repeatActionForever:[SKAction sequence:#[[SKAction performSelector:#selector(AddSprite) onTarget:self],[SKAction waitForDuration:0.5]]]];
and to add the sprite:
-(void)AddSprite{
if (NumberofSprite<50) {
SKSpriteNode *Sprite=[SKSpriteNode spriteNodeWithImageNamed:#"sprite.png"];
Sprite.size=CGSizeMake(8, 8);
Sprite.position=CGPointMake(1320, 570);
[_worldNode addChild:Sprite];
NSMutableArray *textures = [NSMutableArray arrayWithCapacity:10];
for (int i = 1; i < 10; i++) {
NSString *textureName =
[NSString stringWithFormat:#"sprite%i", i];
SKTexture *texture =[SKTexture textureWithImageNamed:textureName];
[textures addObject:texture];
}
SKAction *spriteAnimation = [SKAction animateWithTextures:textures timePerFrame:0.2];
SKAction *repeat = [SKAction repeatActionForever:spriteAnimation];
[Sprite runAction:repeat];
[Sprite runAction: [SKAction repeatActionForever:[SKAction followPath:APath asOffset:NO orientToPath:YES duration:68]]];
NumberofSprite++;
}
else{
[self removeActionForKey:#"addingsprites"];
}
}
How i can start my sprites at different point along the path? With many startpoint in the same path i can add all my sprite at once during level loading and start a follow path without overlappings...
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]];
I want the jump to be realistic and the sprite not to jump so height
current code
[self.physicsBody applyImpulse:CGVectorMake(0, 2200)];
added action to the sprite
SKAction *incRight = [SKAction moveByX:1.0 y:0 duration:0.004];
SKAction *moveRight = [SKAction repeatActionForever:incRight];
[self runAction:moveRight];
I have two different SKSpriteNodes. The first is stationary and the second, I would like, to move around the first node. I have my second node is flying in from off screen with a zPosition of 11 (the first node has a zPosition of 10). When the second node flies to the opposite end of the screen, I have the node flip and fly back across. At this time I would like to change the zPosition to 9.
witch.position = CGPointMake(self.size.width + 200, self.size.height / 2 + 50);
witch.zPosition = 11;
[self addChild:witch];
SKAction *moveLeft = [SKAction moveToX:-200 duration:8];
SKAction *moveRight = [SKAction moveToX:self.size.width + 200 duration:8];
SKAction *moveDown = [SKAction moveToY:secondNode.position.y - 50 duration:0.3];
SKAction *moveUp = [SKAction moveToY:secondNode.position.y + 50 duration:0.3];
SKAction *flipRight = [SKAction scaleXTo:-1 duration:0];
SKAction *flipLeft = [SKAction scaleXTo:1 duration:0];
[secondNode runAction:
[SKAction repeatActionForever:
[SKAction sequence:
#[moveLeft, moveDown, flipRight, CHANGEZPOSITIONHERE, moveRight, moveUp, flipLeft, CHANGEZPOSITIONHERE]]]];
How would I go about changing the zPosition in the middle of an SKAction?
Thank you in advance for all suggestions and help.
This answer was found due to LearnCocos2D comment.
Adding a runBlock:action I was able to change the zPosition. The final code is:
[secondNode runAction:
[SKAction repeatActionForever:
[SKAction sequence:
#[moveLeft, moveDown, flipRight,
[SKAction runBlock:(dispatch_block_t)^(){
secondNode.zPosition = 9;
}], moveRight, moveUp, flipLeft,
[SKAction runBlock:(dispatch_block_t)^(){
secondNode.zPosition = 11;
}]]]]];