Creating a sprite during didBeginContact - sprite-kit

I've been working on some SpriteKit tutorials. I understand the whole collision thing and have verified with NSLog that a collision is being registered between my two objects. However for some really strange reason my sprite is not being created (or rather shown) when it's done during didBeginContact.
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (CNPhysicsCategoryPlayer | CNPhysicsCategoryRock))
{
NSLog(#"ouch");
SKSpriteNode *bigOuch = [SKSpriteNode spriteNodeWithImageNamed:#"star"];
bigOuch.position = CGPointMake(200, 200);
[self addChild:bigOuch];
}
}
I get the ouch log message but no sprite appears.
I have tried the same (sprite creation) code in other parts of my program and have no issues. What am I doing wrong?

I was stuck on the exact same issue a while back. You can create a SKSpriteNode and add it to the view but it does not get displayed. The short of it is that I ended up creating an array and adding any sprites I needed to create during the didBeginContact phase. During the update phase I checked the array and added them to my view. Just remember to empty the array after you are done. Otherwise you will end up with the same sprite being added over and over again.

Related

How to check for gameObject while Grid Snaping in Unity2D

I am trying to make a game which allows moving objects by snapping them on the grid, I already figured out to snape them to grid but there is one thing little problem, I want to check if there is already a game object placed on that same grid so that I won't let the dragging game object snap to that same spot but the thing is that I have a different game object shapes.
see for yourself
Click to see the image
how can I achieve that?
Since you're on a square grid I think the best way to do this is with Physics2D.Boxcast(). Basically what you're doing is casting a box at the snap vector before moving the game object.
So in your code before you move the game object to the snap location:
RaycastHit2D hit = Physics2D.BoxCast(snapTo, boxSize, 0.0f, Vector2.zero);
if (hit == null)
{
// We're clear to move
}
else
{
// Something is in the way
}
Where snapTo is the Vector2 of the location you're going to snap to and boxSize is a Vector2 equal to the size of one grid position (you might need to play around with this a bit). The last two arguments, 0.0f refers to the angle of the box, which we don't need so just set it to zero and Vector2.zero is the direction of the cast, but we're casting in one spot so this also doesn't matter.
I'm assuming that only one game object can occupy the space at once, so there will only ever be one hit. If there's a chance for more than one you can change it to RaycastHit2D[] hits and Physics2D.BoxCastAll then check if hits.Length is greater than 0.
I had some troubles with Physics2D.Boxcast() , so instead i used Physics2D.OverlapBox() and it is working just fine.
isColl = Physics2D.OverlapBox(ObjectToMove.position, size, 0f, layerM);
if (isColl == true)
{
// Something is in the way
}
else
{
//Clear to go
}

SKSpriteNode with physicsBody auto correct orientation

What would be the best way to make a Swift SKSpriteNode auto correct its orientation after it has had a couple of physicsBody knocks and is now not in the default orientation?
For example I have have a 2D stick-man who gets knocked to the side by another object and would like the stick-man to tilt and reorient itself to the default standing position.
The way I have done this in the past is to wait until the physics body comes to rest, turn off the physics engine for the stickman, reorient the stickman, turn the physics engine back on again.
Write yourself an action called standupAction which animates the stickman's reorientation, maybe just a rotate or a jump up. Then do something like the following.
Sorry this Objective-C not Swift, don't know swift, but should be easy to translate.
if (stickman.physicsBody.resting) {
stickman.physicsBody.dynamic = NO;
[stickman runAction:[SKAction sequence:#[
standupAction,
[SKAction runBlock:^{ stickman.physicsBody.dynamic = YES;}]
]]];
}
The only downside of this approach is that sometimes it can take a full second until the stickman comes comes to rest. Box2d takes quite a long time to settle down. But it looks very realistic if you wait.
Alternatively, you could just check the orientation of stickman and if he is >45degrees off balance then reorient him with impulses. I find impulses to be very difficult to know how much force to apply when you need precise movement like this.
Just to update, I couldn't afford to set the physicsBody to not be dynamic.
My scene updates each node, similarly to Apple's Adventure game, as such I implemented the rotation in the subclassed SKSpriteNode's update method as such:
if (isTouchingGround) {
if self.zRotation != 0 && !rotating {
let actions = [
SKAction.runBlock {
self.rotating = true
},
SKAction.rotateToAngle(0, duration: 1.0),
SKAction.runBlock {
self.rotating = false
}]
runAction(SKAction.sequence(actions))
}
}

Why are only some nodes removed from parent in Sprite Kit?

So I am using the didBeginContact method to detect the collision between the physics bodies of a bullet and other objects in my scene using the block of code below:
-(void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (WWPhysicsCategoryOther | WWPhysicsCategoryBullet)) {
[_bullet removeFromParent]
}
}
When one bullet is on the screen, the bullet is removed. However, like many shooting games, the player is allowed to fire bullets repetitively. I find that when more than one bullet is on screen, not all of them are removed after contact. How can I ensure that every bullet is immediately removed right after a collision?
0x141E and ZeMoon comments are correct.
_bullet is probably a pointer to a specific node, therefore, on collision detection, the bullet node that collides is probably not always the one that has that pointer to (which means that could be that when collision happens, some other bullet on screen is being removed).
A better and more 'correct' way of doing that is, on didBeginContact: identify which contact body is the bullet, and using its node property, remove it from its parent.
Something along the following example should work-
-(void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (WWPhysicsCategoryOther | WWPhysicsCategoryBullet)) {
SKNode *bulletNode = (contact.bodyA.categoryBitMask == WWPhysicsCategoryBullt) ? contact.bodyA.node : contact.bodyB.node;
[bulletNode removeFromParent]
}
}

