Manipulating alpha property vs adding/removing node - swift

If I want a node or nodes (in this case a "panel" with two "buttons" - e.g.: a node to represent the panel, and two more nodes on that panel to represent buttons) to appear and be available to call actions (with the buttons using touchesBegan()), I seem to be able to do it by creating the nodes (color Sprites) in my .sks scene and using alpha = 0/1. I can also do it programatically by creating the node in .swift class and using .addChild()/.removeFromParent() functions.
Are these interchangeable approaches or is there a danger of using alpha since the nodes are still present, though not seen?

In Spritekit hidden and alpha properties are equal to 0 as default value.
From Apple regarding hidden objects
objects are not rendered. However the still exist in the scene and
continue to interact with it in other ways
So that would be the same thing as having created the object and not added it to a parent
Having just run a test on an object that was detected in the touchesBegan func.
When the object had .alpha = 0 it was still detected in the touchesBegan
When the object was created but not added to the parent it was still detected in the touchesBegan
So I think both methods are comparable
Edit> I stand corrected they are not comparable, please feel free to unselect my answer. Please comments to see pitfalls of using alpha = 0

Related

Why does parenting an object in the hierarchy produce different results then parenting via script?

Parenting GIF (for visual)
When parenting an object using the hierarchy you click and drag that object and place it into another game object.
When parenting an object using a script, it looks something like this
myObject.transform.SetParent(parentObject, false);
Now, if you watch the GIF you will see that the two different methods of parenting produce different results for the child objects transform values. The resulting position and scale are different for the child object depending on which approach to object parenting is used.
How do you get the same results produced when parenting in the hierarchy via click and drag, when parenting by script?
EDIT: Forgot to add that when watching the gif, you can see the click and drag parenting first and watch the transform values change. I then control Z to undo the change, click into the scene view, and execute a button press that sets the parent of the 'blue' game object to 'myObject'. Note, you will see the transform values don't change when parenting is done via the latter method.
If we check Unity's API documentation for the SetParent() method we can better understand how this method works. In my case I was using the method that used two parameters:
parent:
The parent Transform to use
worldPositionStays:
When false the object keeps its local orientation rather than its global
For my question, there are two simple solutions:
Set the worldPositionStays parameter to true so that the parent-relative position, scale and rotation are modified such that the child object keeps the same world space position, rotation and scale as before, or
Use the SetParent() method with only the parent parameter, effectively yields the exact same result as setting worldPositionStays to true.

How to duplicate a sprite in sprite kit and have them behave differently

I've been working on a IOS mobile game and I wanted to take an object,duplicate it, and have the copies move all over the screen. I've looked through Google to find things relevant to this but they were all in Objective C or just didn't have what I was looking for. I want to know how to do this in Swift and SpriteKit.
If you are working with SKSpriteNode you can copy it and all it's current properties with:
let copiedNode = nodeToCopy.copy() as! SKSpriteNode
You will still need need to add copiedNode to your scene. copiedNode will also continue to run any actions that nodeToCopy was running. You can cancel them with copiedNode.removeAllActions().
Note that the documentation for the protocol NSCopying reads exactly:
Protocol
NSCopying
A protocol that objects adopt to provide functional
copies of themselves.
The exact meaning of “copy” can vary from class to class, but a copy
must be a functionally independent object with values identical to the
original at the time the copy was made...
Indeed, in the case of SKSpriteNode, Apple have interpreted that idea so that the copy() function "spawns" another instance of the item, exactly as in any game engine.
(So, for SKSpriteNode copy() works identically to the sense of Instantiate in Unity, say.)
As mogelbuster points out below, there is nowhere in the Apple documentation that they state "The spawn command in Apple is copy()" but in fact they have interpreted this "The exact meaning of “copy” can vary from class to class" in exactly that way for SKNode, since indeed it's a game engine and it's the only meaningful sense of copy there.
It's worth noting that the most completely typical way to work in games is: for your say rocketShips, you would have one "model" of your rocketShip, say modelRocketShip. The model simply sits offscreen, or is perhaps marked as invisible or inactive. You never use the model in the game, it just sits there. When you spawn rocketShips, you just dupe the model. (So in Apple that's modelRocketShip.copy() and then set the position etc.)
You can define a function to create and return a sprite :
func createSprite()->SKSpriteNode{
let sprite = SKSpriteNode(...)//Use the init function in the SKSpriteNode class
//Add some code to define the sprite's property
return sprite
}
And call this function to get some sprites that have the same property:
let spriteOne = createSprite()
let spriteTwo = createSprite()
Then you can add different SKActions to each of them so that they can behave differently.
Once you have multiple SKSpriteNodes, you can also control them by using EnumerateChildNodesWithName (assuming all your nodes have the same name) to go through all of them do do what you want in the update() function.
On a more advanced level, you could subclass SKSpriteNode and incorporate your own behaviour in your custom class.

