I am working on a game, and I am using an alpha mask to create an SKPhysicsBody for the basket + catcher. The SKView has showPhysics set to true.
I can't figure out what in the world the disc is hitting. There is no physics field there. When I recreate the reference node with SKSpriteNodes this works flawlessly. I would like to use a reference node though because it would make it easier to make lots of these quickly. Here is where I set up the reference node:
Here is where I create the scene itself:
I have zero idea at this point what is happening. Clearly there is an error with showing the physics as well, because there is no blue outline there.
Related
I'm new to ARKit and SceneKit. I have a rather complex scene coming from an 3D artist. He replaced some items with SceneKit objects. I now try to change the properties of one of the SCNNodes, in this case the scale property, in another case the position in space, and in yet another I have a SCNText where I change the string property:
feedScaler?.scale = SCNVector3Make(1.0, scale, 1.0)
feedText?.string = String(feedValue)
feedIndicator?.position.y = someNewValue
So, pretty straight forward. When I run the scene though, it seems that the changes here are only commited once, before the scene appears. Then nothing happens. Here's the thing:
the method which updates the properties runs once per frame
I print out the property values of the nodes to the console and they update each frame
the text updates, too, and is the only update which is actually rendered and visible.
Note: There's also animations in that scene that do not play unless I uncheck "Use scene time base". Maybe that is a hint regarding how the Scene's animations are handled...
I found the issue. I used a clone of the scene which caused the references to get lost. The documentation says:
Cloning or copying a node creates a duplicate of the node object, but not the geometries, lights, cameras, and other SceneKit objects attached to it—instead, each copied node shares references to these objects.
When the original gets lost all the references get useless.
So in my Space Invaders game, all collisions were working perfectly until I added a physics body created from a edgeChainFromPath which is a single line to represent the ground (an SKShapeNode created from 2 points). Now my invader bombs (which move via SKAction) notify when they hit the ground but my invaders (moved in update() by manually updating their positions) do not. My ship missiles (also moved by SKAction) DO notify when contacting an invader.
Question : if a physicsBody is moved manually and comes into contact with another physicsBody, is didBeginContact not called? (All physics interactions - bitMasks, delegates etc - are set correctly). I'm thinking the answer is 'No it's not' because that's the only explanation and makes sense picturing how Sprite/Kit probably works. I.e. A contact occurs when the SK engine itself moves a node and realises that it's physicsBody is being drawn on top of another physicsBody.
Edit - just realised that I have other physicsBodies in my scene that are stationary and that the invaders DO collide with, so it's not an SKAction thing. The difference might be that the new node I've added is an edge-based body belonging to an SKShapeNode, rather than a volume-based body for a SKSPriteNode, but nothing in the documentation that I can find states that this shouldn't work.
New question : Do volume-based bodies being moved manually not collide with stationary edge-based bodies?
Ok - my bad. The invaders' physicsBodies had dynamic=false. Every other sprite was dynamic, so all other collisions were working. My new shape was an edge-based body which also are dynamic=false.
Made that one change and all is Ok. I need to update my checkPhysics() routine to test for this.
Edit: I really should have seen this earlier - checkPhysics() was not printing that invader notifies when contacting ground, which I just put down to a glitch that I'd fix later. Whereas checkPhysics() deliberately doesn't report on nodes with dynamic=false. I think that when I wrote the function, I assumed that you'd set dynamic=false deliberately to not be involved in collision/contact detection. I should change it to print a warning.
I'm designing a game and in my game, rockets are launched. I've created an emitter, gotten it configured, and when my rocket is launched, it adds the emitter to the rocket. Problem is, the rocket is moving pretty fast and it appears that the particles follow the motion of the rocket - what I mean by that is, instead of the rocket leaving a "trail" of smoke behind it, the "smoke" looks the same as if the rocket weren't moving, I guess because it is a child of the rocket.
The only workaround I've thought to my problem is to:
-Create an ivar or property to hold the current position of the rocket and update this every frame
-When rocket is launched, add child of emitter to the scene, not to the rocket
-place it's position at the position of the rocket
-on update, follow the rocket
However, this seems extremely computationally expensive, to be checking to see if a rocket exists, getting it's position if it does, creating a new CGPoint for this position, and set the emitter position to this new point on every single frame. Also, it leaves very few options for having more than one rocket on the screen at the same time.
Any other, more elegant solutions?
You need to set the targetNode property of your emitter to the SKNode or SKScene that you want the smoke to stay on. That property sets the node that the emitter particles will be children of, that way when the rocket moves, the emitted particles stay in the same place.
NOTE: The emitter itself should still be a child of the rocket.
SKEmitterNode.targetNode docs
I'm working on a game in which the user should be able to trigger 'rods' that come out from the edge of the screen to displace elements on screen (balls). These projectiles roughly resemble pool-cues. Or perhaps pinball plungers, except that they start from the 'loaded' position (mostly offscreen), and when triggered, they eject out, then quickly retreat.
I'm unclear how I should build these with Sprite Kit.
The game uses the PhysicsEngine, and the onscreen balls should be effected both by gravity AND they should be displaced when they collide with the rods. However the rods should neither be effected by gravity, not displaced when they collide with the balls -- they should simply retreat regardless of whether they've made contact with the balls.
I realize I can set the affectedByGravity property for the rods. However because they will still displace slightly when they collide with the balls. How can I 'fix' or 'peg' them in place? Do I need to use an SKPhysicsSlidingJoint? If so, has anyone encountered any examples online? Is there a simpler way to do this?
A related physics engine, Box2D distinguishes static, kinematic, and dynamic bodies.
Kinematic bodies can move and will collide with other objects, but they are themselves not affected by dynamic bodies or forces like gravity. Thus, consider setting rod.dynamic = NO; but animate it with actions. See also here in the reference for SKPhysicsBody.
So I have a marionette I am making in Sprite Kit, and placing him in a scene. I have created a Marionette class, which is a subclass of SKNode, and when I create an instance of this class, I add a number of SKSpriteNodes to each other. This should give you an idea of how it works (I've snipped out the unnecessary lines):
[self addChild:self.head];
[self.head addChild:self.chest];
[self.chest addChild:self.leftLeg];
[self.chest addChild:self.rightLeg];
[self.leftLeg addChild:self.leftFoot];
[self.rightLeg addChild:self.rightFoot];
So, after doing this, I have my marionette showing up. I want to add a SKPhysicsJointPin to each of these connections. Code looks like this:
self.chestPin = [SKPhysicsJointPin jointWithBodyA:self.marionette.head.physicsBody bodyB:self.marionette.chest.physicsBody anchor:self.marionette.chest.anchorPoint];
At first I thought I could just set up all the pins inside the Marionette class, but that doesn't work (I get EXC_BAD_ACCESS if I recall). It turns out that I have to add the Marionette to the overall SKScene before I add the joints.
This make sense I guess, but I can't help thinking there should be some way I could just set everything up in the Marionette class, and then stick 2 lines of code in the scene to create a new Marionette, then addChild him to the Scene.
As it is, my SKScene subclass has a bunch of code now to add all the pins, and it doesn't feel like it fits in the Scene. Thoughts?
You don't want to use anchorPoint as anchor. The anchorPoint property is a factor which ranges from 0 to 1 and affects how the texture is offset from the sprite's position, ie the default 0.5/0.5 centers the sprite's texture on the sprite's position. In other words anchorPoint is not a position, and using that will anchor the body & head joint to the lower left corner of the screen.
Instead try using either chest or head's position as anchor, or the point in between the two.