How to set up SceneKit collision detection

Hello I have pored over the documentation and can not figure out how to set up collision detection in scene kit. Can some one please show an example.
Please help I am very desperate to figure this out.
Thank you!
Edit:
Hello Thank you very much, I'm sorry I forgot to mention my project is in swift. No big deal I can translate my self for the most part.
I have the BitMasks working correctly as the objects collide and bounce with each other. However I can not seem to get the function to work
func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact){
let contactMask = contact.nodeA.physicsBody!.categoryBitMask | contact.nodeB.physicsBody!.categoryBitMask
if (contactMask == (CollisionBallCategory | CollisionTerminatorCategory)) {
println("Collided")
}
}
Looking at the documentation it appears i need to assign the scenes physics world delegate to this method somehow. I am not sure how to do that.
The main things to get about collision detection in SceneKit:
it's based on bit masks, which together form a table.
a contact delegate is how you respond to collisions.
Making objects collide
For example, you might state a bit of game design in plain English like this:
Asteroids hit each other (and make smaller asteroids). Missiles should pass through each other, but destroy rockets and asteroids. Rockets shouldn't do anything to missiles (only the other way around), but if one gets too close to another or to an asteroid you are having a bad problem and you will not go to space today.
The first step to realizing that with collision detection is to codify that design in terms of which pairs interact. You can do this with a table:
| Missile | Rocket | Asteroid
--------------------------------------
Missile | No | Yes | Yes
Rocket | No | Yes | Yes
Asteroid | No | No | Yes
Then you can turn the headers of the table into a set of category constants for use in your code.
typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
CollisionCategoryMissile = 1 << 0,
CollisionCategoryRocket = 1 << 1,
CollisionCategoryAsteroid = 1 << 2,
};
missile.physicsBody.categoryBitMask = CollisionCategoryMissile;
rocket.physicsBody.categoryBitMask = CollisionCategoryRocket;
asteroid.physicsBody.categoryBitMask = CollisionCategoryAsteroid;
Use bitwise OR on these constants to create collisionBitMask values that fill in the table.
missile.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
rocket.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
asteroid.physicsBody.collisionBitMask = CollisionCategoryAsteroid;
That's all you need to make SceneKit resolve collisions for you (that is, bounce objects off each other).
Responding to collisions
If you also want to be notified of collisions (so you can make missiles blow stuff up, and running your ship into an asteroid end the game), you'll need to set a contact delegate on your scene's physics world and implement one or more of the contact delegate methods that get called when a contact happens.
In your contact delegate method (say, physicsWorld:didBeginContact:), you'll need to find out which categories of bodies were involved in the contact, and which was which, so you can get to your code that does whatever your game does for the collision:
- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact
{
CollisionCategory contactMask =
contact.nodeA.physicsBody.categoryBitMask | contact.nodeB.physicsBody.categoryBitMask;
// first, sort out what kind of collision
if (contactMask == (CollisionCategoryMissile | CollisionCategoryRocket)) {
// next, sort out which body is the missile and which is the rocket
// and do something about it
if (contact.nodeA.physicsBody.categoryBitMask == CollisionCategoryMissile) {
[self hitRocket:contact.nodeB withMissile:contact.nodeA];
} else {
[self hitRocket:contact.nodeA withMissile:contact.nodeB];
}
} else if (contactMask == (CollisionCategoryMissile | CollisionCategoryAsteroid)) {
// ... and so on ...
}
}
Put this code in one of your classes (a view controller, maybe — wherever you keep your game logic is good), and make that class declare conformance to the SCNPhysicsContactDelegate protocol.
#interface ViewController: UIViewController <SCNPhysicsContactDelegate>
Then assign that object to your scene's physics world as the contact delegate:
// in initial setup, where presumably you already have a reference to your scene
scene.physicsWorld.contactDelegate = self
Learning more
There's a little bit about collision resolution in the SCNPhysicsBody reference documentation. And Apple has some sample code that uses collision detection — it's part of the smorgasbord of demos in the WWDC slides and demo sample apps, and in the vehicle physics demo, too.
Beyond that, SceneKit's collision handling model is almost exactly the same as SpriteKit's, so almost everything in the SpriteKit programming guide is also useful for understanding the same stuff in SceneKit.

SpriteKit - How do I check if a certain set of coordinates are inside an SKShapeNode?

In my game, I'm trying to determine what points to dole out depending on where an arrow hits a target. I've got the physics and collisions worked out and I've decided to draw several nested circular SKShapeNodes to represent the different rings of the target.
I'm just having issues working out the logic involved in checking if the contact point coordinates are in one of the circle nodes...
Is it even possible?
The easiest solution specific to Sprite Kit is to use the SKPhysicsWorld method bodyAtPoint:, assuming all of the SKShapeNode also have an appropriate SKPhysicsBody.
For example:
SKPhysicsBody* body = [self.scene.physicsWorld bodyAtPoint:CGPointMake(100, 200)];
if (body != nil)
{
// your cat content here ...
}
If there could be overlapping bodies at the same point you can enumerate them with enumerateBodiesAtPoint:usingBlock:
You can also compare the SKShapeNode's path with your CGPoint.
SKShapeNode node; // let there be your node
CGPoint point; // let there be your point
if (CGPathContainsPoint(node.path, NULL, point, NO)) {
// yepp, that point is inside of that shape
}