Tank Throwing Sphere

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
pharo
Posts: 5
Joined: Wed Oct 28, 2009 2:19 pm

Tank Throwing Sphere

Post by pharo »

Hey guys,

Im having trouble understanding ApplyImpulse.

I have a Tank and once an enemy has been targeted, I got a sphere to be added into the space and I have applied an impulse, but it doesnt do what I want it to do.

Obviously I want the sphere to come out of the tank (lets say its at Vector3 position) and the target is at Vector3 targetPosition.

I have tried this:

Code: Select all

ball.applyImpulse(Position, Vector3.Normalize(LockedTarget.Position - Position));
but all it does is just comes out of the tank's position and then drops. Theres no impulse at all.

I also tried

Code: Select all


Vector3 direction = Vector3.Zero;

                direction = LockedTarget.Position - Position;

                direction.Y += (10.0f * (float)Math.Sin(45));

                //ball.applyImpulse(Position, Vector3.Normalize(direction));
But I need to know how strong to throw the ball... I have the distance.. I just need to know how to do this right if all I have is the distance.

Can anyone please help me? Much appreciate it!

Thanks!!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Tank Throwing Sphere

Post by Norbo »

First, you should probably set it so that the tank doesn't collide with its own projectiles. Even if you have the right impulse to fire the sphere directly at the enemy, it could hit the insides of your tank and stop :) You can do this by changing the collision rule between the projectile and the tank:

Code: Select all

                    tank.collisionRules.specificEntities.Add(projectile, CollisionRule.noPair);
To prevent tons of extra worthless collision rules piling up in the list after the projectiles are gone, it would be a good idea to remove the projectiles from the tank's collision rules when they 'explode' later on.


For simplicity, I'm going to use the entity's linearVelocity field as opposed to the apply impulse method. Internally, the linear velocity property computes the appropriate impulse for you, so all you need to worry about is finding what the initial velocity needs to be.

There's more than one way of going about calculating the velocity depending on what kind of behavior you're looking for. So I'm going to say arbitrarily that the horizontal speed of this projectile, traveling through the X-Z plane, is going to be some value I'll call horizontalSpeed (which you can define). Now that that is fixed, we only need to figure out what the vertical velocity needs to be to reach the target.

To get started on that, we need the time it will take for the projectile to make it to the target based on its horizontal speed. Time is the distance divided by the speed of the projectile.

Code: Select all

                    Vector2 horizontalDisplacement = new Vector2(targetPosition.X - position.X, targetPosition.Z - position.Z);
                    float horizontalDistance = horizontalDisplacement.Length();
                    float time = horizontalDistance / horizontalSpeed;
