I have this very odd problem with Box2D (under iOS). I have a body that is resting on the bottom of the screen. If I set the body from b2_dynamicBody to b2_staticBody using body->SetType(b2_staticBody), then later set it back to b2_dynamicBody, it falls through the bottom of the screen for a quick moment (several frames as I can see it moving down) before being pushed back up through the floor and coming to a rest correctly.
This behavior seems to only happen on the bottom of the screen. Doing the same thing with other bodies sitting on each other does not product this behavior.
I am defining the screen edges as follows (screenRect as already been adjust to world space):
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
b2Body* groundBody = globalWorld->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundBox;
groundBox.SetAsEdge(b2Vec2(screenRect.p1.x,screenRect.p1.y), b2Vec2(screenRect.p2.x, screenRect.p1.y));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(screenRect.p1.x,screenRect.p1.y), b2Vec2(screenRect.p1.x, screenRect.p2.y));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(screenRect.p1.x,screenRect.p2.y), b2Vec2(screenRect.p2.x, screenRect.p2.y));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(screenRect.p2.x,screenRect.p2.y), b2Vec2(screenRect.p2.x, screenRect.p1.y));
groundBody->CreateFixture(&boxShapeDef);
The oddest part of this is the more I switch the body from dynamic to static, the farther and farther it falls through the floor before being pushed back up.
I have not changing anything else in the body except from dynamic to static. If I move the body and drop it back onto the floor, the start switching it from dynamic to static, it resets how much it's drop into the floor, but it build up again the more I switch.
I can't figure out why is is falling through the floor like this unless I'm creating it incorrectly. Everything else in the game works perfectly.
I had this problem too. Here is my theory: when the object is static, it stops generating contacts with other static stuff like the ground. So, it seems that when set to dynamic again, it fails to update this contact checking.
My solution was this: since changing the position of an object correctly update these contacts, I just move the object to its current place. Unfortunately, it's detected as a zero change. So, I need to move it elsewhere, then move it again to its previous position.
b2Vec2 pos = body.getPosition();
float ang = body.getAngle();
b2Vec2 off_map(-100,-100);
body.setPositionAndAngle(off_map, 0);
body.setPositionAndAngle(pos, ang);
If you don't have an off-map area, you can try deactivating the object during the first move.
Related
I built a complete structure as a node (with its child nodes) and the user will walk through it using ARKit.
At some point, if the user cannot continue because of some real obstacle in the real world, I added a "pause" button which should freeze whatever the user currently sees in front of the camera, the user could then move freely to some other open space and when the user will release the pause button he/she will be able to resume where they left off (only someplace else in the real world).
A while ago I asked about it in the Apple Developer forum and an Apple Frameworks Engineer gave the following reply:
For "freezing" the scene, you could transform the anchor's position (in world coordinates) to camera coordinates, and then anchor your content to the camera. This will give you the effect that the scene is "frozen", i.e., does not move relative to the camera.
I'm currently not using an anchor because I don't necessarily need to find a flat surface. Rather, my node is placed at a certain position relative to where we start at (0,0,0).
My question is how do I exactly do what the Apple engineer told me to do?
I have the following code which I'm still stuck with. When I add the node to the camera (pointOfView, last line of the code below), it does freeze in place, but I can't get it to freeze in the same position and orientation as it was before it was frozen.
#IBAction func pauseButtonClicked(_ sender: UIButton) {
let currentPosition = sceneView.pointOfView?.position
let currentEulerAngles = sceneView.pointOfView?.eulerAngles
var internalNodeTraversal = lastNodeRootPosition - currentPosition! // for now, lastNodeRootPosition is (0,0,0)
internalNodeTraversal.y = lastNodeRootPosition.y + 20 // just so it’s positioned a little higher in front of the camera
myNode?.removeFromParentNode() // remove the node from the Real World view. Looks like this line has no effect and just adding the node as a child to the camera (pointOfView) is enough, but it feels more right to do this anyway.
myNode?.position = internalNodeTraversal // the whole node is moved respectively in the opposite direction from the root to where I’m standing to reposition the camera in my current position inside the node
// myNode?.eulerAngles = (currentEulerAngles! * -1) — this code put the whole node in weird positions so I removed it
myNode?.eulerAngles.y = currentEulerAngles!.y * -1 // opposite orientation of the node so the camera will be oriented in the same direction
myNode?.eulerAngles.x = 0.3 // just tilting it up a little bit to have a better view, more similar to the view as before it was locked to the camera
// I don’t think I need to change the eulerAngles.z
myNode!.convertPosition(internalNodeTraversal, to: sceneView.pointOfView) // I’m not sure I wrote this correctly. Also, this line doesn’t seem tp change anything
sceneView.pointOfView?.addChildNode(myNode!) // attaching the node to the camera so it will remain stuck while the user moves around until the button is released
}
So I first calculate where in the node I'm currently standing and then I change the position of the node in the opposite direction so that the camera will now be in that position. That seems to be correct.
Now I need to change the orientation of the node so that it will point in the right direction and here things get funky. I've been trying so many things for days now.
I use the eulerAngles for the orientation. If I set the whole vector multiplied by -1, it would show weird orientations. I ended up only using the eulerAngles.y which is the left/right orientation and I hardcoded the x orientation (up/down).
Ultimately what I have in the code above is the closest that I was able to get. If I'm pointing straight, the freeze will be correct. If I turn just a little bit, the freeze will be pretty close as well. Almost the same as what the user saw before the freeze. But the more I turn, the more the frozen image is off and more slanted. At some point (say I turn 50 or 60 degrees to the side) the whole node is off the camera and cannot be seen.
Somehow I have a feeling that there must be an easier and more correct way to achieve the above.
The Apple engineer wrote to "transform the anchor's position (in world coordinates) to camera coordinates". For that reason I added the "convertPosition" function in my code, but a) I'm not sure I used it correctly and b) it doesn't seem to change anything in my code if I have that line or not.
What am I doing wrong?
Any help would be very much appreciated.
Thanks!
I found the solution!
Actually, the problem I had was not even described as I didn't think it was relevant. I built the AR nodes 2 meters in front of the origin (-2 for the z-coordinate) while the center of my node was still at the origin. So when I changed the rotation or eulerAngles, it rotated around the origin so my nodes moved in a large curve and in fact also changed their position as a result.
The solution was to use a simdPivot. Instead of changing the position and rotation of the node itself, I created a translation matrix and a rotation matrix which was at the point of the camera (where the user is standing) and I then multiplied both matrices. Now when I added the node as a child of the camera (pointOfView) this would freeze the image and in effect show exactly what the user was seeing before it was frozen as the position is the same and the rotation is exactly around the user's standing position.
I have a ship that everything is centered around and everything moves relative to it. It is a first person shooter. Right now when I fire, and the ship speeds up, it catches up to the bullets. I would like the physics world to move relative to the ship's speed so that the bullet is essentially unaffected by ship speed.
The physics engine is doing the right thing, but not the right thing for my game.
I have other elements that move relative to the ship as it moves, which move correctly now, so don't want make ship stationary and move everything else in world around it. I don't see a direct way to do this maybe there is an indirect way? Perhaps I can manually take over the positioning of the bullets. I would like to use the other parts of the physics engine for doing collisions etc so don't want to completely manually do it, but will if that is the only option.
Anyone else have any suggestions?
It sounds like your bullets are receiving air friction. This is controlled by the physics bodies "damping" property. A value of 1.0 will make it static without movement. A value of 0 will allow it to move continuously without ever stoping. The default value is 0.1 as per the Apple documents. Assign your node like so to remove the damping(air friction)...
yourNode.physicsBody.damping = 0
I'm making a platformer using Actionscript 2. I got the jumping and gravity and everything going, but I'm limited to one "ground". As one might imagine, platformers require multiple "grounds" for jumping onto and falling off of. I tried editing the "ground" movie clip so that it was several blocks with nothing between them, but when I try this, my character will jump, land at the peak of its jump, and repeat the process until it lands on the top of the ground movie clip, then behave regularly, jumping and landing on top of the ground movieclip, even if there's no part of the ground movieclip to land on.
Here's my ground-gravity code.
if(this.hitTest(_root.ground))
{
this._y -= gravity;
gravity = 0;
jumping = false;
}
When you use hitTest between two MovieClips, it doesn't matter if there's nothing inside the movieclip, as long as the hittesting movieclip is INSIDE the bounding box (the blue outer rectangle of a movieclip when you select it) of the other movieclip.
To solve your problem, but still have many grounds in the same MovieClip, you have to use the second usage of hitTest, hitTest(x, y, shapeFlag) -- this will not check if two movieclips are hittesting each other, but rather if a MovieClip is touching a POINT (just an x and a y coordinate). But the real advantage of using this is the third parameter, shapeFlag, which is a Boolean value (either true or false) -- if it's false, then the hitTest will take the whole movieclip into account, meaning that even if there are empty spaces, those will be included in the hitTest, WHILE, if it's true, then only the actual shape of the MovieClip will be considered during the hitTest.
First of all, you have to get inside your Character's MovieClip and move him so that the registration point of the movieclip (you know that small plus sign), is at the BOTTOM of your character. Then, change your code to this:
if(_root.ground.hitTest(this._x, this._y, true))
{
this._y -= gravity;
gravity = 0;
jumping = false;
}
This will check if the SHAPE of the ground MovieClip (meaning only the platforms, NOT the empty spaces between them) are touching the registration point of your MovieClip, which is located at the bottom, at the feet, of your character. So, whenever the feet of your character are touching any of the platforms inside the ground movieclip, the code will be executed and your character wil stop.
Hope this helps :)
Here is the code for setting the characters physics body.
character.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:character.size];
It works fine, I mean it stays where I want it to but as you can see it displays the character's physics body in the bottom left of the screenshot (which is the grey box).
Is this a bug or can this be fixed?
I had a similar problem which may or may not solve yours.
It looks like you are using some sort of viewport system. Perhaps with a node called world and one called camera? If this is the case then you must be moving your world node every frame in order to center the content correctly? When drawing physics, you need to move the world node at -didEvaluateActions instead of -didSimulatePhysics
In my Corona SDK game I would like an item to drop from the sky and bounce up and down a few times before settling, at a randomly designated point on the screen. Say I'll drop an item at X=500 and Y=0. I then designate a drop-off point at Y=700, where the item will drop all the way til Y=700, bounce back up, then down, and after a few times (depending on bounciness), settle down and stay there.
This game is 2.5D, so having a static physics ground at the bottom would not work.
To do this, I came up with two options, neither which worked well:
Make a temporary invisible, 2x1 physics platform at the point where I would want the item to hit and bounce back up and down. This platform is created the moment I drop the item, and deleted when the item has settled down (fell asleep).
Inject force or change the linear velocity when the item passes a certain point.
However, because my gravity has been set to 40 (normal gravity of 9.8 was too floaty), the item will literally vibrate once it has stopped bouncing at the platform, and oscillate between velocities of 20 to -40 (varies) and not go to sleep.
The Injecting force method has also caused weird results, because the code checks the velocites per enterFrame event, so the results are not consistent.
I think the invisible bar is what makes the most sense. I would consider lowering the gravity back to something closer to normal and play with the bounce and density to get the bouncy that you want.