I'm new using the SpriteKit Editor within XCode. I applied a resizeToWidth action to a simple Color Sprite Node. The Node has a physics body of the type bounding rectangle. The problem is the graphical representation is resizing but not it's body. The body just stays the same. See the result after applying the action, red is the sprite and the blue line it's bounding box.
How can I make sure that the physics body is resizing like the sprite?
Related
I have a placement marker (a simple plane with green corners) to visualize detected planes (via ARRaycastResult) in an ARView. This placement marker uses UnlitMaterial with a texture. Everything works fine as long as there is no other object added.
When I add another object, RealityKit also adds grounding shadow (invisible plane) right under the object. It works as a shadow plane and occludes everything behind it - including my placement marker.
Here is a picture of the placement marker (part of which is hidden under the shadow plane):
Is there any way to prevent this clipping? I was lookig for something like rendering order (as ARKit does have one), but have not fond anything in RealityKit yet.
I would like to keep the shadow plane if possible.
Edit: Added official name of the invisible plane (grounding shadow)
Reality kit automatically adds "grounding shadows" if the AnchoringComponent.Target is of type "plane". According to an Apple Engineer this can be aso simulated using a DirectionalLight with a Shadow and placing a plane (with an OcclusionMaterial) under the model. So the grounding shadow is probably also made out of OcclusionMaterial. This also explains why this grounding shadow occludes other objects.
There is an option to disable rendering of these grounding shadows. It can be done by inserting of disableGroundingShadows option into ARView's renderOptions property.
arView.renderOptions.insert(.disableGroundingShadows)
I have not yet found a way to override OcclusionMaterial (if any).
I am experimenting with ARKit and SceneKit and have been able to place boxes or custom shapes using UIBezierPath. What I’d like to do next is draw text and place images on the surface of these shapes. I’ve tried adding an image to the material property but this just fills the shape with an image. I’d like to have control over the size and position of the image / text relative to the shape. Is this possible?
You can do so by creating a new node for your text or image, and add it as a child node of your existing SCNNode (addChildNode). You can then position it as needed relative to your parent node, much as you have already done with your SCNNode.
For text you can make your SCNNode from an SCNText, or render the text into a bitmap and use it as a texture material of an SCNPlane.
I am starting to learn Swift2 to develop on iOS using SpriteKit and I cannot seem to detect if I touched a visible part of my Sprite.
I can find which node was touched like this:
let touchedNode = self.nodeAtPoint(location)
But this detect the touch on the sprite. I would like to detect the touch on the "not transparent" part of the sprite only.
I tried creating a PhysicsBody with an alpha mask bounding box and testing if the bounding box of the node I selected contains the location of the touch like this:
sprite.physicsBody = SKPhysicsBody.init(texture: sprite.texture!, size: sprite.size)
sprite.physicsBody?.affectedByGravity = false
if (touchedNode.containsPoint(location)){
But it didn't help. If I click in a transparent part of my sprite, the event still triggers.
The documentation says "A new physics body is created that includes all of the texels in the texture that have a nonzero alpha value.", so shouldn't it work?
Thanks for your time.
PS: I also tried to be more generous on my alpha threshold, but this also did not work (in case my transparency wasn't perfect).
UPDATE:
To add a little more details, I am building a level editor. This means that I will create many nodes, depending on what the user chooses, and I need to be able to select/move/rotate/etc those nodes. I am actually using SKSpriteNodes as my PNG pictures are automatically added in xcassette that way. I decided to use the PhysicsBody's Alpha Mask bounding box, as this value is shown in the Scene Editor (Xcode) when you select a node, and when selected, the Alpha Mask highlights exactly the part of my Sprite that I want to be able to detect a touch inside.
If I am using the wrong ideas/techniques, please tell me. This is possible as I am only starting to use Swift and SpriteKit.
UPDATE 2
I queried the physicsWord (as recommended) to get the right physicsBody and got the name of the attached node like this:
let body = self.physicsWorld.bodyAtPoint(location)
print(body?.node?.name)
But this is still printing the name of the node even if I touch outside the bounding box, which makes no sense to me.
Thank you anyway for your help.
The SKPhysicsBody doesn't define the bounds of the SKNode. You can do the hit check by querying the SKPhysicsWorld of your scene by calling bodyAtPoint on it. That will return the SKPhysicsBody you are interested in.
I was having the same problem. You actually can't perform the touch on the alpha mask of a Sprite Node and it says it right in the Apple documentation. You have to use a Composite Box. I used a shape Node and changed the "line width" to 0 so essentially the composite box is invisible. Make sure that the Z axis is higher for the composite box and then run the touch event through the composite box shape node instead of the original node.
I'm working on a sprite kit game and I'm trying to create a particular silhouette lighting effect whenever objects pass in front of a particular object (in this case a red sun). I want anything in front of it to appear black, and everything else to appear as normal (so if an object is partially in front, only that part should be black).
But I'm not sure how to do it in an efficient way. I've tried playing around with different SKBlendModes but so far haven't had much success. The major challenge seems to be achieving the effect whilst preserving the colour of the sun behind.
I'm not sure if it's possible to achieve this with the existing SKBlendModes, or if something else will be required.
I've attached a diagram to illustrate what I'm going for and an image of the current best fit.
You can create the silhouette effect with an SKCropNode, a mask node, and a background node. An SKCropNode selectively mask pixels of the sprite nodes in its node tree. Here, it will provide the silhouette effect by hiding/revealing portions of a black circle.
First, create the following objects:
A shape node (yellow circle) with its zPosition set to -1
A sprite node (black circle) with the same size as the yellow one
A crop node (SKCropNode) and a mask node (SKNode)
Next,
Add the yellow circle at the center of the scene
Add the black sprite as a child of the crop node
Assign the mask node to the maskNode property of the crop node
Add the crop node at the center of the scene
Since the mask node currently has no children, the black circle will be completely hidden and the entire yellow circle beneath it will be visible. As we add sprites to the mask node, the pixels of the black circle that intersect with the sprite will be unmasked (shown in black), producing the silhouette effect.
All that's left is to add a "presentation" node that will be displayed when the mask node's sprite is outside of the black circle. The presentation node will mirror the mask node's sprite's position and rotation. This should be done in didSimulatePhysics to ensure that the presentation and mask-node sprites are synchronized after the physics and actions have been updated.
But wait...if the presentation node moves over the yellow circle, won't it eclipse the Sun? Not if we set its presentation node's zPosition to -2.
The following shows an implementation of the above:
This problem was interesting to me, so I came up with a simple solution. It's not perfect nor does it scale very well, but the basics fulfill your need I believe and it may point others in the right direction.
I don't use any special SKBlendMode. Instead, I am using a duplicate object for the object which moves in front of the sun. This duplicate object is cropped using an SKCropNode with a duplicate of the sun as the maskNode. So, my node tree is as follows:
SKSpriteNode (sun) (the white sun)
SKSpriteNode (object1) (the rotating purple square with alpha 0.25)
SKCropNode
maskNode: SKSpriteNode (sunDuplicate = [sun copy])
SKSpriteNode (object1duplicate, same size as object1 but with [SKColor blackColor])
Inside the update method, align the duplicate with the original to ensure animation is properly forwarded.
- (void)update:(CFTimeInterval)currentTime {
self.object1duplicate.position = self.object1.position;
self.object1duplicate.zRotation = self.object1.zRotation;
}
As I said, this doesn't scale very well since you'll manually have to add duplicate objects and keep track of them for each object moving in front of the sun object. Perhaps SKShader can be of more elegant use.
I need to move the box2d body according to position received form game center server.
After receiving position I just update the body position using: -
Carbody->SetTransform(b2Vec2(serverposition.x,serverposition.y),0);
But its moving the body inapprotiate manner (for example. Body is showing somewere lese in the screen). At same time my sprite image not moving (attached with body).
What i did to solve the positioning problem is i taken a normal sprite image and just change position in update with that box2d body position.
Eg:-
your carbody movement based on server position. it will move invisibly.
your b2body without userdata(image)
carMainBody->SetTransform(b2Vec2(serverposition,carMainBody->GetPosition().y), 0.0f);
here your normal sprite image. just attch your sprite image like this
car->setPosition(ccp(carMainBody->GetPosition().x*PTM_RATIO,carMainBody->GetPosition().y*PTM_RATIO));
This method worked fine for me.