does anyone have any experience with SpriteKit for iOS using Xojo, ObjC or Swift?
I am attempting to write a card game, and the cards are each a “Card Class”… this class is a SKSpriteNode with the abiility to move in an animated fashion from Point A to Point B, spinning along the path … Basically its “dealing the card”
There is an array of this class (52 instances of course).
The Deal function loops thru these 52 instances… telling each card to deal itself to a specific location on the screen. The “board” consists of 18 “piles”
the deal is
For i=0 to 17
deal_card(ptr,i) // ptr is the next card, I is the pile to deal it do
creates an group of SKActions [move, spin, flip]
This all works very well … with ONE major flaw. the actual on screen animation occurs out of desired sequence
for example … Pile #1 is the card #1, card #17 and card #34
What I should see is
- card #1 move,spin, flip and end up on pile #1
- then all the rest of the piles
- card #17 move,spin, flip and end up on pile #1 (overlapping #1)
- then all the rest of the piles
- card #34 move,spin, flip and end up on pile #1 (overlapping #17)
but what I see instead is
- card #1,#17 and #34 all moving, spinning and flipping as a UNIT
- followed by the same for the other 17 piles
I have checked best I can, and the actions seem to be called correctly (ie. the actions for cards 2-16 happen in between 1 and 17 like they should)
I have altered the durantion of each step of the animation to see if anything disrupted the flow, and it doesn’t
I posted this as OFF-TOPIC as the question is not Xojo related as much as it is SpriteKit,
You should group them in a SKAction.Sequence or chain them with a RunBlock so that each concurrent action is called by the block of the previous one, whichever suits your project structure best.
See that is what is confusing… I did that.
Each indivuial card… has an action sequence that consists of
- a wait of fraction of a second
- a move action
- a rotate action (so the spin as they move)
those 3 actions are in a Group
then the flip action is last (but not in the group)
so the end sequence is [[wait/move/spin] flip]
this is done for each of the 52 cards in order… so I cannot see how the 1st/17th and 34th card [move/spin] togehter… as if they were dealt as a single unit at the same time
Do you of a way (I’ve searched) where ALL the actions for the SCENE can be laid out… So I could define the actions for all 52 nodes and then execute them together instead of each node on its own
The delay I had was based on position (the ID of the destination location)… so since #1, #17 and #34 all went to the same place they all had the same delay… The delay should have been based on the CARD number (1 to 52)… made that little change and it all dealt properly…
Just got back to this app… and am finding that dealing with animations is a PITA.
Not in getting them to work or not, but figuring the timing etc.
Take the above example. There is a layout of cards on the screen. The user makes a move, and various cards may move, be flipped faceup or down etc. There could be any number of “actions”, and each action belongs to a “card” not to the scene, so there could be dozens of actions in progress at any given instant.
So once the user completes their move, these animations begin, and then the app determines what moves are available for the next turn (also for hints, end of game check etc). HOWEVER… before it can accurately determine this information, all the animations MUST be completed so the board is in a stable state.
I could use a timer set to some abitrary value, and “hope” all the animations are done before the timer runs out, but that introduces a delay that may or may not be necessary based on what just happened.
If I turn all animation OFF, the app works perfectly, but doesn’t have that extra kick in the visuals
But you can chain a block call to the end of each action that could do something like decrease an actionRunning counter or something (and triggers the next step on count 0), or combine all actions into one group and finish that with a custom block that makes your app call the next step. Way more reliable than an arbitrary timer!
Could you describe that more? The issue I see is that each node is independant of all the others.
The only idea I have had so far is to create a stack (array)… and each time I need to have a node perform an animation, push that node onto the stack. Once all the nodes are on the stack. Execute the first one, and pop it off the stack, when its completion event runs have that check the stack for more, until finally the stack is empty at which time the “animation is complete”
Could be that this approach does not work with your current structure, but what I would do would be something like
a) Create a Group action instead of the stack where you put all parallel node animations into.
b) Put that group into a sequence.
c) Add a custom block action to the sequence that will trigger your main code.
d) Run the sequence.
That works for CONCURRENT actions (which is what I was doing in the OP)… but now I need to deal with up to 52 SEQUENTIAL actions
- block user interaction with the scene (and/or block main thread)
- move card #1…when its done, move #2 etc…
- restore user interaction
So the user cannot select (ie. initate new actions) until the current sequence is complete
So queue them up in a sequence and add the block action at the end. You can even staple groups in sequences in groups
But you can’t group the actions of independent nodes, can you??? The action/run is at the node level, not the scene (unless I am really missing something)
Well, the scene itself is a node. You should be able to use that as node for the Sequence and add the individual node actions to it.