How to determine when bodies in display stop moving in lua - lua

I have some bodies moving in display using physics. I want to determine when bodies stop moving so as to call a function to take an action.
I tried a function like so:
function ball:stopMove ()
if condition then
print("Game Over!!!")
end
end
This do not get invoked. how can I do this correctly?

You can here to see how to implement your own callbacks. Basically you can create a proxy table that acts as a filter, screening for certain actions and acting on those.
If you don't want to do that, assuming you created a physics body, the function you are looking for is object:getLinearVelocity. If the object's x and y velocity are zero, the body has stopped moving. You would, of course, need to check for this every update.
Alternatively, you can calculate this yourself if you aren't using a physics body. All you need to do is keep track of the object's last x and y positions, and if the values are the same, the object has not moved since the lasted update.

I am not aware of any movement related events. So I guess you have to frequently poll the objects velocity for being zero.

Related

Drawing instances with WebGL2 - vertexAttribDivisor

I'm learning webgl2 from https://webgl2fundamentals.org. I'm learning about instancing right now. I can get the demo to work, where it draws many crosses, and I can get it to work with 500 instances.
But I cannot add anything else to the scene. I have a simple triangle that renders fine without the instancing, but with the crosses added the triangle disappears. I believe it has to do with gl.vertexAttribDivisor. I'm not sure when I need to call it, or if I need to undo it somehow.
If I omit calls to vertexAttribDivisor, the crosses don't render correctly, but the triangle is fine. If I replace the call to vertexAttribDivisor, the triangle disappears.
When do I call gl.vertexAttribDivisor? Do I have to undo the call to resume normal, non-instanced rendering? What does it really do?
The vertex attribute functions change a single global state. vertexAttribDivisor sets the divisor for a specified generic vertex attribute (one of the globally available ones), for every draw* call you want to setup the attributes using vertexAttribPointer and vertexAttribDivisor, if you changed the divisor for an attribute for one draw call but don't want to use the same divisor for your following draw call you need to reset it.

how to fix occasional stutter in my game?

The context:
In my SKScene I have:
1) a few sprites with no physics controlled by touch using touchesMoved: which instantly changes sprite position property based on touch location,
2) one sprite that while colliding with the others changes its physicsBody.velocity instantly.
That's all - no other fancy processing.
The issue:
I found occasional and random stuttering all of the sprites independently without any FPS dropping.
The questions:
In the context of my performance issue:
1) Is there any reason to update sprite position or velocity in update: method rather than update them instantly?
2) Is there any sense to use SKAction rather than changing directly position or velocity property?
3) If 2 then can make any difference running SKActions instantly or run them in update: method?
Apple says about
update:
method:
This is the primary place to implement your own in-game simulation, including input handling, artificial intelligence, game scripting, and other similar game logic. Often, you use this method to make changes to nodes or to run actions on nodes.
but nothing more like "must,..." or "should, because...".
4) Isn't SpriteKit done like all the changes made to the nodes instantly are processed in respective loop update phase or do I have always go to the appropriate loop method to make/fire changes there to avoid any rendering performance loss or interference?

Why are didBeginContact called multiple times?

In an iOS game that uses Sprite Kit along with the contact detection in Sprite Kit's build-in physics engine, I decrease the Hero's number lives by one each time he gets in contact with an enemy. This is done from the didBeginContact method.
However, it seems like that method is not just called once, when the contact begins, but called continuously as long as the Hero and the enemy overlaps: when I set a breakpoint in that method, I can see, that it is the exact same physics body instances that exist as contact.bodyA and contact.bodyB. The result is, that the Hero will lose multiple lives, even though he only passes one single enemy.
If the Hero meets the same enemy again later, he should get one more live subtracted, and therefore I cannot just maintain a seenEnemies hash set to deal with the problem above.
The question is now: how would you make sure that only one live is subtracted for each Hero/enemy contact?
The reason why the didBeginContact is being fired multiple times is because you have multiple contact points happening on concave shapes.
If you look at the picture below, you will see I have 2 sprites, a black star and a red rectangle. When the black star hits the red rectangle, it hits it on multiple points, circled in blue. Sprite Kit will then do a call for each line intersection, so that the developer can use the contactPoint variable for each of these contacts.
I had the same problem (score increasing multiple times for a single enemy destroyed and multiple life points being lost for a single instance of damage.) A user on the Apple forums thinks that it's a bug in [SKPhysicsBody bodyWithTexture:size:] but I don't believe that's the case, because it was happening with other constructors too.
First off, the categoryBitMask and contactTestBitMask are very important, obviously. Take a look at Apple's SpriteKit Physics Collisions sample code:
// Contacts are often a double dispatch problem; the effect you want is based on the type of both bodies in the contact. This sample this in a brute force way, by checking the types of each. A more complicated example might use methods on objects to perform the type checking.
// The contacts can appear in either order, and so normally you'd need to check
each against the other. In this example, the category types are well ordered, so
the code swaps the two bodies if they are out of order. This allows the code
to only test collisions once.
What I did to solve it was setting a flag after handling each condition. In my case, I was testing whether bodyA.node.parent was nil in didBeginContact, because I called removeFromParent() on the missile/enemy nodes to destroy them.
I think you should expect the event to fire multiple times and your code in there has to make sure it's processed only once.
I figured out easy solution:
Just change either body's categoryBitMask value to 0 or non-used value right after it detected contact.
For example:
if (firstBody.categoryBitMask == padCategory && secondBody.categoryBitMask == colorBallCategory) {
secondBody.categoryBitMask = 0;
// DO OTHER THING HERE
}
I came across the same issue. In my case the didBeginContact() was called many times (I counted up to 5 times) for one contact of a bullet with the enemy. As the bullet is a simple circle format, I agree with #SFX that it cannot be a bug just in Texture-Bodies. The tests have shown that there was no call to update() between the didBeginContact() calls. So the solution is simple (Swift):
var updatesCalled = 0
...
internal update() {
updatesCalled ++
}
...
internal func didBeginContact(contact: SKPhysicsContact) {
NSLog("didBeginContact: (\(contact.contactPoint.x), \(contact.contactPoint.y)), \(updatesCalled)")
if(updatesCalled == 0) {return} // No real change since last call
updatesCalled = 0
... your code here ...
}
I tried didEndContact() but that was not called at all. I didn't investigate further into this.
BTW: I just switched from Android, and I'm impressed by the easiness and stability of this System :-)
Here is an option that makes the player invulnerable after being hit for a set time:
A. Create a variable that makes the player invulnerable to losing a life after being hit for a few seconds.
Create a global Boolean variable called isInvuln (set to FALSE) and an NSTimeInterval called invulnTime.
In the method that handles the player and enemy making contact, check to see if isInvuln is False before taking a life. (if isInvuln is true ... do nothing)
If isInvuln is false, take a life then set isInvuln to true.
if(self.isInvuln == FALSE){
self.player.lives-=1;
self.isInvuln = True;}
Add to your updateWithCurrentTime:
if(self.isInvuln==True){
self.invulnTime += timeSinceLast;}
if (self.invulnTime > 3) {
self.isInvuln = FALSE:}
self.invulnTime= 0;
This will make it so that when an enemy and player collide, the player loses a life and becomes invulnerable 3 seconds. After that 3 seconds, the player can take damage again. If the enemy contacts the player within the 3 invulnerable seconds, the contact method does nothing. Hope this helps spark ideas to tackle your problem.
In my experience, didEndContact & didBeginContact are both called multiple times while the objects overlap. This is also happening in SceneKit using iOS 9, so I have to assume it's an intended behavior.

