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

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.

Related

SpriteNodes are disappearing randomly upon collision

I'm creating an iOS iPhone game similar to tetris where blocks fall from the sky and stack up on each other. However, my SpriteNodes blocks randomly disappear sometimes when a block comes on top of another one.
This is my block placement, I call this for 10 iterations to place random blocks that fall:
-(void)setupBlocksForT:(float)time {
Block *block = (Block *)[SKSpriteNode spriteNodeWithImageNamed:#"block1"];
block.physicsBody = [SKPhysicsBody bodyWithTexture:block.texture size:block.size];
block.physicsBody.dynamic = YES;
block.physicsBody.allowsRotation = NO;
block.physicsBody.usesPreciseCollisionDetection = YES;
block.physicsBody.restitution = 0;
block.physicsBody.friction = 1.0;
block.physicsBody.categoryBitMask = BlockMask;
block.physicsBody.collisionBitMask = CharacterMask | GroundMask | BlockMask;
block.physicsBody.contactTestBitMask = BlockMask | CharacterMask;
double randomSize = rand_range_double(0.10, 0.5);
block.xScale = randomSize;
block.yScale = randomSize;
block.position = CGPointMake(rand_range_int(0, self.frame.size.width, self.frame.size.height);
SKAction *wait = [SKAction waitForDuration:1.5 * time];
SKAction *spawn = [SKAction runBlock:^{
[self.myWorld addChild: block];
}];
SKAction *spawnSequence = [SKAction sequence:#[wait, spawn]];
[self runAction:spawnSequence];
}
Nowhere in my code do I call a remove(node).
I'm developing using SpriteKit and my setup is having an SKNode that contains all of my blocks so that the camera stays focused on my character's position in the DidSimulatePhysics() method.
Has anyone run into an issue where their sprites are randomly disappearing?

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

Spritekit node jitters while moving.... why?

Im trying to make a node move using SKAction but whenever I add the node and move it, it begins to jitter up and down along the y axis like crazy!
Any ideas?
I've tried using MoveToY, MoveTo, etc.. and no luck not sure what is causing the jitter..
Thanks..
-(void)addEnemy{
enemy = [SKSpriteNode spriteNodeWithImageNamed:#"enemy"];
enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(40, 40)];
enemy.physicsBody.dynamic = YES;
enemy.physicsBody.usesPreciseCollisionDetection = YES;
enemy.physicsBody.categoryBitMask = enemyHitCatagory;
enemy.physicsBody.contactTestBitMask = bulletHitCatagory;
enemy.physicsBody.collisionBitMask = bulletHitCatagory;
enemy.position = CGPointMake(random() % 300, CGRectGetMaxY(self.frame));
enemy.size = CGSizeMake(40, 40);
enemy.zPosition = 5;
SKAction *attack = [SKAction moveTo:(CGPointMake(20, 300)) duration:(3)];
[enemy runAction:[SKAction repeatAction:attack count:1]];
[self addChild:enemy];
}
This is happening because the physics bodies are colliding. By default, an SKPhysicsBody has a restitution of 0.2, making it a little bouncy. Setting enemy.physicsBody.restitution = 0 and doing the same for the physics body your enemy is colliding with should resolve the jitter you're seeing.

method not spawning sprite properly

Right now I have five bricks at the top of the screen all on the same y position and equally spaced apart. I would like to have five more breaks spawn outside of the top of the scene and slide down every 5 seconds. While the new bricks are sliding down I want the previous bricks to slide down to make room for the new. I want this sequence to continue on forever. I would like the new bricks to pick up the same properties of the old ones , such as when a ball hits them the react.
With the code I put in to accomplish this, I get a single brick spawning and then sliding down. Also the new brick does not act the same way as the old, it does not act like its a part of the physics world. How do I get 5 bricks spawning then sliding down and applying the same properties as the other bricks.
This code is the code I added to spawn more bricks:
-(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 runBlock:^{[self addChild: brick];
SKAction *move = [SKAction moveByX:0 y:-80 duration:3];
[brick runAction: move];
}];
SKAction *spawnSequence = [SKAction sequence:#[wait, spawn]];
SKAction *repeatSequence = [SKAction repeatActionForever:spawnSequence];
[self runAction:repeatSequence];
}
}
This code adds the bricks into the scene right when it initializes, they react to the ball colliding with them and everything:
- (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/5 * (i+.5);
int yPos = size.height - 25;
brick.position = CGPointMake(xPos, yPos);
brick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:brick.frame.size];
brick.physicsBody.dynamic = NO;
brick.physicsBody.categoryBitMask = brickCategory;
//add bricks to scene
[self addChild:brick];
}
}

