Does collision work during animation for SceneKit? - swift

I wanted to do a simple asteroids games where the asteroids go from far to bypass you (z>0) in SceneKit.
let moveAction = SCNAction.move(to: SCNVector3(0, -10, 10), duration: 2)
rockNode.runAction(moveAction)
Says I have a spaceship in Z axis 0, even though I can visually see the asteroids pass through the spaceship, the collision detection does not occurred. The collision only happened if the end point of the moveAction ends in Z axis 0 and in the same location as the spaceship.
Does detection only occurred after the moveAction ended (thus will not detect collision)? If yes, what solution do I have in detecting the collision during the asteroids movement?

did you set the isDynamic to true on both of your objects? and they both need to have different categoryBitmasks otherwise SceneKit will treat them as the same objects (can't comment don't have 50 rep yet) if not then do so collision should happen even when moving an object programmatically

Make the physics body as: kinematic. So it can detect collision even during SCNAction.
eg:
rockNode?.type = .kinematic
Or you can set it from Physics Inspector
Keep coding....... :)

Related

Swift SpriteKit: How to make a sprite gain slight velocity when it collides with an object?

Im creating a game that where you tap to start the player to make him jump, and then as he goes up, more and more objects generate for you to collect to gain points (think of doodle jump). I have it set up so this will happen, but instead of being given a boost by the object, he just floats up out of the scene. Id also like to know how to remove the object from the scene when the player touches it. Thanks in advance(:
Here is my code for making him gain velocity when he touches the object:
func bounceOff() {
player.physicsBody?.affectedByGravity = false
player.physicsBody?.applyImpulse(CGVectorMake(0, 10))
let advance = SKAction.moveByX(0, y: 10, duration: 5)
runAction(advance)
}
Your object goes off the screen because you cancel gravity. The impulse you apply pushes up, but there is no force pulling down. As to removing node from the scene. You can use node's removeFromParent method.

Collision without sprites colliding

I have some simple code that adds a block sprite at the leftmost part of a tile like this :
block.position = CGPointMake((-self.size.width * 0.5), 0);
[self addChild:block];
Since the anchor point is in the middle of the block sprite. self refers to the actual tile.
This works fine and indeed adds the block on the left side of the tile sprite.
Now I also have a player sprite that can collide with that block if it tries to go through it. That also works just fine.
The problem happened when i tried to get the block sprite to show in the exact same spot using another anchor point (i need a new anchor point for a shrink effect i wanted to create - which appears to work fine btw).
The new code becomes :
block.position = CGPointMake(-(self.size.width * 0.5), -(self.size.width * 0.5));
block.anchorPoint = CGPointZero;
[self addChild:block];
The new block appears in a similar to the first case position (though not totally identical).
I am not sure why the position is not identical but i can fix that by adding/subtracting 1 or 2 from the x,y points.
The weird problem is that if my player sprite now tries to go below that block on the tile below (which is an open tile without any blocks), i get a contact between the player and the block.
I have even added debug paths with SKShapeNode to make sure that the player and block sprites do not actually collide. And they don't ! But i still get a collision event.
The player scale is (0.8, 0.9), but i don't think this would play much of a role.
I really don't get why this could be happening. Any ideas guys ?
Changing the sprite's anchor point have no effect on the physics body.
When talking about CGRect, the rect origin is at point {0, 0},
So what is happening is that you now have a sprite that its image is centred around anchor point {0, 0} but with a physics body, that starts at {0, 0} and is the size of the sprite, meaning that it is centred around {0.5, 0.5}.
So even that the player doesn't collide with the image of the sprite, it does collide with its physics body.
What is happening is that you have a physics body, that before had the same centre point as the sprite,
But as oppose to before, where the sprite anchor point were in the middle, which would 'fit' into the physics body,
Now the sprite's anchor point is {0, 0}, which causes the physics body centre point, to actually be the most bottom left point of the sprite.
To resolve this, you need to offset your physics body, so it will be centred around the new anchor point.
For example:
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size center:CGPointZero];
CGPoint newCenter = CGPointMake(block.size.width, block.size.height);
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size centre:newCenter];
Good luck mate.
EDIT- On a second thought, I think I got confused with the offset directions.
An edit has been made to correct it.