Box2D / cocos2d animation to a point with rotation

I'm pretty new to Box2D and cocos2d. I'm trying to do something which I thought would be pretty simple, but it is turning out to be more difficult than I had expected and I cannot find a working answer anywhere.
Basically, I want to move a b2body and rotate it to a certain point with animation.
I can get it to the correct position and rotation with:
targetBody->SetTransform(b2Vec2(10.0f,1.0f),10);
But I have no idea how to animate it there over time. I tried using cocos2d animation on the sprite used for the body, but that doesn't do anything. Any ideas?
There are a couple of ways you could do this.
You could use SetTransform every time step to update the position of the body gradually over time, in effect performing the animation yourself. The drawback with this method is that the body is 'teleporting' to the new position rather than moving, so it has no momentum, which means you can get odd results if it hits anything along the way. Still, if you know it will not hit anything or does not need to react to a collision this would be ok.
The other way is to SetLinearVelocity and SetAngularVelocity to give the body proper movement. This will keep the results of a collision realistic, and you don't need to keep updating anything every timestep. On the other hand, you will need to detect when the body has arrived at the desired position and then set the velocities back to zero, otherwise it will just keep moving. For dynamic bodies you will also need to counter gravity somehow, either by setting the gravity scale of the body to zero, or by applying an upwards force to balance gravity, or by changing the body type to kinematic during the move.
In general, you use Box2D to simulate the physical behavior of objects in relation to each other. The rules of mechanics implemented by Box2D dictate how your cocos2d CCSprites move if you continuously update the translation and rotation of your sprites according to their corresponding Box2d b2Body. You will have some kind of repeatedly invoked tick: method in which you step your Box2d world along in time, and in which you update your sprite positions according to simulation results of Box2d.
This pattern corresponds to b2Bodys of type b2_dynamicBody. Physical laws dictate the motion of the body in this case, and your sprites will follow these simulation results. This is why setting a conflicting position of a sprite by means of a CCAction or even directly will be undone almost instantaneously with the next tick:.
Solution 1: kinematic body type
However, there do exist other modes for a b2Body, and one of these is b2_kinematicBody in which the translation is no longer governed by the world but by the velocities or angular speeds you dictate through setters. So it would be one solution to work with body type b2_kinematicBody as in:
b2BodyDef bdef;
bdef.type = b2_kinematicBody;
With this you would manipulate the velocity and angular speed of a b2Body explicitly. In this case, Box2d is still responsible for moving bodies around, but according the velocities you dictate, and without any force effects of collision or gravity applied to this particular body. Also with this strategy, your CCSprites will follow b2Bodys. Setting conflicting positions for your sprites directly or by applying a CCAction would not make sense for the same reason as described above.
Solution 2: decouple sprites from Box2d
An alternative way to animating sprites would be to fully decouple those sprites from Box2d. In this case, you would simply not have any b2Body that governs the position of the sprite you are going to animate. Now, in this case, only you will dictate the position and rotation of your CCSprite, i.e. directly either through its position property or by applying a CCAction.

Move a body from VecA to VecB, instantly, but properly affect other bodies

I'm using the box2dflash library to create a game, and so far I've been using "SetPosition" to instantly move a body from one place to another... the problem is that it obviously skips affecting other bodies when I do this. I have the body set to bullet... now I just need to know how I calculate the force(?) to get the body to the exact coordinates that I need to move it to... preferably after only a single frame.
How would I go about doing this in box2d properly?
You could SetLinearVelocity to the difference between the current location and the destination, multiplied by your frames per second. That should get the body there in one frame, then you will need to stop it! SetLinearVelocity again to zero would work.

Resources