Inverted texture caused from SKAction following a CGPath - ios

"orientToPath:YES" is causing the texture of an SKSpriteNode to be rotated 180 degrees while it follows the path. I still want the node's zRotation to adjust while following the path, but I want the texture to be facing its original direction.
SKAction *path = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5];
How can I fix this?

Setting your sprite node's yScale to -1 will flip the texture vertically. Your sprite should then be oriented correctly along the path.

Related

SKSpriteNode follow CGPath plus adding SKAction

I am making a game and I want an enemy to move in a circle but the enemy should have constant movement to the left as well. I have tried to create a circle path with CGPath and make it follow that path and then added a SKAction with constant left movement. But it seems that the node is just following the CGPath without left movement.
Is there any other way to make this possible?
This is my code at the moment:
CGMutablePathRef circle = CGPathCreateMutable();
CGPathAddArc(circle, NULL, 0, 0, 80, 0, 2*M_PI, true);
CGPathCloseSubpath(circle);
SKAction *followTrack = [SKAction followPath:circle asOffset:NO orientToPath:NO duration:1.5];
SKAction *forever = [SKAction repeatActionForever:followTrack];
[enemy runAction:[SKAction moveByX:-1000 y:0 duration:3.0]];
[enemy runAction:forever];
You can't move the same node with 2 move actions. What you can do is place the node in a container node. Then move the container node left while its child moves in a circle.
Another option is to not use SKActions and use something more dynamic and real-time by computing the centripetal velocity manually and shifting the centripetal point overtime. You can see an example of this in my answer here.

SKAction starting point

How do you set the starting point for a SKAction? I am trying to animate a node in a circle, but I can't set the starting position. It always is set by default. Here is my code:
CGPathRef circle = CGPathCreateWithEllipseInRect(CGRectMake(self.frame.size.width/2-75,self.frame.size.height/2-75,150,150), NULL);
self.circlePathActionClockwise = [SKAction followPath:circle asOffset:NO orientToPath:YES duration:5.0];
self.circlePathActionClockwise = [SKAction repeatActionForever:self.circlePathActionClockwise];
//[self.ball runAction:self.circlePathActionClockwise];
self.ball.speed = 1.0;
The starting point of the circle, when trying to move it, is based on the circles position. Try setting the position property like so:
circle.position = CGPointMake(100,100);
The above will set the position of the circle to 100,100.
CGPointMake takes the first number as the x axis coordinate and the second number as the y axis coordinate. I hope that helps.

Scrolling a Tilemap in Sprite-Kit (JSTileMap glitch)

Since JSTileMap extends SKNode, you can use the API to move and animate your tilemap like any other node. However, I keep getting this weird effect/glitch...
Code:
_tiledMap = [JSTileMap mapNamed:#"Cloud.tmx"];
if (_tiledMap) {
[self addChild:_tiledMap];
}
_tiledMap.position = CGPointMake(800, 0);
SKAction *scrollLeft = [SKAction moveTo:CGPointMake(600, 0) duration:4];
SKAction *scrollRight = [SKAction moveTo:CGPointMake(700, 0) duration:4];
SKAction *sequence = [SKAction sequence:#[scrollLeft, scrollRight]];
SKAction *repeat = [SKAction repeatActionForever:sequence];
[_tiledMap runAction:repeat];
Results:
As you can see, whenever the JSTileMap changes direction, depending if its left or right, the image gets cropped or something, I can't explain it. This doesn't happen if the node itself is a SKSpriteNode. I added numbers to the background image for visual reference.
EDIT
Further tests reveal that moving the JSTileMap's position manually (_tiledMap.position.x = x+1) in the update loop, has the same effect. It crops the image/tile when it animates left, and returns to normal when it animates to the right.
I found a work-around. Apparently the problem is that the first tileset column itself is being cropped for some reason (if anyone figures this out please let me know). So the solution is to create a tilemap that is 2 tile units wider than what your original tilemap dimension is. For example, if your tiles are set to 32x32 (tilemap of 1024x768), you should generate a tilemap of 1088x768 instead and start drawing after the first column.
See image below.
It seems I was using an old/unmaintained version of JSTileMap. Slycrel's version of JSTileMap addresses this issue.
https://github.com/slycrel/JSTileMap

SpriteKit MoveToX:duration from Current Stat

I am planning to move batch of sprite randomly accross x- axis from left to right say 0 to 320 and
right to left say 320 to 0 with some Constant duration,
Further each sprite i am placing at random position across x-axis,
but when i create my batch of sprite and apply that skaction on each one
SKAction *moveRight = [SKAction moveToX:320 duration:walkAnim.duration];
SKAction *moveLeft = [SKAction moveToX:0 duration:walkAnim.duration];
after some time the whole batch of sprites is moving in one direction, from left to right and then right to left
i know the problem is with my approach and to moveToX with Constant duration
I need Constant duration in my case, Is there something we have in moveToX like we do have in
[UIView setAnimationBeginsFromCurrentState:YES]
so that i can tackle the issue for batch sprites with random position across x-axis
Note when i give some space to call that action on each sprite, then its working fine, but i need all at one time.
One can get Sample app from here
EDIT
What i need i have updated the code here
but I need all the sprites present on the dice without any Timeinterval with the same actions applied on all of the sprites.
Any suggestion would be appreciated
thanks
Umer
To have a constant speed you will need to calculate the duration for the first move Action based on the current position of your sprite. after doing that first move, you can use your moveRight and moveLeft actions. Here is an example for starting to move Right.
CGFloat durationForFullDistance = walkAnim.duration;
CGFloat fullDistance = 320;
CGFloat firstDistance = fullDistance - sprite.position.x;
CGFloat durationForFirstMove = durationForFullDistance*firstDistance/fullDistance;
SKAction *firstMoveRight = [SKAction moveToX:320 duration:durationForFirstMove];
SKAction *moveRight = [SKAction moveToX:320 duration:durationForFullDistance];
SKAction *moveLeft = [SKAction moveToX:0 duration:durationForFullDistance];
SKAction *continousMove = [SKAction sequence:#[
firstMoveRight,
[SKAction repeatActionForever:[SKAction sequence:#[
moveLeft,
moveRight
]]]
]];
]]

Set the angle of a sprite in SpriteKit

How would I set the angle of a sprite to 45 degrees?
SKAction *rotate = [SKAction rotateByAngle: M_PI/4.0 duration:1];
only increases the angle by 45 degrees, what I want to do is have to SKSprite rotate however long it takes to get to 45 and then stop. Is there a method for that or will I have to hard code it?
Thanks!
The method you’re looking for is +rotateToAngle:duration:shortestUnitArc:, as in:
SKAction *rotate = [SKAction rotateToAngle:M_PI_4 duration:1 shortestUnitArc:YES];
You can also just use +rotateToAngle:duration:, but that always rotates counterclockwise; this variant goes in whichever direction requires the least rotation.
(also note that π/4 is already defined as a constant, M_PI_4; see usr/include/math.h)

Resources