Grid base movement with gravity and step by step - Godot - grid

I'm trying to make a grid-based movement game but when character jumps, it's affected by gravity; too, the character doesn't receive instructions by the keyboard, but it receive instructions step by step when the players push "GO" button
I have the gravity affecting the character, but I don't know how to move the character step by step on grid-based movement. Someone has an idea or some video tutorial
The var "moviendose" is changed to true when the player press GO
`
extends KinematicBody2D
var moviendose = false
var lista_habilidades_jugador = []
onready var tweene = $AnimatedSprite
const GRAVITY = 9.8
var velocity = Vector2.ZERO
const def_habilidades = {
"Habilidad1": Vector2(16,0),
"Habilidad2": Vector2(-16,0),
"Habilidad3": Vector2(0,(-GRAVITY*16))
}
func _physics_process(delta):
velocity.y += GRAVITY
if lista_habilidades_jugador.size() == 0:
moviendose = false
if moviendose == true:
movimiento()
velocity = move_and_slide(velocity)
func movimiento():
for mov in lista_habilidades_jugador:
if mov == "Habilidad1":
velocity = velocity.move_toward(def_habilidades[mov] , 5)
tweene.flip_h = false
tweene.play("correr")
if mov == "Habilidad2":
velocity = lerp(velocity + def_habilidades[mov], Vector2.ZERO,20)
tweene.flip_h = true
if mov == "Habilidad3":
velocity = velocity + def_habilidades[mov]
self.lista_habilidades_jugador.pop_front()
`
[bar of movement] (https://i.stack.imgur.com/cnwqA.png)

I'll break this into issues:
Units
Sequencing movement
Grid movement
Overshooting
Jump
Units
Presumably, this is an earth-like gravity:
const GRAVITY = 9.8
Which means this is an acceleration, in meters per second square.
But this is a 2D enviroment:
extends KinematicBody2D
So movement units are pixels, not meters. Thus the velocity here is in pixels per seconds:
velocity = move_and_slide(velocity)
And thus here you are adding meters per second squared to pixels per second, and that is not right:
velocity.y += GRAVITY
I bet it looks about right anyway, I'll get back to why.
Do you remember physics? Velocity is displacement over time (speed is distance over time). And we have that time, we call it delta. So this would be meters per second:
GRAVITY * delta
And if we add a conversion constant for pixels to meters, we have:
GRAVITY * delta * pixels_per_meter
How much is that constant? How much you want. Presumably something noticiable, you need to check the size of your sprites to come up with some pixel scaling that works for you.
That means the constant is big, but the time between frames we call detal is small, less than a second. So delta makes the value small and the pixel to meters constant makes it big. And I expect these effects to compensate each other, so it kind of looks good anyway… But having them 1. makes it correct, 2. makes it frame rate independent, 3. gives you control over the scaling.
The alternative is to come up with the gravity value in pixels per second squared. In other words, instead of figuring out a conversion constant from pixels to meters, tweak the gravity value until it works like you want (which is equivalent to having it pre-multiplied by the constant), and just keep delta:
GRAVITY * delta
Now, what is this?
velocity = velocity.move_toward(def_habilidades[mov] , 5)
We are changing the velocity towards some known value at steps of 5. That 5 is a delta velocity (delta meaning change here). You would want an acceleration to make this frame rate independent. Something like this:
velocity = velocity.move_toward(def_habilidades[mov] , 5 * delta)
Which would also imply to pass delta to the movement method.
And what the heck is this?
velocity = lerp(velocity + def_habilidades[mov], Vector2.ZERO,20)
I'll assume the value you are adding to the velocity is also a velocity. I'll challenge that later, it is not the point here.
The point is that you are using lerp weird. The lerp function is meant to give you a value between the first two arguments. The third arguments controls how close is the result towards the first or second argument. When the third argument is zero, you get the first argument as result. And when the third argument is one, you get the second argument. But the third argument is 20?
I don't know what the intention here is. Do you want to go to zero and overshoot?
I don't know. But as far as units are concerned, you are changing the velocity but not by a delta, but by a factor. This is not an acceleration, this is a jerk (look it up).
Sequencing movement
Here you have an unusual structure:
func movimiento(): # you probably will add delta as parameter here
for mov in lista_habilidades_jugador:
# PROCESS THE MOVEMENT
self.lista_habilidades_jugador.pop_front()
You iterate over a list, and each iteration - after processing the movement - you remove an element from the list. Yes, the same list.
If the list stars with three items:
The first iteration looks into the first element and removes the third. The list now has two elements.
The second iteration looks into the second element and removes the second. The list now has one element.
No third iteration.
Don't do that. In general you want to one element, and process it. The minimum would be like this:
func movimiento():
var mov = self.lista_habilidades_jugador.pop_front()
# PROCESS THE MOVEMENT
The next time you call the movement method it will pull the next element, and so on.
Ah, but you are calling the movement method each physics frame. Except presumably the motion should take more than one physics frame. So you should hold up until the current movement finishes.
This is how I would structure it:
func _physics_process(delta):
velocity.y += GRAVITY
movimiento()
velocity = move_and_slide(velocity)
Then the movement method can set the variable:
func movimiento():
# if there are no movements we do nothing
if lista_habilidades_jugador.size() == 0:
return
# get the first movement
var mov = self.lista_habilidades_jugador[0]
moviendose = true
# PROCESS THE MOVEMENT
if not moviendose: # we will come back to this
# we are done moving
self.lista_habilidades_jugador.pop_front()
Grid movement
To process each movement we need to update the velocity and know when it reached the destination. We can't do that if we just have a velocity.
In general we don't want to define velocities for grid movement. But displacements. Which will be an issue for the jump but we will get to that.
Thus, I'll assume that the values you have in your dictionary are not velocities but displacements. In fact, we are going to store a target:
var target := Vector2.ZERO
So we can keep track to were we have to move towards. And we need to update that when we pull a new movement from the list:
func movimiento():
# if there are no movements we do nothing
if lista_habilidades_jugador.size() == 0:
return
# get the first movement
var mov = self.lista_habilidades_jugador[0]
if not moviendose:
# just starting a new movement
var displacement = def_habilidades[mov]
target = position + displacement
moviendose = true
# PROCESS THE MOVEMENT
if not moviendose: # we will come back to this
# we are done moving
self.lista_habilidades_jugador.pop_front()
The other thing we need is how long it should take to move. I'll come up with some value, you tweak it as you see fit:
var step_time := 0.5
Do you remember physics (again)? the velocity is displacement over time.
velocity = displacement / step_time
So:
func movimiento():
# if there are no movements we do nothing
if lista_habilidades_jugador.size() == 0:
return
# get the first movement
var mov = self.lista_habilidades_jugador[0]
if not moviendose:
# just starting a new movement
var displacement = def_habilidades[mov]
velocity = displacement / step_time
target = position + displacement
moviendose = true
# PROCESS THE MOVEMENT
if not moviendose: # we will come back to this
# we are done moving
self.lista_habilidades_jugador.pop_front()
And what is left is finding out if we reached the target. A first approximation is this:
func movimiento():
# if there are no movements we do nothing
if lista_habilidades_jugador.size() == 0:
return
# get the first movement
var mov = self.lista_habilidades_jugador[0]
if not moviendose:
# just starting a new movement
var displacement = def_habilidades[mov]
velocity = displacement / step_time
target = position + displacement
moviendose = position.distance_to(target) > 0
if not moviendose:
# we are done moving
self.lista_habilidades_jugador.pop_front()
And we are done. Right? RIGHT?
Overshooting
We are not done. We move some distance each frame, so the distance to the target will likely not hit zero. And that is without talking about floating point errors.
Thus, instead of finding out if we reached the target, we will find out if we will overshoot the target. And to do that we need to compute how we will move. Start by bringing delta in (I'm also adding type information):
func _physics_process(delta:float) -> void:
velocity.y += GRAVITY
movimiento(delta)
velocity = move_and_slide(velocity)
func movimiento(delta:float) -> void:
# if there are no movements we do nothing
if lista_habilidades_jugador.size() == 0:
return
# get the first movement
var mov:String = self.lista_habilidades_jugador[0]
if not moviendose:
# just starting a new movement
var displacement:Vector2 = def_habilidades[mov]
velocity = displacement / step_time
target = position + displacement
moviendose = position.distance_to(target) > 0
if not moviendose:
# we are done moving
self.lista_habilidades_jugador.pop_front()
Now we can compute how much we will move this frame:
velocity.length() * delta
And compare that with the distance to the target:
moviendose = position.distance_to(target) > velocity.length() * delta
Now that we know we will overshoot, we should prevent it. The first idea is to snap to the target:
if not moviendose:
# we are done moving
position = target
self.lista_habilidades_jugador.pop_front()
For reference I'll also mention that we can compute the velocity to reach the target this frame (within floating point error):
if not moviendose:
# we are done moving
velocity = velocity.normalized() * position.distance_to(target) / delta
self.lista_habilidades_jugador.pop_front()
Here we normalize the velocity to get just its direction. And do you remember physics? Yes, yes. That is distance over time.
However we will not use this one, because it would mess with the jump…
Jump
But the jump does not work like that. You cannot define a jump the same way. There are six ways to define a vertical jump:
By Gravity and Time
By Gravity and Speed
By Gravity and Height
By Time and Speed
By Time and Height
By Speed and Height
Defining the jump by gravity and speed is very common, at least among beginners, because you already have a gravity and then you define some upward velocity and you have a jump.
It is, however, a good idea to define the gravity using height because then you know - by design - how high it can jump which can be useful for scenario design.
In fact, in the spirit of keeping the representation of movement by displacement, using a definition by gravity and height is convenient. So I'll go with that. Yet, we will still need to compute the velocity, which we will do like this:
half_jump_time = sqrt(-2.0 * max_height / gravity)
jump_time = half_jump_time * 2.0
vertical_speed = -gravity * half_jump_time
That comes from the equations of motion. I'll spare how to come up with that, feel free to look it up.
However, note that the vertical component will not be the destination vertical position, but the height of the jump. Which is half way through the jump. So for consistency sake, when you specify a jump the displacement will be to the highest point of the jump…
We will know it is a jump because it has a vertical component at all.
if not moviendose:
# just starting a new movement
var displacement:Vector2 = def_habilidades[mov]
target = position + displacement
if displacement.y == 0:
velocity = displacement / step_time
else:
var half_jump_time = sqrt(-2.0 * displacement.y / gravity)
var jump_time = half_jump_time * 2.0
velocity.y = -gravity * half_jump_time
velocity.x = displacement.x / half_jump_time
And that highlights another problem: We cannot say the motion ended when reached the target, we also need to check if the character is on the ground.
For that effect, I'll have one extra variable (add at the top of the file):
var target_reached := false
So we can say:
var distance:float = velocity.length() * delta
target_reached = target_reached or position.distance_to(target) > distance
moviendose = not (target_reached and is_on_floor())
if not moviendose:
# we are done moving
target_reached = false
position = target
self.lista_habilidades_jugador.pop_front()
Unless I forgot to include something, that should be it.
Addendum: Yes, I forgot something. When the character landed that is not the target position (because the target position is the mid point of the jump). You could, in theory, snap mid jump, but I don't think that is of much use. Instead consider snapping the position (or issuing a move) once landed to the nearest position of the grid. You can use the method snapped on the vector to find out where it aligns to the grid size.

Related

how to color point cloud from image pixels?

I am using google tango tablet to acquire point cloud data and RGB camera images. I want to create 3D scan of the room. For that i need to map 2D image pixels to point cloud point. I will be doing this with a lot of point clouds and corresponding images.Thus I need to write a code script which has two inputs 1. point cloud and 2. image taken from the same point in same direction and the script should output colored point cloud. How should i approach this & which platforms will be very simple to use?
Here is the math to map a 3D point v to 2D pixel space in the camera image (assuming that v already incorporates the extrinsic camera position and orientation, see note at bottom*):
// Project to tangent space.
vec2 imageCoords = v.xy/v.z;
// Apply radial distortion.
float r2 = dot(imageCoords, imageCoords);
float r4 = r2*r2;
float r6 = r2*r4;
imageCoords *= 1.0 + k1*r2 + k2*r4 + k3*r6;
// Map to pixel space.
vec3 pixelCoords = cameraTransform*vec3(imageCoords, 1);
Where cameraTransform is the 3x3 matrix:
[ fx 0 cx ]
[ 0 fy cy ]
[ 0 0 1 ]
with fx, fy, cx, cy, k1, k2, k3 from TangoCameraIntrinsics.
pixelCoords is declared vec3 but is actually 2D in homogeneous coordinates. The third coordinate is always 1 and so can be ignored for practical purposes.
Note that if you want texture coordinates instead of pixel coordinates, that is just another linear transform that can be premultiplied onto cameraTransform ahead of time (as is any top-to-bottom vs. bottom-to-top scanline addressing).
As for what "platform" (which I loosely interpreted as "language") is simplest, the native API seems to be the most straightforward way to get your hands on camera pixels, though it appears people have also succeeded with Unity and Java.
* Points delivered by TangoXYZij already incorporate the depth camera extrinsic transform. Technically, because the current developer tablet shares the same hardware between depth and color image acquisition, you won't be able to get a color image that exactly matches unless both your device and your scene are stationary. Fortunately in practice, most applications can probably assume that neither the camera pose nor the scene changes enough in one frame time to significantly affect color lookup.
This answer is not original, it is simply meant as a convenience for Unity users who would like the correct answer, as provided by #rhashimoto, worked out for them. My contribution (hopefully) is providing code that reduces the normal 16 multiplies and 12 adds (given Unity only does 4x4 matrices) to 2 multiplies and 2 adds by dropping out all of the zero results. I ran a little under a million points through the test, checking each time that my calculations agreed with the basic matrix calculations - defined as the absolute difference between the two results being less than machine epsilon - I'm as comfortable with this as I can be knowing that #rhashimoto may show up and poke a giant hole in it :-)
If you want to switch back and forth, remember this is C#, so the USEMATRIXMATH define must appear at the beginning of the file.
Given there's only one Tango device right now, and I'm assuming the intrinsics are constant across all of the devices, I just dumped them in as constants, such that
fx = 1042.73999023438
fy = 1042.96997070313
cx = 637.273986816406
cy = 352.928985595703
k1 = 0.228532999753952
k2 = -0.663019001483917
k3 = 0.642908990383148
Yes they can be dumped in as constants, which would make things more readable, and C# is probably smart enough to optimize it out - however, I spent too much of my life in Agner Fogg's stuff, and will always be paranoid.
The commented out code at the bottom is for testing the difference, should you desire. You'll have to uncomment some other stuff, and comment out the returns if you want to test the results.
My thanks again to #rhashimoto, this is far far better than what I had
I have stayed true to his logic, remember these are pixel coordinates, not UV coordinates - he is correct that you can premultiply the transform to get normalized UV values, but since he schooled me on this once already, I will stick with exactly the math he presented before I fiddle with too much :-)
static public Vector2 PictureUV(Vector3 tangoDepthPoint)
{
Vector2 imageCoords = new Vector2(tangoDepthPoint.x / tangoDepthPoint.z, tangoDepthPoint.y / tangoDepthPoint.z);
float r2 = Vector2.Dot(imageCoords, imageCoords);
float r4 = r2*r2;
float r6 = r2*r4;
imageCoords *= 1.0f + 0.228532999753952f*r2 + -0.663019001483917f*r4 + 0.642908990383148f*r6;
Vector3 ic3 = new Vector3(imageCoords.x,imageCoords.y,1);
#if USEMATRIXMATH
Matrix4x4 cameraTransform = new Matrix4x4();
cameraTransform.SetRow(0,new Vector4(1042.73999023438f,0,637.273986816406f,0));
cameraTransform.SetRow(1, new Vector4(0, 1042.96997070313f, 352.928985595703f, 0));
cameraTransform.SetRow(2, new Vector4(0, 0, 1, 0));
cameraTransform.SetRow(3, new Vector4(0, 0, 0, 1));
Vector3 pixelCoords = cameraTransform * ic3;
return new Vector2(pixelCoords.x, pixelCoords.y);
#else
//float v1 = 1042.73999023438f * imageCoords.x + 637.273986816406f;
//float v2 = 1042.96997070313f * imageCoords.y + 352.928985595703f;
//float v3 = 1;
return new Vector2(1042.73999023438f * imageCoords.x + 637.273986816406f,1042.96997070313f * imageCoords.y + 352.928985595703);
#endif
//float dx = Math.Abs(v1 - pixelCoords.x);
//float dy = Math.Abs(v2 - pixelCoords.y);
//float dz = Math.Abs(v3 - pixelCoords.z);
//if (dx > float.Epsilon || dy > float.Epsilon || dz > float.Epsilon)
// UnityEngine.Debug.Log("Well, that didn't work");
//return new Vector2(v1, v2);
}
As one final note, do note the code he provided is GLSL - if you're just using this for pretty pictures, use it - this is for those that actually need to perform additional processing.

THREE.js: Why is my object flipping whilst travelling along a spline?

Following up from my original post Three.JS Object following a spline path - rotation / tangent issues & constant speed issue, I am still having the issue that the object flips at certain points along the path.
View this happening on this fiddle: http://jsfiddle.net/jayfield1979/T2t59/7/
function moveBox() {
if (counter <= 1) {
box.position.x = spline.getPointAt(counter).x;
box.position.y = spline.getPointAt(counter).y;
tangent = spline.getTangentAt(counter).normalize();
axis.cross(up, tangent).normalize();
var radians = Math.acos(up.dot(tangent));
box.quaternion.setFromAxisAngle(axis, radians);
counter += 0.005
} else {
counter = 0;
}
}
The above code is what moves my objects along the defined spline path (an oval in this instance). It was mentioned by #WestLangley that: "Warning: cross product is not well-defined if the two vectors are parallel.".
As you can see, from the shape of the path, I am going to encounter a number of parallel vectors. Is there anything I can do to prevent this flipping from happening?
To answer the why question in the title. The reason its happening is that at some points on the curve the vector up (1,0,0) and the tangent are parallel. This means their cross product is zero and the construction of the quaternion fails.
You could follow WestLangley suggestion. You really want the up direction to be the normal to the plane the track is in.
Quaternion rotation is tricky to understand the setFromAxisAngle function rotates around the axis by a given angle.
If the track lies in the X-Y plane then we will want to rotate around the Z-axis. To find the angle use Math.atan2 to find the angle of the tangent
var angle = Math.atan2(tangent.y,tangent.x);
putting this together set
var ZZ = new THREE.Vector3( 0, 0, 1 );
and
tangent = spline.getTangentAt(counter).normalize();
var angle = Math.atan2(tangent.y,tangent.x);
box.quaternion.setFromAxisAngle(ZZ, angle);
If the track leaves the X-Y plane things will get trickier.

How to make an object move in the path of an arc?

I'm making a game where there should be a robot throwing ball-shaped objects at another robot.
The balls thrown should fly in the shape of a symmetrical arc. Pretty sure the math-word for this is a parabola.
Both robots are on the x axis.
How can I implement such a thing in my game? I tried different approaches, none worked.
The current system of moving things in my game, is like so: Every object has x and y co-ordinates (variables), and dx and dy variables.
Every object has a move() method, that get's called every cycle of the game-loop. It simply adds dx to x and dy to y.
How can I implement what I described, into this system?
If there is a lot of math involved, please try to explain in a simply way, because I'm not great with math.
My situation:
Thanks a lot
You should add velocity to your missiles.
Velocity is a vector, which means it says how fast the missile moves in x-axis and how fast in y-axis. Now, instead of using Move() use something like Update(). Something like this:
void Update()
{
position.X += velocity.X;
position.Y += velocity.Y;
}
Now let's think, what happens to the missile, once it is shot:
In the beginning it has some start velocity. For example somebody shot the missile with speed of 1 m/s in x, and -0.5 m/s in y. Then as it files, the missile will be pulled to the ground - it's Y velocity will be growing towards ground.
void Update()
{
velocity.Y += gravity;
position.X += velocity.X;
position.Y += velocity.Y;
}
This will make your missile move accordingly to physics (excluding air resistance) and will generate a nice-looking parabola.
Edit:
You might ask how to calculate the initial velocity. Let's assume we have a given angle of shot (between line of shot and the ground), and the initial speed (we may know how fast the missiles after the shot are, just don't know the X and Y values). Then:
velocity.X = cos(angle) * speed;
velocity.Y = sin(angle) * speed;
Adding to Michal's answer, to make sure the missile hits the robot (if you want it to track the robot), you need to adjust its x velocity.
void Update()
{
ball.dy += gravity; // gravity = -9.8 or whatever makes sense in your game
ball.dx = (target.x - ball.x); // this needs to be normalized.
double ballNorm = sqrt(ball.dx^2 + ball.dy^2);
ball.dx /= ballNorm;
ball.x += ball.dx;
ball.y += ball.dy
}
This will cause the missile to track your target. Normalizing the x component of your vector ensures that it will never go above a velocity of one. It's nor fully "normalizing" the vector because normally you would have to do this to the y component too. If we didn't normalize here, we would end up with a ball that jumps all the way to your target on the first update. If you want to make your missile travel faster, just multiply ballNorm by some amount.
you can get every thing you need from these few equations
for the max height to time to distance.
g = gravity
v = start vorticity M/S
a = start angle deg
g = KG of object * 9.81
time = v*2 * sin(a) / g
range = v^2 * sin(a * 2) / g
height = v^2 * sin(a)^2 / 2*g

