Question

I'm currently in the process of converting one of my projects over to SpriteKit, and I'm having some trouble with my conversions of animateWithDuration to SKAction MoveByY: duration: First is the fact that animateWithDuration gives you a nice aesthetic speeding up and slowing down which is lost in SKAction. Annoying, but not game breaking. Second is the fact that animateWithDuration will calculate its end position immediately, whereas SKAction calculates its position constantly. This is a problem for me because I have a gameboard where a row of spriteNodes are moving down the screen. If a node in the middle of this row is deleted, I need the nodes below that node to move up to the now vacant position(s). This means that they are going to a moving target, and using SKAction they overshoot the position. I could solve this buy adding another SKAction, but then I have to account for the pieces falling at different speeds and it starts to get messy fast. I was wondering if anyone had a nice clean solution that didn't involve guesswork? Ideally I would just run the animateWithDuration on the spriteNode, but unfortunately that doesn't work.

This was my initial animation code:

[UIView animateWithDuration:collapseSpeed animations:^{[[[_activePiecesVerticalOne objectAtIndex:piecesInArrayOne - 1] imageView] setCenter:CGPointMake (30, _positionOfLastObjectArrayOne )]; }];

and this is my new code:

SKAction *collapseUp = [SKAction moveToY:positionOfLastObjectArrayOne duration:collapseSpeed];
collapseUp.timingMode = SKActionTimingEaseInEaseOut;  //thanks Can!
SKAction *correctPosition = [SKAction moveByX:0 y:correctionVariable duration:.1];
SKAction *theAnimation = [SKAction group:@[collapseUp, correctPosition]];

[[_fallingPiecesRowOne objectAtIndex:piecesInArrayOne - 1] runAction:theAnimation];

Apologies to Can, as I was actually already using moveTo and not moveBy. The variable correctPosition = fallingPiecesSpeed * 25. fallingPieceSpeed is -.1, which is how far every falling piece is moved every .01 seconds via the update method. I rationalized that during the .25 seconds it takes to animate the piece up, it was missing 25 of these -.1 movement increments and thus implemented this to try and fix my issue. I believe that using the animateWithDuration, these movement increments would be stored and applied to the piece as it falls, which is what I'm missing with SKAction. This solution seems to work ok as long as I keep fallingPieceSpeed at -.1, but cranking it up to -.3 gives me major inconsistencies on where the pieces end up.

Hopefully this makes sense. As I mentioned, I was hoping to bypass all of this with a cleaner approach, but I may have to just keep tinkering with this to find my solution :S

Was it helpful?

Solution

If you're using the animateWithDuration:, I assume you know the final position, right? Then, instead of using SKAction +moveByY:duration: use SKAction +moveToY:duration:.

And the "speeding" you want, is a simple timing function, which in the case of an SKAction, can be changed on the instance object SKAction -setTimingMode:

So essentially:

SKAction *action = [SKAction moveToY:someYValue duration:0.15];
action.timingMode = SKActionTimingEaseInEaseOut;

Edit

It's hard for me to assess the issue, there's a lot of things involved, and my knowledge of SpriteKit is not that big, but I know about Core Animation.

My biggest worry is that you're taking values from SpriteKit which may have not been fully committed to the model layer. Notice this term, there are two forms of a layer, the model layer and the presentation layer, the model layer retains the actual properties of a layer, and the presentation layer is a intermediary layer that has the current animated properties. You can actually access all this properties via the view.layer.presentationLayer.

A general rule of thumb to deal with animations, is to do everything via relative values. So rows that need to move up should do it based on a fixed amount (the sprite's height), so the moveByY: isn´t as bad as it first seemed, but make sure that everything is relative.

Another alternative, is that you use SKPhysics, where the last row keeps pushing things up, and all the other pieces fall with gravity/bounciness.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top