How to track multiple collisions between 2 sprites? - sprite-kit

Here's an example, just for ease of understanding:
Sprite A is a ball. Sprite B is a cube. When the ball touches the cube once, I want the label to say first contact. When the same ball touches the same cube again, I want the label to say second contact. When the same ball , touches the same cube again, I want the label to say third contact.
How do I accomplish this?
It seems Sprite kit only allows 1 hit collisions between sprites to be programmed, which is enormously limited, in my opinion. Especially, since I want to create an enemy that actually changes behaviour dependant on the amount of hits it receives from the player, not just the same action for every collision.

Figured out a way. If you assign sprite A with points and use a cumulative score to keep track of the points you can then then use "score" as a collision counter. So each time sprite A touched Sprite B the score would increment by 10 points, simply then saying if score == 100 for example ... program something or if score == 150 ... program something (did begin method) and it worked, allowing you to program different actions or whatever at each point of collision with the same sprites! Awesome. Didn't think it would work but it did :)

Related

Spritekit contact detection crash(EXC_breakpoint)

I set up a game where the player controlls a ship and shoots the incomming enemies. When One Bullet and ONE enemy make contact, there is no crash but when two bullets hit 2 different enemis i got a crash in the following func.(EXC_Breakpoint) (all bullets has the same physicCategory and all enemy has the same physicsCategory.
How can I solve this?
Thanks!
if body1.categoryBitMask==PhysicsCategories.Bullet && body2.categoryBitMask==PhysicsCategories.Enemy && (body2.node?.position.x)!<self.size.width{
All Sprite-Kit collisions are between 2 bodies - you can’t have 2 bullets hit 2 enemies. If it looks as though 1 bullet has hit 2 enemies at the same time, what you will actually get is a call to didBegin() for the bullet and one enemy and another call for the bullet and the other enemy. However, if you do removeFromParent() for the bullet for the first collision, then you may have problems for the second collision as the bullet node will be nil, although the bullet’s physics body will still be there.
Search on SO for “Sprite Kit multiple collisions” as this is a common problem and there are several ways to handle it. The easiest way to describe is instead of doing removeFromParent for nodes that should be “destroyed”, add them to an array (or more properly, a set). Then in didFinishUpdate, iterate over this set and remove all the nodes that are in it.

SKPhysics in Swift - Lowering Speed Property Jittery

Usually in 2D physics engines like JBox2D, if the user wanted to make a simulation run in "slow motion", you would just decrease the value by which the simulated world iterates by, for example normal movement at 60fps, the step would be 1/60 if the physics world is stepped forward every frame.
But for the SKPhysics class in the sprite kit in xcode 6 using swift, I only see the property called ".speed" which when I decreased, only led to a jittery mess, that updated the physics bodies once every 10 frames.
Is there a specific property, or trick maybe to get the SKPhysics world to iterate forward in time by smaller increments without gross glitchy movements?
The only way to slow down the simulation in sprite kit is to use the physicsWorld.speed element.
But if you are trying to change only one or two sprite speeds, try the velocity element of the sprite:
node.physicsBody.velocity = x
you can directly change the velocity(speed) of your node or sprite through its physicsBody.
Hope it helps :)

How to measure the force by which Two rigid Bodies collide?

How to measure the force by which Two rigid Bodies collide and in the reaction add force to other object in opposite direction. For example in the cricket game how the force is measured b/w bat and ball . If player blocks it add a min force to the ball and if he plays the shot he ball goes too far for a four or a six. I will say that just simple addforce() component will not work. It will just apply the force every time when it hits the bat doesn't matter it is blocked or a shot played.

SKPhysicsContact when object collides with more than 1 object, handle first, ignore all others.. how?

Okay I have some physics objects, and they are all nicely categorized, and my didBeginContact is properly fired, and does what it is supposed to do. The problem is this:
I have two categories of objects, say ball and paddle.... When the ball touches a paddle the ball should explode... simple enough.. The problem lies in that the ball could touch 2 paddles at the same time... So, more than one didBeginContact gets called, and as such more than 1 explosion happens (1 per paddle the ball contacted with).. So the problem I am trying to figure out is, how do I remove/ignore all subsequent contacts with paddles from being handled if the code has already handled a collision involving the original ball? Removing the SKSpriteNode from parent before starting the explosion does not nullify the other contacts, they still get handled... so how do I tell it.. HEY PHYSICS CONTACTS STUFF... that body is no longer in the picture... so just throw those contacts away and don't worry about them?
I suppose I could explicitly check that the parent still has the SKSpriteNode available in the contact code before doing the explosion etc, but that seems kludgy at best, though I suppose it would work... Is there another/better way to handle this? I have to believe there is.
The moment you get the contact, set the contactBitMask of the ball node's physicsBody as 0. I am assuming the node needs to be destroyed and does not need to be reused.
This should prevent multiple contacts from appearing for the same node.
If the above doesn't work, you can try the following methods:
Removing the node from parent within the contact delegate, and triggering the explosion animation subsequently.
Subclass SKSpriteNode or SKPhysicsBody for the ball nodes and add a property for eg. alreadyTouched. Then you can check and set the property from within the contact delegate.
If you have three physicsBodies (ball, paddle1 and paddle2) and ball is set to collide with paddles (but paddles do not collide with each other) and the ball collides with 2 paddles during the same update cycle, then the game engine will generate 2 separate SKPhysicsContact objects - ball & paddle1 and ball & paddle2.
didBegincontact (Swift2) or didBegin(contact:) (Swift 3) (dBC for brevity) will then be called twice during the same update() cycle i.e. there will be 2 calls to dBC between calls to update()- firstly for the SKPhysicsContact between ball & paddle1 and then for the contact between ball & paddle2. You can do ball.removeFromParent() during the first contact, and the ball will be removed from the node tree but this will not prevent the second call to dBC for the ball & paddle2 collision and you will likely perform the same actions against ball (exploding, removing the score etc).
The simplest thing to do is to create a subclass of SKSPriteNode for your ball (ballNode?) and add a single property isActive, initialised to true. This is very easy.
In dBC, when the ball hits the paddle, check its isActive property and if false, simply return. If it's true, perform the normal collision actions and then set ball.isActive to false. When dBC is called the second time, the check against isActive will prevent any duplicate actions.
You could also use the ball's userData (part of SKSpriteNode) to store the isActive values to prevent subclassing, if you'd prefer that.
There are other ways to handle this issue, but so far I've found this one to work and to be the simplest.

How to detect collision between three objects simultaneously in Box2D?

I am new to Objective-C. I am currently working on a game using Cocos2D and Box2D. My problem is that when 3 objects collide together, the game crashes. Now let me describe my game in details:
In my game I have a main character standing on top of a building. Below the building there's this the road. Enemies pass by the road at various random speeds entering the screen from right and exiting from the left. I have created the enemies as b2_kinematicBodies and set a random velocity for each of them using SetLinearVelocity(). The main character shoots the enemies. The projectile (the object being shot) is a b2_dynamicBody. When the projectile hits the enemies, both the projectile and the enemy are destroyed. During gameplay sometimes an enemy moving at a slow speed is crossed by one which is moving at a higher speed. If a projectile hits the two enemies just at the point when they are overlapping and one is about to pass the other one, the game crashes! Please help me with this.
I have detected collision using b2contactListener class.
One thing I didn't mention before is that I am not creating the enemies as individual distinct bodies. Instead, I am creating it once and making it move and I am calling this method (which creates the enemies and makes them move) inside init as below:
[self schedule:#selector(addRightTarget) interval:2.0];
I believe the issue is that the collisions are calculated before your handler gets any calls. Meaning that when your handler gets called, the bullet has hit 2 objects. So you get 2 call-backs as shown below.
Collision Detected: Bullet + Enemy1
Destroy Enemy1
Destroy Bullet
Collision Detected: Bullet + Enemy2
Destroy Enemy2
Destroy Bullet [CRAAAASH!!! You just tried to delete a non-existent object]
1st: You should not be removing anything except in your step function (as someone mentioned in another answer)
2nd: Pick one of these:
Make your list/array of objects-to-delete be a 'set' or implemented in such a way that duplicates are avoided.
Check for existence of your object in the world
The collision only happens between 2 objects in Box2D. So in your mentioned scenario your will get multiple collision events which could be,
Enemy-1 and Enemy-2
Enemy-1 and Bullet
Enemy-2 and Bullet
So one possible reason of crash could be that you are not expecting (Enemy-1 and Enemy-2) collision and you are handling it like you have collision between (Enemy-1 and Bullet) so you might be casting it into wrong class. Make sure you are checking the kind of class "isKindOf" before casting it.
Also you may want to use Contact Filtering and or assign category masks to your enemies so that they don't collide with each other and only collide with bullet.
But it will be more help full if you tell something about how and where you destroy your bodies (I hope its not inside your Collision Detection Functions) and also if you can share the exception text when your application crash, that will be helpful.
I used a rather cheap workaround. I alternately created enemy fixtures of different sizes(differing by few pixels). So now if i shoot them even when they overlap, the app doesn't crash(because only the bigger object collides and gets destroyed). This serves my purpose. Thanx a llot for your help. I really appreciate it! :)