Scenekit Physics - Prevent Rotation on Collision

In my project, I have a node that is moved forward (by applyForce) upon touches began. I would like the object to only move in one direction (z) and never rotate (x). However, when the object hits a body that is at an angle to it, it bounces back at an angle, as would be expected under normal physics.
Ideally, I want it to stop moving on collision and not rotate.
I have already set the physics body's restitution to 0 to prevent a bounce (but it still bounces), and its angular damping to 1.0 to prevent rotation (but it still rotates.) Any other ideas on how I can prevent rotation upon object collision?
cubeNode.physicsBody?.restitution = 0
cubeNode.physicsBody?.angularDamping = 1.0
Found the answer on another thread: set angularVelocityFactor to 0.
allowRotation in SceneKit?
Apologies for the duplicate question. I searched, but only found the other thread as a link from my own question's page.

Physics vs graphics fighting each other (box2d)

so I have a ball (sprite subclass) that can be dragged around the screen and updates it body to tell the world its position.
The problem is, when I apply a force to the ball while the ball is being touched (thus being controlled by a finger), I have two pieces of code fighting against each other to update the sprite's visual position.
The world stepper is trying to follow through the physics and update the ball's position. The touch methods however are also trying to update the ball's body and graphic position. Ideally, when touched I would like to kill off any physics affecting the ball.
So what exactly should I be trying to do to consolidate this? This is also creating issues for collisions and filtering. Any help appreciated. Thanks
Do you want the ball to have an accurate physics simulation? If not, you could always use the SetTransform method of the b2body class like this.
CGPoint ballLocation = ;//use the touched location for this
b2Vec2 vecBallLocation = b2Vec2(ballLocation.x / 32, ballLocation.y / 32);//calculate this on your own
b2Body * ballBody = ;//replace this variable with your ball's b2Body;
ballBody->SetTransform(vecBallLocation, ballBody->GetAngle());
Do not set the ball sprite's position manually. Leave this up to the physics simulation. Your code will get really messy over time if you have to keep track of what sprites you set the position of manually and which ones use the physics simulation to update their positions. This way is also much easier.
When the physics object is being dragged, set its velocity and angular velocity to 0,0 before running the physics step simulation. You may also want to temporarily get the physics object's position, then step, then set the body's position back, then apply whatever touch dragging offset you got from moving the finger to the body.

stick a sprite to another when it collide with it

so I have a sprite that is created every second and that is moving at a random position (sprite1) and another sprite that has a fixed position (sprite2). I would like that when sprite1 collide with sprite2, sprite1 is like sticked to it (it stops moving and is sticked to it) . How can I do this please ? sorry for my english I'm french :/
p.s : sprite2 is rotating with accelerometer, so if sprite1 collide with it I would like that it rotate too :)
I think, you can try to use box2d to do this. It will help to detect collisions and to manage rotations, movement, etc.
I think, you can do it simply in Cocos2d.
1) First set the rect for sprite1 and sprite2 using CGRectMake(x,y,width,height)
2) As you told sprite1 is moving at random position and sprite2 is fixed to particular position, you can check them collide by using CGRectIntersectsRect([sprite1 bounds],[sprite2 bounds]).
3) if it intersects, set sprite1.position = sprite2.position
Note: you said sprite1 is rotating, rect can be fit only to the regular bodies. if you want exact collision or physical properties for sprite better you can go for box2d.
If you don't want to use Box2d (which can handle circle collisions), you can try something like this:
1.) Detect collision, is the distance between the two circles center point (x,y), less than the sum of the two circles radius.
2.) Make the Sprite1 stick to Sprite2, Stop the movement of Sprite1, and save the relative delta (x,y) to Sprite2, then whenever Sprite2 moves or rotates apply the same delta movement and rotation to Sprite1.