Home > Back-end >  How would you normalize and calculate speed for a 2D vector if it was clamped by different speeds in
How would you normalize and calculate speed for a 2D vector if it was clamped by different speeds in

Time:07-31

My goal here is to improve the user experience so that the cursor goes where the user would intuitively expect it to when moving the joystick diagonally, whatever that means.


Consider a joystick that has a different configured speed for each direction.

e.g. Maybe the joystick has a defect where some directions are too sensitive and some aren't sensitive enough, so you're trying to correct for that. Or maybe you're playing an FPS where you rarely need to look up or down, so you lower the Y-sensitivity.

Here are our max speeds for each direction:

var map = {
    x: 100,
    y: 200,
}

The joystick input gives us a unit vector from 0 to 1.

Right now the joystick is tilted to the right 25% of the way and tilted up 50% of the way.

joystick = (dx: 0.25, dy: -0.50)

Sheepishly, I'm not sure where to go from here.

Edit: I will try @Caderyn's solution:

var speeds = {
    x: 100, // max speed of -100 to 100 on x-axis
    y: 300, // max speed of -300 to 300 on y-axis
}

var joystick = { dx: 2, dy: -3 }
console.log('joystick normalized:', normalize(joystick))

var scalar = Math.sqrt(joystick.dx*joystick.dx / speeds.x*speeds.x   joystick.dy*joystick.dy / speeds.y*speeds.y)
var scalar2 = Math.sqrt(joystick.dx*joystick.dx   joystick.dy*joystick.dy)
console.log('scalar1' , scalar) // length formula that uses max speeds
console.log('scalar2', scalar2) // regular length formula

// normalize using maxspeeds
var normalize1 = { dx: joystick.dx/scalar, dy: joystick.dy/scalar }
console.log('normalize1', normalize1, length(normalize1))

// regular normalize (no maxpseed lookup)
var normalize2 = { dx: joystick.dx/scalar2, dy: joystick.dy/scalar2 }
console.log('normalize2', normalize2, length(normalize2))

function length({dx, dy}) {
    return Math.sqrt(dx*dx   dy*dy)
}

function normalize(vector) {
    var {dx,dy} = vector
    var len = length(vector)
    return {dx: dx/len, dy: dy/len}
}

Am I missing something massive or does this give the same results as regular vector.len() and vector.normalize() that don't try to integrate the maxspeed data at all?

CodePudding user response:

three solutions :

  • You can simply multiply each component of the input vector by it's respective speed

  • you can divide the vector itself by sqrt(dx^2/hSpeed^2 dy^2/vSpeed^2)

  • you can multiply the vector itself by sqrt((dx^2 dy^2)/(dx^2/hSpeed^2 dy^2/vSpeed^2)) or 0 if the input is (0, 0)

the second solution will preserve the vector's direction when the first will tend to pull it in the direction with the greatest max speed. But if the domain of those function is the unit disc, their image will be an ellipse whose radii are the two max speeds

EDIT : the third method does what the second intended to do: if the imput is A, it will return B such that a/b=c/d (the second method was returning C): 1

  • Related