Fixed floor in Sprite Kit Xcode

I can't seem to get a unmovable fixed floor / wall in Sprite Kit.
I have a scene which has an SKNode as a "floor" and when the user presses the screen, a block drops from the touched position onto the "floor". That works well, but when the user adds another lets say 20 blocks or so, suddenly the floor rotates.
This is the code for my Floor:
SKSpriteNode *floorNode = [[SKSpriteNode alloc] initWithColor:[SKColor clearColor] size:CGSizeMake(self.size.width*2, 10)];
floorNode.position = CGPointMake(CGRectGetMidX(self.frame), -5);
floorNode.name = #"floor";
floorNode.zPosition = 1;
floorNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:floorNode.size];
floorNode.physicsBody.affectedByGravity = NO;
floorNode.physicsBody.dynamic = NO;
floorNode.physicsBody.usesPreciseCollisionDetection = YES;
return floorNode;
Sorry i'm quite new to Sprite Kit. Does anyone know what's wrong with my code?
EDIT: I've added some images to make the problem a bit more clear. Since it happens in this screen also. Those black spheres you see are flying from left to right like a canonball. I increased the amount of spheres to show the problem occurring. This is the code:
- (SKNode *)newEditButton {
SKLabelNode *editButtonNode = [SKLabelNode labelNodeWithFontNamed:#"chalkduster"];
editButtonNode.text = #"EDIT CASTLE";
editButtonNode.fontSize = 19;
editButtonNode.fontColor = [SKColor darkGrayColor];
editButtonNode.position = CGPointMake(CGRectGetMidX(self.frame) + 110, CGRectGetMidY(self.frame) + 30);
editButtonNode.name = #"edit_button";
editButtonNode.zPosition = 2;
editButtonNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(140, 40)];
editButtonNode.physicsBody.usesPreciseCollisionDetection = YES;
editButtonNode.physicsBody.dynamic = NO;
editButtonNode.physicsBody.affectedByGravity = NO;
SKAction *hover = [SKAction sequence:#[[SKAction moveByX:0 y:6.0 duration:0.9],
[SKAction moveByX:0 y:-6.0 duration:0.9]]];
SKAction *hoverForever = [SKAction repeatActionForever:hover];
[editButtonNode runAction:hoverForever];
return editButtonNode;
}
- (SKNode *)newPlayButton {
SKLabelNode *playButtonNode = [SKLabelNode labelNodeWithFontNamed:#"chalkduster"];
playButtonNode.text = #"SLAUGHTER";
playButtonNode.fontSize = 19;
playButtonNode.fontColor = [SKColor darkGrayColor];
playButtonNode.position = CGPointMake(CGRectGetMidX(self.frame) - 110, CGRectGetMidY(self.frame) + 30);
playButtonNode.name = #"play_button";
playButtonNode.zPosition = 2;
playButtonNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(140, 40)];
playButtonNode.physicsBody.usesPreciseCollisionDetection = YES;
playButtonNode.physicsBody.dynamic = NO;
playButtonNode.physicsBody.affectedByGravity = NO;
SKAction *hover = [SKAction sequence:#[[SKAction moveByX:0 y:6.0 duration:0.9],
[SKAction moveByX:0 y:-6.0 duration:0.9]]];
SKAction *hoverForever = [SKAction repeatActionForever:hover];
[playButtonNode runAction:hoverForever];
return playButtonNode;
}
After a while 5-10 seconds, the "buttons" called "slaughter" and "edit castle" start to rotate everytime a sphere collides with it. But it doesn't seem like it has to do something with physics, because, if it rotates to the left, it's rotation direction will always be left. And if it starts rotating right, it's rotation direction will always be right.
It looks funny though! But not what i want ;-)
You don't know it, but you're telling SpriteKit to apply collisions from the cannonballs to the labels, and from the blocks to the floor!
That's because you're leaving SKPhysicsBody.collisionBitMask to its default value, which is to observe collisions for everything.
From the documentation:
Discussion
When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a nonzero value, this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.
The default value is 0xFFFFFFFF (all bits set).
So, do:
floorNode.physicsBody.collisionBitMask = 0

Resources