The game Supertype is incredible.
I was thinking about making an app similar to it.
Is there any easy way to turn the text of a SKLabelNode into a Physics Body?
for example, I want to have the letter 'A' become a literal Physics Body
- Is there any simplistic way to achieve this without having to actually define each cgPath?
- I guess I could make the 'A' a SKSpriteNode, but this seems poor.
Also,
I've had many problems turning SKSpriteNodes into Physics Bodies. I can easily turn a single image into a physicsBody, but if it's an image broken apart by invisible segments, things brake. Swift chooses a specific segment to become a physicsBody.
• I'm also so upset, since you can't define a concave shape and make a Physics Body. But you can have concave contiguous images become physics bodies nicely.
Last,,
It would be very nice to have a word turn into a Physics Body, and with a Boolean, define it to fall apart or stick together. Is there a way to do this?
(I'm thinking I can do it by clumping an array of them in the initialization: [SKPhysicsBody])
A SKLabelNode doesn't have a physics body, so you can not apply physics directly to it. What you could do is create them as a set of SKSpriteNodes and assign an image of each letter to the body texture.
To "turn the physics body on and off", you should toggle the node's property isDynamic. For other effects, you can play with affectedByGravity property and the collision and the contact bitMasks, depending on what you want.
To make the collision feel more real, you can use SKPhysicsContactDelegate, so you can automatically "draw" a physics body with the exact shape of the letters. Something like this:
letterNode.physicsBody = SKPhysicsBody(texture: letterTexture, alphaThreshold: 1.0, size: letterTexture.size())
To handle the collisions and contacts, don't forget to set the contactDelegate in your scene, like this:
self.physicsWorld.contactDelegate = self
Related
I've an explosion in my SKScene and I want this Explosion even effect another objects close to its , Object are in all sides .I want to give them force to run away with this explosion .
It sounds like you need an SKFieldNode implementing a vortexField():
https://developer.apple.com/reference/spritekit/skfieldnode#1654415
SKFieldNode:
A node that applies physics effects to a portion of the scene.
vortextField()
Creates a field node that applies a perpendicular force to physics bodies.
Is it possible to explain how bitmasking works for just this simplistic situation:
A big (blue) ball. Contact BitMask 0b0001
A medium (red) ball. Contact BitMask 0b0010
A small (white) ball. Contact BitMask 0b0100
They have no collisions between them, because somehow this is turned off between them. I assume by setting their collision masks to 00 all the way through the 32 bits... but let's leave that for another question, I haven't yet figured out how to turn these off.
Having set each ball to have a unique contact bit mask, what is done that gives contact information when they contact?
How is it possible to know which two balls have contacted each other?
Is it possible to have the contact information only received by the biggest ball in any given contact?
UPDATE:
I'm not necessarily after code. If you need code to explain what's what, how it works, and why whatever does what, go for it.
But what I'm really after is an understanding of how bitmasking works to provide logic that permits the determination of "who" was involved in any contact.
The reason I've given each ball size a different bitmask is that I thought this might help determine the bigger ball in any given contact between two balls. I could be wrong about this, though.
UPDATE 2:
Understanding of processes progressing:
As I understand it, these are the parts of the process:
Register SKView subclassed SKScene as conforming to the physics world contact notification delegate. Say it is so, too.
Set bitmask as categories for each type of bodily interaction type desire to be known about and/or controlled in the simulation
Use these bitmasks to articulate the nature of each object desired to be a part of contacts and/or collisions by applying them appropriately (some magic decision making in here).
Override the contacts callback with code that does stuff, in the same SKView subclass registered as the delegate
Create some magic code that determines who/what has contacted whom.
I understand some of these, but not the differentials of setting contact bitmasks versus the reasoning for the naming of category bitmasks, and not how to determine who has contacted whom.
In almost all physics engines, collision layers are represented by bit masks. All objects in the same collision layers will collide with each other. In the bit mask, each layer is represented by a bit. If the bit at position 0 is on, the object will collide with other objects which have the bit at the same position in their bit mask on.
While checking for collisions, the physics engine's broad-phase routine only reports those pairs as potentially colliding which have at least one common bit set to 1 in their collision bit mask. This check is simply done by ANDing (&) the two bit masks. The potentially colliding pair is reported to the narrow-phase routine only if the above check returns a non-zero result.
For example, if you wanted the blue ball to collide with both the red and white balls but wanted the red and white balls to not collide with each other, you'd set the bit masks to somewhat the following:
Blue -> 0b0011
Red -> 0b0001
White -> 0b0010
In your example, since none of the bodies have a common bit set in their collision bit mask, none of them collide with each other. In the above example, since the red and white balls don't have a common bit in their bit mask, they don't collide.
You might want to set all the collision bit masks to -1 (which turns all bits on) and remove bits/categories from the mask by XORing. The above example would then be implemented by the following pseudocode:
blueBody.collisionMask = -1;
whiteBody.collisionMask = -1;
redBody.collisionMask = -1;
redBodyCategory = 0b0001;
whiteBodyCategory = 0b0010;
whiteBody.collisionMask ^= redBodyCategory;
redBody.collisionMask ^= whiteBodyCategory;
I don't use SpriteKit, but from the little information I obtained from this SO answer, the contactTestBitmask sets the categories with which events will be raised on contact, while the collisionBitmask sets the categories with which the body will actually collide. So if you want contact information only from contacts which involve the Blue ball, you'd set the contactTestBitmask to the values as in my example above.
To check which balls are colliding with each other, you'd have to check the bit mask values and discern which one is which. In the above example, the Blue ball can be recognized by checking if body.contactTestBitmask == 0b0011, and so on for each other body.
As a side note, you might want to look into using a proper game engine like Unity that will make all this much easier.
First, you need to define what your sprites are, this is what the categoryBitMask is for. Think of this as a binary name for your sprite, with each digit being a unique name. Now it is possible to give your sprite more than 1 name, but for simplicity purposes, let's keep it to one.
contactBitMask tells the sprites what names it should be looking for.
So during the physics phase, the engine will take a given sprite, and look for all other physics sprites with the search name provided in the contactBitMask.
After this, evaluations are performed against the original sprite and the sprites in the filtered list.
On a contact, didBegin(contact:) is called, and contact contains all the information you need, including the 2 contact bodies. You then check the categoryBitMask to get the name of the sprites in question, and you do your conditioning based on these names.
What is an effective method to perform instantaneous hit detection in SpriteKit? Using SpriteKit's built in physics engine I want to collect affected objects during a single frame for situations such as an explosion's blast radius.
I have considered adding an SKNode with SKPhysicsBody to the explosive object and accessing its allContactedBodies property when it explodes but this would add unnecessary collision detection to other frames.
I have also considered adding an SKNode with SKPhysicsBody to the scene or altering an existing one at the time of explosion and using an action to remove or restore the node after a short duration but this feels unnecessarily complex and may delay the hit detection until the next frame.
I have wondered if there is a means to extend SKPhysicsWorld to allow for enumerating bodies with a circle in addition to a rectangle - or to extend SKPhysicsBody to allow manual collision detection with another test body.
However, I do not see how to access an SKPhysicsBody's shape data to do either of these.
If I were to tackle this problem I would do it by creating a node with a physics body and then messing with its dynamic, categoryBitMask, and collisionBitMask properties. I would set dynamic to false since theoretically the collision/explosion doesn't move because it hits other objects. I would set its categoryBitMask so that every object generated a "didBeginContact" report when colliding with it. And I would set its collisionBitMask so that it never caused impulses because of collision. This way the physicsBody is more of a probe then an actual physics object, just being what is their.
At the end of that the physics body should cause collision reports but not repel any objects. Obviously you can create this body and just not have it added to the scene until it is actually time to detect things. Then after that frame is over and you know all the physics bodies it touched you can remove it again.
Then I would set the scene as a physicsContactDelegate and impliment the did begin contact method.
class GameScene: Scene, SKPhysicsContactDelegate {
func didBeginContact(contact: SKPhysicsContact)
{
var AName:NSString = NSString(string: contact.bodyA.node!.name!)
var BName:NSString = NSString(string: contact.bodyB.node!.name!)
}
}
Then I would have if statements checking if either AName or BName were the name of your "probing" node/physicBody. Then after that you can add code to do whatever you want as a result of that collision.
Good luck! If you are having troubles with the bit mask properties I would strongly suggest checking out this.
I have a stack of blocks (think Angry Birds) and when a projectile hits them they fall over like you'd expect. However, this only works if I create the physicsBody like so:
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.size];
If, however, I create the physics body like this:
CGRect r = CGRectMake(-self.size.width/2, -self.size.height/2, self.size.width, self.size.height);
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:r];
Then the collision is there, but the blocks are not affected by it. The projectiles bounce off of it, but do not cause the blocks to move at all. My categoryBitMask and collisionBitMask are correct - they work with -bodyWithRectangleOfSize, but -bodyWithEdgeLoopFromRect does not.
Is this a SpriteKit bug, or am I missing something?
Thanks,
-Brian
Have a look at the SKPhysicsBody Class Reference.
You will find that the various class methods for creating physicsBodies are listed under two categories, namely Volume-based and Edge-based physics bodies.
bodyWithRectangleOfSize: returns a volume-based physicsBody whereas bodyWithEdgeLoopFromRect returns an edge-based physicsBody.
In the overview of the same document, the difference between the two is explained as:
Sprite Kit supports two kinds of physics bodies, volume-based bodies
and edge-based bodies. When you create a physics body, its kind, size,
and shape are determined by the constructor method you call. An
edge-based body does not have mass or volume, and is unaffected by
forces or impulses in the system. Edge-based bodies are used to
represent volume-less boundaries or hollow spaces in your physics
simulation. In contrast, volume-based bodies are used to represent
objects with mass and volume.
I have this situation: http://mokainteractive.com/example.png
I'd like to move the white ball inside the red track and detect wherever the balls touch the limit of the red track.
Which is the best solution? I have to create multiple transparent shape along the borders? Do you have other ideas?
thanks so much
In iOS8 you can create a single physics body for that kind of shape.
Make a texture of your shape with p.e. Adobe Illustrator and use this method:
init(texture texture: SKTexture!,alphaThreshold alphaThreshold: CFloat,size size: CGSize) -> SKPhysicsBody
The SKTexture is your shaped image. The body is defined by the colored pixels.
The alphaThresHold: The minimum alpha value for texels that should be part of the new physics body.
The Size is clear I think.
The texture is analyzed and all invisible pixels around the egg are ignored and only the color pixels are interpreted as the body of the SKPhysicsNode. You should use too many of these because they are very expensive to calculate for the Physics Engine.
Variations of this method are found in the SpriteKit Class Reference.
To your problem. Make an inverse texture of your area which should be transparent and pass it as texture to the physics body. It will be analyzed and a body around the free zone is created.
You cannot create a single physics body for that kind of shape.
Using bodyWithPolygonFromPath: will only allow you to create a convex polygonal path which obviously does not work for your shape.
I think you have 3 options here:
Use a number of bodyWithPolygonFromPath: bodies (probably the hardest to do and time consuming).
Use a number of various size bodyWithRectangleOfSize: bodies (not so hard but time consuming).
Use only straight lines in your image and use bodyWithRectangleOfSize: (the easiest and fastest). If you choose this option remember you are still free to rotate your straight lines to various angles.