SWIFT: SKSpriteNode setting alpha to 0 vs. removing it from it's parent

I have a problem and I have to admit, I'm a bit of confused. I have to show/hide some SpriteNodes (those are some option buttons that will appear if the game is over). If the retry "button" (SpriteNode) is pressed by the player, the method that is called by that touch is setting it's alpha to zero. But sometimes it remains "active"(means alpha remains 1), behind other sprites and while the game is played again and the nodes that are in front of it are moving and it becomes visible. That is very confusing and being a random behavior I was thinking if removing it from it's parent (which is self, anyway) and adding it again when it's necessary is a better way to approach that kind of situations.
The code is like:
func restartGame()
{
restartButon.alpha = 0
......................
}
if nodeAtPoint(location).name == "someName"
{
restartGame()
}
It's good to mention that the appearance of this button is made by SKAction.fadeAlphaTo(1,1.5) and it's initially alpha is set to 0 in didMoveToView() override method.
Thanks.
If you still seeing it, it obviously means something in your program is setting the alpha to 1.
Why not just set the node's hidden property to true? This will hide it.
In general, if this is for UI elements which are not always displayed, you are better off by controlling these pieces by a parent node which can contain all of the UI elements. For example, you could have a "menu" node, which contains all of the button nodes. Note this is very simplistic in that more complicated UIs would require a more complicated node hierarchy. But this would work if your UI is layer "floating" over the game.
The advantage of this is you could either remove everything by removing the parent from the tree or just set the parent's hidden property to true

change parent of a CCSprite in cocos2D

I'm kind of new in cocos2Dm and i'm facing a problem that i can't solve
So far I have 2 sprites (let's call them tables) in the layer , that is touchable, one of them has added other sprites, that I wanna move from one table to another one, i'm recognizing the objets that I touch, & moving them around, My problem is that I can't change the parent to be the other table, I tried to remove the object from parent in different ways & add the no the new parent, but it doesn't seem to work, the object is duplicated cause it's not being removed, I even tried to remove them when I touch it.
I'm storing the objects in _objectsToDrag & calling this function in touchbegan:
- (void) lookForObjectWithTouchLocation:(CGPoint)touchLocation
{
for (RICCObject *object in _objectsToDrag) {
if (CGRectContainsPoint(object.boundingBox, touchLocation)) {
_selectedObject = object;
}
}
if (_selectedObject) {
[self objectSelectedWithLocation:touchLocation];
}
}
And then using _selectedObject to move it around, is this the problem? should I use aributes instead local objects in an array?
Any help is welcome
Thank you in advance
To move an instance of a class that derives from CCNode (like CCSprite, CCLabelTTF etc) from one parent node to another, follow this process:
// get yourNode in whatever way fits your implementation ...
CCNode* nodeToMove = yourNode;
// not cleaning up leaves actions running
[nodeToMove removeFromParentAndCleanup:NO];
// add the removed node to its new parent node
[newParentNode addChild:nodeToMove];
This process works regardless of how or where else you store the nodes.
Note that if you see nodes being duplicated, you either create a new node without removing the old node or you have two nodes to begin with. In cocos2d, a CCNode can only have one parent and trying to add a node that already has a parent to another node will prompt you with an error message. If you experience duplicated nodes respectively removing a node from its parent still keeps it on screen try to find the cause for that first. This is something that doesn't happen under normal circumstances, except when you actually create multiple versions of the same node.

Practical efficient usage of IBOutletColletion

How does look the practical usage of IBOutletCollection? Unfortunately Apple documentation mentions it briefly without giving an wider idea of usage. OK, it maintains one-to-many relation with IB, but how to access and use particular objects efficiently? With TagName? How to ensure the order of objects?
I've recently used this to easily initialize a grid of labels. I have a n by n matrix of labels on a view, and reference each one individually (via an IBOutlet) in order to display relevant data. However when the view first loads I wanted to control the default text that displayed in all the labels. Initially i wanted a dash to display, but since this is for a client I wanted it to be easy to change. The view contents have and continue to change over time, per client requests.
Instead of writing N line of code, I created an IBOutletCollection and accomplished the same results in 4 (#property, #synthesize, and for loop). YMMV but I found it very useful in this situation.
Read again this section in the Interface Builder User Guide.
IBOutletCollections are actually just NSArrays you can connect to more than one object in IB. All the objects you connected end up in this array and can be accessed from code like any other object in an array.
I used it to minimize code. I have a range of UIViews that should react on "touch up inside" events of some UIButtons (custom mode).
I gave all UIButtons a tag (lets say 1005 to 1010) and all UIViews the same tag as the UIButton they shall respond to.
Then I connected the UIViews with the collection in Interface Builder. All UIButton touch up events go to the same function in my controller. This function gets the tag of the sender object, iterates through the NSArray list (of "IBOutletCollection(UIView)") and compares the tag. Everytime it hits, the appropriate action is done.
It is a pity that NSArrays seem not to hold the order...