If there was no vertical displacement between the target and myself, the computation would now be straightforward as all that is needed is an application of kinematic equations (http://www.physicsclassroom.com/class/1DKin/u1l6a.cfm). What is the upwards pointing velocity that causes the ball to take exactly 'time' seconds to return to the ground? Using the equation d = Vi * t + (1/2) * a * t^2 and solving for Vi (initial velocity):

0 = Vi * time + (1/2) * (gravity) * time^2
-Vi * time = (1/2) * (gravity) * time^2
-Vi = (1/2) * gravity * time (note that the root at zero was removed here by dividing by time, but we didn't care about it anyway)
Vi = -(1/2) * gravity * time

Plug in your values for gravity (as a scalar like -9.81 since its just pointing straight down) and time (computed earlier from horizontal distance), and there's your initial velocity.

For an environment where the tanks can be in different vertical positions, we still use the same basic approach but the end result is a tiny bit more complicated. d is vertical displacement, which was 0 before. Now, consider it to be targetPosition.Y - position.Y.

targetPosition.Y - position.Y = Vi * time + (1/2) * (gravity) * time^2
-Vi * time = -(targetPosition.Y - position.Y) + (1/2) * (gravity) * time^2
-Vi = -(targetPosition.Y - position.Y) / time + (1/2) * (gravity) * time
Vi = (targetPosition.Y - position.Y) / time - (1/2) * (gravity) * time

And there we go! This equation is equivalent to the last one where the displacement is zero (that term just drops out). Just plug in the numbers and it should work.

The initial 3d velocity is then computed as follows:

Code: Select all

                    Vector2 horizontalDirection = horizontalDisplacement / horizontalDistance;
                    Vector3 initialVelocity = new Vector3(horizontalDirection.X * horizontalSpeed, Vi, horizontalDirection.Y * horizontalSpeed);
Let me know if I messed up somewhere!
pharo
Posts: 5
Joined: Wed Oct 28, 2009 2:19 pm

Re: Tank Throwing Sphere

Post by pharo »

Hmm looks like it gives me the same result as before.

The ball just drops out of the tank and onto the ground.
There is a bit of velocity on it, but not on the right angle.
If theres a way to change the angle it points up, its probably the right equation.

But all its doing is dropping out of the tank, like it just spat it out..


Thanks for your help :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Tank Throwing Sphere

Post by Norbo »

It sounds a lot like it's still colliding with the tank. Did you change the collision rules like at the beginning of the post? Otherwise, the projectile will probably immediately stop due to hitting the tank itself. If there's any other entities that are guaranteed to be in the way, you should add rules to them too.

For testing purposes, you could try arbitrarily offsetting the firing position up 10 meters (out of the tank completely) to see what it does.
pharo
Posts: 5
Joined: Wed Oct 28, 2009 2:19 pm

Re: Tank Throwing Sphere

Post by pharo »

I know its not the collision with the tank because right now the tank isnt part of the physics space.

btw I used: ball.linearVelocity = initialVelocity;


I have attached a pic of whats happening.

Left side shows what happens when I add an offset.
The Right side shows whats been happening without an offset.


Thanks so much for your time!!

Code: Select all

                Sphere ball = new Sphere(Position, 0.1f, 3);
                theGame.space.add(ball);
                theGame.entityRenderer.addEntity(ball);

                ball.moveTo(position+new Vector3(0,10,0));

                float horizontalSpeed = 5; //??
                Vector2 horizontalDisplacement = new Vector2(LockedTarget.Position.X - position.X,
                                                            LockedTarget.Position.Z - position.Z);
                float horizontalDistance = horizontalDisplacement.Length();
                float time = horizontalDistance / horizontalSpeed;

                float gravity = -9.8f;
                float Vi = (LockedTarget.Position.Y - position.Y) / time - (1 / 2) * (gravity) * time;
            
            
                Vector2 horizontalDirection = horizontalDisplacement / horizontalDistance;
                Vector3 initialVelocity = new Vector3(horizontalDirection.X * horizontalSpeed, Vi, horizontalDirection.Y * horizontalSpeed);

                ball.linearVelocity = initialVelocity;
Attachments
bepu.JPG
bepu.JPG (18.28 KiB) Viewed 7134 times
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Tank Throwing Sphere

Post by Norbo »

Two quick little things:
First, the (1 / 2) factor needs to be (1 / 2f) or just .5f since 1 / 2 truncates to zero.
Second, if you're getting positions originally from entities (specifically the centerPosition property), make sure that the centerPosition is 'up to date.' It's a buffered field, so if you set it while it's in a space, it won't be applied until the next space update. If the entity's not in the space, it won't matter. The internalCenterPosition (and other internal-prefixed properties) access directly all the time if you find yourself needing it.
pharo
Posts: 5
Joined: Wed Oct 28, 2009 2:19 pm

Re: Tank Throwing Sphere

Post by pharo »

Aw your a champion!

It was the (1/2f)

I didnt realise it would make a difference.
it makes sense now why it does!

Champion!

Thanks
pharo
Posts: 5
Joined: Wed Oct 28, 2009 2:19 pm

Re: Tank Throwing Sphere

Post by pharo »

The projectile goes really up high and then comes back and hits the target.

Now I just gotta figure out how to get a smaller angle :)


But you've helped heaps! Thank you!!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Tank Throwing Sphere

Post by Norbo »

No problem; and to fix that, you can just increase the horizontal speed.
Post Reply