Potential floating point issue with cosine acceleration curve

I am using a cosine curve to apply a force on an object between the range [0, pi]. By my calculations, that should give me a sine curve for the velocity which, at t=pi/2 should have a velocity of 1.0f
However, for the simplest of examples, I get a top speed of 0.753.
Now if this is a floating point issue, that is fine, but that is a very significant error so I am having trouble accepting that it is (and if it is, why is there such a huge error computing these values).
Some code:
// the function that gives the force to apply (totalTime = pi, maxForce = 1.0 in this example)
return ((Mathf.Cos(time * (Mathf.PI / totalTime)) * maxForce));
// the engine stores this value and in the next fixed update applies it to the rigidbody
// the mass is 1 so isn't affecting the result
engine.ApplyAccelerateForce(applyingForce * ship.rigidbody2D.mass);
Update
There is no gravity being applied to the object, no other objects in the world for it to interact with and no drag. I'm also using a RigidBody2D so the object is only moving on the plane.
Update 2
Ok have tried a super simple example and I get the result I am expecting so there must be something in my code. Will update once I have isolated what is different.
For the record, super simple code:
float forceThisFrame;
float startTime;
// Use this for initialization
void Start () {
forceThisFrame = 0.0f;
startTime = Time.fixedTime;
}
// Update is called once per frame
void Update () {
float time = Time.fixedTime - startTime;
if(time <= Mathf.PI)
{
forceThisFrame = Mathf.Cos (time);
if(time >= (Mathf.PI /2.0f)- 0.01f && time <= (Mathf.PI /2.0f) + 0.01f)
{
print ("Speed: " + rigidbody2D.velocity);
}
}
else
{
forceThisFrame = 0.0f;
}
}
void FixedUpdate()
{
rigidbody2D.AddForce(forceThisFrame * Vector2.up);
}
Update 3
I have changed my original code to match the above example as near as I can (remaining differences listed below) and I still get the discrepancy.
Here are my results of velocity against time. Neither of them make sense to me, with a constant force of 1N, that should result in a linear velocity function v(t) = t but that isn't quite what is produced by either example.
Remaining differences:
The code that is "calculating" the force (now just returning 1) is being run via a non-unity DLL, though the code itself resides within a Unity DLL (can explain more but can't believe this is relevant!)
The behaviour that is applying the force to the rigid body is a separate behaviour.
One is moving a cube in an empty enviroment, the other is moving a Model3D and there is a plane nearby - tried a cube with same code in broken project, same problem
Other than that, I can't see any difference and I certainly can't see why any of those things would affect it. They both apply a force of 1 on an object every fixed update.
For the cosine case this isn't a floating point issue, per se, it's an integration issue.
[In your 'fixed' acceleration case there are clearly also minor floating point issues].
Obviously acceleration is proportional to force (F = ma) but you can't just simply add the acceleration to get the velocity, especially if the time interval between frames is not constant.
Simplifying things by assuming that the inter-frame acceleration is constant, and therefore following v = u + at (or alternately ∂v = a.∂t) you need to scale the effect of the acceleration in proportion to the time elapsed since the last frame. It follows that the smaller ∂t is, the more accurate your integration.
This was a multi-part problem that started with me not fully understanding Update vs. FixedUpdate in Unity, see this question on GameDev.SE for more info on that part.
My "fix" from that was advancing a timer that went with the fixed update so as to not apply the force wrong. The problem, as demonstrated by Eric Postpischil was because the FixedUpdate, despite its name, is not called every 0.02s but instead at most every 0.02s. The fix for this was, in my update to apply some scaling to the force to apply to accomodate for missed fixed updates. My code ended up looking something like:
Called From Update
float oldTime = time;
time = Time.fixedTime - startTime;
float variableFixedDeltaTime = time - oldTime;
float fixedRatio = variableFixedDeltaTime / Time.fixedDeltaTime;
if(time <= totalTime)
{
applyingForce = forceFunction.GetValue(time) * fixedRatio;
Vector2 currentVelocity = ship.rigidbody2D.velocity;
Vector2 direction = new Vector2(ship.transform.right.x, ship.transform.right.y);
float velocityAlongDir = Vector2.Dot(currentVelocity, direction);
float velocityPrediction = velocityAlongDir + (applyingForce * lDeltaTime);
if(time > 0.0f && // we are not interested if we are just starting
((velocityPrediction < 0.0f && velocityAlongDir > 0.0f ) ||
(velocityPrediction > 0.0f && velocityAlongDir < 0.0f ) ))
{
float ratio = Mathf.Abs((velocityAlongDir / (applyingForce * lDeltaTime)));
applyingForce = applyingForce * ratio;
// We have reversed the direction so we must have arrived
Deactivate();
}
engine.ApplyAccelerateForce(applyingForce);
}
Where ApplyAccelerateForce does:
public void ApplyAccelerateForce(float requestedForce)
{
forceToApply += requestedForce;
}
Called from FixedUpdate
rigidbody2D.AddForce(forceToApply * new Vector2(transform.right.x, transform.right.y));
forceToApply = 0.0f;

Moving character with vectors

Whenever I have a character and I want him to move to an object I always have to convert it to an angle, ex:
int adjacent = myPosition.X - thatPosition.X;
int opposite = myPosition.Y - thatPosition.Y;
double angle = Math.atan2(adjacent, opposite);
myPosition.X += Math.cos(angle);
myPosition.Y += Math.sin(angle);
Is there an easier way to move an object to another by just using vectors and not converting to an angle and back, if so I would appreciate if you showed how and/or pointed me to a site that could show me.
p.s. I am coding in XNA
Yes, you can minimize the trig & take a more linear algebra approach. That would look something like this:
//class scope fields
Vector2 myPosition, velocity, myDestination;
float speed;
//in the initialize method
myPosition = new Vector2(?, ?);
myDestination = new Vector2(?, ?);
speed = ?f;//usually refers to "units (or pixels) per second"
//in the update method to change the direction traveled by changing the destination
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
myDestination = new Vector2(?', ?');//change direction by changing destination
Velocity = Vector2.Normalize(myDestination - myPosition);
velocity *= speed;
myPosition += velocity * elapsed;
//or instead of changing destination to change velocity direction, you can simply rotate the velocity vector
velocity = Vector2.Transform(velocity, Matrix.CreateRotationZ(someAngle);
velocity.Normalize();
velocity *= speed;
myPosition += velocity * elapsed;
The only angles/trig used here is the trig that is embedded in the CreateRotationZ() method and it is happening behind the scenes by the xna framework.

Resources