Group Group Group Group Group Group Group Group Group

raywenderlich.com Forums

Card Game Mechanics in Sprite Kit with Swift

Learn how to implement basic card game mechanics and animation with Sprite Kit and Swift.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1062-card-game-mechanics-in-sprite-kit-with-swift

I’ve borrowed from this tutorial on several projects… there’s some really great stuff in here.

I’ve been stuck on getting to the next step since the last version of this great tutorial … creating a Game State (or something) and having the cards implement even simple special powers such as forcing a draw or discard. I just can’t conceptually get my head around which objects should be sending messages and which should be listening to them and how to implement that. Should the scene be handling touches (as in this tutorial) ,or should the cards and then send them to the relevant objects, whether they be draw decks or discard locations. Does anyone have any resources they can recommend for next steps, or is anyone interested in conceptually working this out with me, either privately or in a public forum somewhere?

Maybe the next step to this tutorial series is a simple game like War that implements a game state including a full replay / undo stack, object messages and simple rules checking?

The original full sample game is at https://bitbucket.org/bcbroom/ccg (still in Obj C). Its not the cleanest implementation, but has turns, attacks, and special effects. It might give you some ideas.

i am having exploring SpriteKit again and wondering if a SKNode(or SKNode subclass) can render custom drawing? in other words if i want to draw shapes by hand in code and display those in a card - is that supported out of the box… i.e. instead of placing just pre-drawn images for the front and back. The initial answer might be, “well convert your drawings to an image” but what I would eventually like to do is take those shapes on a card (think of 2 or 3 on one card) and animate them independently (and go even further and have them react to hitting the edges of card with UIKit Dynamics etc)

The last time I went down this route I was dismayed to find out that unlike UIView subclasses, you cannot create SKNode subclasses that perform custom drawing. If thats still true… then there has to be a another way?

I’m not aware of anything like ‘drawRect’ for sprites. I think the best you can do is render it to an image and swap the texture.

I think you can do custom shaders now (have been out of SK for a little bit, just getting back in now), so I don’t know if that would help you. I don’t have any sense of what you can or can’t do with that.

i just got something to render using SKShapeNode. I made a SKShapeNode like so:

self.buttonNode = [SKShapeNode shapeNodeWithRect:CGRectMake(300, 300, 100, 100) cornerRadius:8.0];
self.buttonNode.fillColor = [SKColor whiteColor];
self.buttonNode.strokeColor = [SKColor orangeColor];
self.buttonNode.lineWidth = 5.0;
//buttonNode.physicsBody =

self.circleNode = [SKShapeNode shapeNodeWithCircleOfRadius:20];
self.circleNode.fillColor = [SKColor greenColor];
self.circleNode.position = CGPointMake(self.buttonNode.frame.origin.x + 30, self.buttonNode.frame.origin.y + 50);

[self.buttonNode addChild:self.circleNode];
[self addChild:self.buttonNode];

this renders to the screen on my iPhone device just fine.

that apple dev link is here: https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKShapeNode_Ref/

looks like you can create shapes made up of points or by using CGMutablePathRef (and I’m assuming BezierPath as well) as well as default stuff (like with my circle)

As you can see I’ve commented out the physics body part , but since this is a subclass of SKNode it looks like its available. You should be able to use here touchesBegan to identify the node touched as well. Unless I am mistaken you should be able to animate objects with the node as well using SKActions, etc.

I know in the past the SKShapeNode had some problems surrounding leaks/memory issues , etc and wasn’t well received. I am not sure what the state of that is now.

Thoughts?

Hey Brian,

Thanks for the awesome and thorough tutorial! I was following along and got stuck at the Tracking Damage section. I think there’s a typo with this:

Then, add the following to the init(texture:color:size:) method, before the call to super.init(texture:color:size:)

I believe init(texture:color:size:) method should actually be init(cardType: CardType) method.

Thanks again!

Kingston

I’m pretty sure the code is correct in the article - there are several init methods, though.

You add those lines inside init(cardType:), but before super.init(texture:color:size:). Does that help? You can also check the completed project files, if it would help to see it.

One thing I needed to do was set a zPosition on the SKLabelNode. Otherwise, it appeared to sometimes put it behind the card texture. I’m not sure why.

I noticed that when the user drags the cards around too quickly, this app drops them.

I went to a few published apps, such as 1010, which involve dragging things, and I noticed that a good, polished app does not drop anything.

how would you correct your code so that no matter how fast the user drags, if they don’t lift up their finger, the card will stick to that finger forever?

your app supports multi-touch gestures, maybe by accident… how would you make the cards stick to each of the user’s fingers, in the case that a multitouch drag gesture was underway?

OK, it’s been a week with no reply, but I went further and discovered another bug which is if the user is dragging a card and their finger gets away from the card, it will just sit there, jiggling without moving… if the still dragging finger touches one of the other cards, it will be picked up and moved…

that doesn’t seem like desirable behavior…

hoping to hear about bug fixes for these problems…

There are several ways to do touch handling. I picked the one I did for the article for simplicity. It fails when moving quickly because by the time the touch event comes in, your finger has moved outside the bounds of the card.

Another way would be to do the selection part only in touchesBegin, and save that card as a property in the scene, like movingCard. Then in touches moved, you change the card position. One downside to this is that you need to remember to clear the saved card in touchesEnd.

I see. So how would that go with multitouch? I can imagine an array holding all the moving objects but am unsure how I would keep each one with their original finger…

One gripe I have with a lot of these tutorials is they teach some basic version of code that actually would never be practical in a real world sense.

It’s like recipes for cooking… I’d rather know how to make the very best food and be the one to worry if it’s simple. Without showing the most robust, real world, optimized way to go about everything, how else is anybody going to learn how to be a world class programmer?

:hamburger: Thank you for the tutorial :hamburger:

i think theres a little error in the first approach to the card.swift file in the line:

super.init(texture: frontTexture, color: .clearColor(), size: frontTexture.size())

.clearColor() doesnt exist. In the final project you changed it for .clear and that works.

Thank you very much for the Card Implementation, I have a little question, as in normal card game , if I want to select my card and place it on the table (limit to a area) , how can I do that ? currently I can move my card to anywhere , what I want is , move my card to specific area , if the card is not in that area , my card should move back to my original location. else my card should stay within that area. Can anyone please suggest ? thanks

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]