Well, the title says it all. If I am currently in a presented Scene of which I have initialized a Background SpriteNode to be a class constant, then how do I use the same Background SpriteNode in my next presented scene without having to create another SpriteNode that behaves and looks exactly the same as in the previous scene.
Will creating another SpriteNode be costly, assuming the background object loads its texture from a texture atlas?
And, I am using Swift.
Something like this should work.
backgroundSprite.removeFromParent()
nextScene.addChild(backgroundSprite)
Related
Have a couple of child nodes in a scene, and do a quick transition to a new scene.
In the new scene, didMove(to view: ….) is used to add the children from the previous scene to this next scene.
SceneKit crashes when doing this quickly, seemingly because the children of the old scene haven’t yet been released.
If I add a slight delay before adding the children to the second scene, it’s fine… it seems SpriteKit isn’t releasing the child fast enough for the scene transition.
the above is the most important thing to understand with regard the purpose for this question. I (wrongly) assumed SpriteKit would make sure all nodes attached to a scene were released before attempting to add them to a subsequent scene. It doesn't do this. But it does release them, it just takes a little time. Is this one frame? One second? Dunno...
My scene transition time is 0.25 seconds
Also tried using willMove(to view: ….) in the original scene to manually remove the children. This also doesn’t work, seemingly same behaviour: not fast enough.
Also tried assuming the child still has a relationship to its parent, so tried moving to its new parent, the new scene, with move(toParent:…) this also crashes. So maybe the children are already flagged as about to be released, I suppose.
Is this known about, and if so, how is it dealt with?
You can't present a scene and have willMove function at the same time in the same frame (SK loop)--your next scene's viewDidLoad will be called before the previous scene is destroyed. You have to remove all of the nodes before calling presentScene:
I suggest making a global variable of some sort to access your SKView; with that you can have control over your scenes from anywhere:
currentScene.removeAllChildren()
gView!.presentScene(nextScene)
“Is this a known about, and if so, how is it dealt with?"
Yes, this is a known issue of the SceneKit and IOS design and operational paradigms. It is considered that a scene must always be present and upon the screen. Can't have time without a scene onscreen.
As a result, for a brief time during transitions, both scenes are loaded, and active.
There are three ways to do deal with this problem:
Remove all content from the old scene prior to executing the transition so it can be instantly loaded by the new scene in didMove(to view...
or
Wait for completion of the transition before loading any content from the old scene into the new scene so there's no ownership conflicts of children.
or
KnightOfDragon’s first suggestion to use .copy() so there’s not the same instances being fought over by the scenes.
I'm currently creating a 2D game in Swift using SpriteKit and I'm having a problem with the collision detection.
Let's say I have SKSpriteNode Foo in the game. Then let's say SKSpriteNode Bar spawns on top of Foo, but does NOT have the contactTestBitMask to trigger a contact. Then after a short moment (let's say 1 second) Bar changes its contactTestBitMask to detect contact with Foo.
Currently, Foo will have to actually move around a little bit OR move out from under Bar and return back to it to detect contact with it. I need Bar to immediately trigger contact with Foo when it changes its contactTestBitMask.
Maybe there's a different way to do this without changing the contactTestBitMask?
Thanks!
If you create a physics body object intersecting another physics body object, no collision will register. It has something to do with the way SK registers a collision through movement only.
You have the option of using intersectsNode: when creating your object to see if it intersects another object and handle any subsequent code accordingly.
I have imported a Collada file into my scene and I am using allowsCameraControl to rotate / pan the object / pan the object
I now need functionality to jump instantly to the front or side view of the object.
Does anybody know how I can get the camera that Scenekit implements in my scene and how to rotate this camera to show the front and back view ?
"Front view" and "side view" are notions that are defined in terms of your content, so you have to define them yourself.
Create a node (let's call it "frontViewNode" for example) with an attached SCNCamera and position/orient it so that it's looking at whatever you call the "front" of your object. See this answer if you need help with that.
Create another node ("sideViewNode") that's looking at whatever you call the "side" of your object.
When you want to switch views, set the pointOfView property on the SCNView displaying your scene to either your "frontViewNode" or your "sideViewNode". You can even do this inside an animation (see SCNTransaction) to make the camera view swoop around between the two viewpoints.
I'm following this question's advice on how to create my game world for a scroller game with camera centered on the player. However, the advice says to use an SKShapeNode; I don't know how I feel about that.
Are there any advantages/disadvantages to using either a shape node or an skscene (or another type of object/node)? Is there a node that is considered best practice to use as a world?
Also, is it possible to create an skscene inside an skscene, or is that bad practice/discouraged?
Thank you!
You can't put a scene inside a scene per-say but you could stagger view controllers and place a view controller on top of another and then put the scene on top of that inset view controller.
The way I implement my scroller games is to put the player in the center and then move the background around. (Checking for bounds of course.)
As far as your advantages/disadvantages I'm not sure what you mean by the SKNodes; that's how you should do it if you're working just in SpriteKit. But don't add another SKScene unless you have something that you can't implement in just one SKScene.
I am on the master branch so that it will work with ARC.
I have implemented a method whereby the sprite will scale by a factor of 1.1 when a user touches the sprite. Multiple touches will queue up multiple scaling actions, built on top of each other. Every now and then I get a strange artifact where the smaller version of the sprite shows up on top of the scaled version.
Here's a screenshot:
More background: I'm using a texture atlas so I use:
sprite = [super spriteWithSpriteFrameName:anObject.filename];
to initialize the sprite. Is this a bug in openGL/cocos2d? Any advice on how to stop this artifact?
EDIT:
I am subclassing CCSprite but as far as I can tell there is only one instance of the sprite (the call to super was in a class method). Basically the user will define a list of actions that the sprite will do. The action list can also be interrupted using:
[self stopAllActions]
I've had actions using subclasses of CCMoveBy and CCRotateBy with no issues. It's only the most recent subclass of CCScaleBy that is causing this artifact. In the subclasses of these actions I'm not changing anything in the actions, just tracking certain variables so that I can properly resume the action after the interrupt.
Are you perhaps subclassing CCSprite, and in your subclass did you add a CCSprite instance variable as well?
In that case you'll be showing two sprites. The super class sprite and the instance variable sprite. If the other sprite shows up only sometimes this may depend on the order of adding sprites as childs, or the zOrder property.