I am developing a 2D, underwater, action-RPG for Android, using Box2D as the physics engine, mainly for collision detection, collision response and movement of in-game characters within an environment comprised of walls, rocks, and other creatures.
I have tried two different approaches for implementing character animations using Box2D, and have found issues with both. As I'm new to Box2D and physics engines, I would appreciate a recommendation on how these things should best be done.
An example of an animation I am trying to do is as follows:
A fish wants to attack another fish, so does the following:
1) Move towards target at speed
2) Take a bite out of target creature
3) Turn and flee, back to where the attack began
4) Turn back to face the target, ready for another attack
The two approaches I've tried are:
A) Apply a force to the attacker (using body.applyForce() ) to move it towards the target, then another force to move it back again, after the collision
Problems:
* Frequently the attacker hits the target and bounces off and goes hurtling back at great speed, and bounces off walls, everywhere. The speed is pretty random, depending on where it impacts the target, the mass of the target, etc. It breaks the animation and looks terrible.
* It's very hard to figure out what forces should be applied to the attacker and when, to simulate a particular animation in a physics world so it looks realistic
B) Directly set the position of the attacker (using body.setTransform() ) to move the attacker to the correct position, as it moves forwards each step, then moves back again.
Problems:
* Directly setting the position allows the attacker to ignore collisions with walls and other creatures, so getting stuck in a wall is common
* If the player is attacking, I update the world origin as the player moves, to keep the player mid-screen. This works well, except when I start an animation, as I don't want the screen to follow the animation, but only the movement component of the existing velocity, which I don't know, as I'm overriding the Box2D forces/velocities when I set the position. It's possible to do this I'm sure, but difficult - maybe I'm missing something obvious.
Should I be monitoring the collisions? Overriding the collision response?? Something else?
So, how would you recommend I approach this problem?
I'm only used to work with Farseer, but Farseer is a pretty direct port from Box2D, so I hope this answer is still helpful.
Next to applying force and teleporting you can also set the linear movement speed of a body. This way you can have the fish move towards the player without applying force. You should capture the collision events from the fish body and compare in each event if the fish has hit the player, then set false/NoCollision in the collision event with the player so that it doesn't bounce of. Now set the fish body to ignore any collisions with the player body and use a fixed joint to stick the fish to the player. You can now play your bite animation.
After the bite animation you want to disengage the fish. Start your flee animation, remove the joint and teleport the fish to the edge of the player body (so that it's not colliding with it). After that re-enable collisions between the fish and the player body and send the fish away from the player (either by setting linear movement speed again, or for a nice bounce effect via force.
Related
I'm using the Corona SDK with the Box2D engine, and I'm trying to make a Flappy Bird style game just to get familiar with the physics engine. I've tried increasing the density of the main character, increasing gravity, changing the scale of the physics stage, etc, but the main character still feels too "floaty".
Increasing the gravity came as close as I could to feel right, but there are still issues. If the user taps the screen quickly in succession, the momentum builds up quickly and the character goes flying up off the screen at high speed. Here is my code right now:
physics.setGravity( 0, 60 ) --default is 9.8
function screenTap()
flappy.isFixedRotation = true
flappy:applyLinearImpulse( 0, -300, flappy.x - 3, flappy.y )
flappy.isFixedRotation = false
end
In the original Flappy Bird game, it seems to have normal gravity, but rapid taps to the screen wouldn't make the bird fly up too quickly. It almost had the feel of something "heavy" like a bowling ball, but obviously in this world objects of all masses fall at the same speed. I don't have much experience with physics engines, so I would appreciate any suggestions.
If you have played flappy bird recently, you should have observed that when you tap the bird in rapid succession, its vertical velocity does not increase! The flappy bird developer seems to have made the bird's vertical velocity set to a certain value whenever it is tapped rather then have it accelerate vertically.
So, my advice would be to simply set the character's vertical velocity to a set value whenever the screen is tapped instead of accelerating it.
So I am coing an android game and have managed to make a ball roll over the screen in the direction you tilt your phone. However I would like to make the ball roll faster the more you tilt your screen.
But what is the best way to implement this? Taking bigger steps is obv not good, it makes collisions hard to calculate. I want to move more steps per second instead.
So lets say you have a tiled board and you implement speed as tiles/millisecond. But that is problematic also speed will not be continous. You'd perhaps move 1 step every 10th time in a loop instead of every time in the loop. So you would move, then be still, then move, etc instead of continously moving. But maybe that is as good as it gets?
So this problem applies generally for any kind if computer graphics I guess. How do you implement this the best way? I'm specifically interested in what applies to Android.
The natural way of implementing speed and position problems is to have position calculated with the speed that way :
position = speed * dt
with dt constant, adapted for your implementation.
So basically the natural way is to increase the step. You say it's obviously bad for collision detection but with a limited speed and a small dt I don't really see why.
I'm looking to implement movement from character to character on a tiled board. I have a 7x7 board set up with each tile representing a character. The player is able to move in up to the 8 directions around the tile (providing proper game logic). I am able to accurately get the character at a given tile based on a onTouch() Action_Down.
For a more elegant solution though I am looking to press and drag to move between tiles/create words. I'm not exactly sure where I should start with this.
I can figure out all the logic for appropriate moves etc. But my question is how to recognize a left movement from 1 position to another as selecting tiles?
My current idea is to have hard boarders but that will not work for diagonal. Then my next idea is to have diagonal boarders instead so like:
This solution seems a little complex though. Is there any easier way to accomplish this?
I have a Fast Moving Body(A) which is dynamic. It is supposed to collide with another Body(B). A collides with B, but sometimes it passes the Body B without collision. This is totally random behavior. I must have that collision. Kindly guide why it is acting like this, randomly.
The effect of one object passing through another due to large movement in a single timestep is called tunneling.
Box2D uses Continuous Collision Detection between dynamic and static objects to solve this problem. However, your case (dynamic v.s. dynamic) isn't automatically handled, so it's just a random dice throw whether your objects happen to be in colliding positions at the exact moment the collisions are evaluated.
From the Box2d Manual:
Normally CCD is not used between dynamic bodies. This is done to keep
performance reasonable. In some game scenarios you need dynamic bodies
to use CCD. For example, you may want to shoot a high speed bullet at
a stack of dynamic bricks. Without CCD, the bullet might tunnel
through the bricks.
Fast moving objects in Box2D can be labeled as bullets. Bullets will
perform CCD with both static and dynamic bodies. You should decide
what bodies should be bullets based on your game design. If you decide
a body should be treated as a bullet, use the following setting.
bodyDef.bullet = true;
The bullet flag only affects dynamic bodies.
Box2D performs continuous collision sequentially, so bullets may miss
fast moving bodies.
I'm developing an Android application with OpenGL and JNI (all OpenGL stuff is in C code).
Imagine I've drawn a cube. I want that user can push his finger over the cube and can rotate the cube and move it around the screen.
Is there any way to do that?
How can assign an event listener to touch and move events only when the user touch the cube?
UPDATE I want something like this:
Rotate cube with fingers
Thanks.
This is called "picking" in 3d-ville... There are a number of tutorials on the subject floating hither and yon. There's even another question (sans the JNI spin) here on StackOverflow.
Also, check out this google IO video on developing android games to see why your approach may not be faster than pure Java... It Depends.
It turns out that JNI calls are Quite Expensive, so a JNI-based renderer could end up slower than a pure-java one unless you are Very Careful. YM Will V.
I'm pretty sure you'll have to listen to all touches then change behavior based on what is being touched. I suppose you could compute your cube's bounding box on screen and then monkey with your listeners every frame (or every time it moves), but I seriously doubt that would be the most efficient course to take. Listen for all touches, react appropriately.