javascriptpositionp5.jslerp

Moving object to targets within an array on the canvas


I have some P5js code that I made.

It basically moves the circle around the screen to predetermined targets stored in an array. I will be using it within my game that uses A* pathfinding and stores the path points in an array. I then am looking at moving the player to each of those points smoothly with the code below.

What I am asking

  1. Most importantly, can this code be optimized/cleaner if so, how?
  2. How can I allow for a larger speed value. Currently if I change the speed to 3, it doesnt trigger the if statement (I would need to cicle to be at the target within a 1 px varience regardless of spped).

Other notes

Thank you :)

var targets
var target_index = 0
var position
var x_complete = true
var y_complete = true
var speed = 1

function setup() {
    createCanvas(400, 400);
    targets = [createVector(0, 0), createVector(50, 50), createVector(0, 0), createVector(0, 50), createVector(200, 200)]
    position = targets[0]
}

var count = 0;

function draw() {
    background(220);
    move_c()
    draw_c()
}


function draw_c() {
    strokeWeight(10);
    point(position.x, position.y);
}


function move_c() {
    var x_needs_to_goes_up
    var x_is_currently_smaller

    var y_needs_to_goes_up
    var y_is_currently_smaller
    x_complete = false
    y_complete = false

    if (targets.length - 1 > target_index) {

        x_needs_to_goes_up = !number_is_larger(targets[target_index].x, targets[target_index + 1].x) //X goes up
        x_is_currently_smaller = number_is_smaller(targets[target_index].x, targets[target_index + 1].x)

        y_needs_to_goes_up = !number_is_larger(targets[target_index].y, targets[target_index + 1].y) //X goes up
        y_is_currently_smaller = number_is_smaller(targets[target_index].y, targets[target_index + 1].y)


        if (x_needs_to_goes_up && x_is_currently_smaller) { //If x is currently smaller then target
            move_x(true)
        } else if (x_needs_to_goes_up && !x_is_currently_smaller) {
            x_complete = true

        }
        if (!x_needs_to_goes_up && !x_is_currently_smaller) { //If x is currently smaller then target
            move_x(false)
        } else if (!x_needs_to_goes_up && x_is_currently_smaller) {
            x_complete = true

        }

        if (y_needs_to_goes_up && y_is_currently_smaller) { //If x is currently smaller then target
            move_y(true)
        } else if (y_needs_to_goes_up && !y_is_currently_smaller) {
            y_complete = true

        }
        if (!y_needs_to_goes_up && !y_is_currently_smaller) { //If x is currently smaller then target
            move_y(false)
        } else if (!y_needs_to_goes_up && y_is_currently_smaller) {
            y_complete = true

        }

        if (y_complete && x_complete) {
            target_index++
        }
    }

}

function move_y(up) {
    if (up) {
        position = createVector(targets[target_index].x, targets[target_index].y += speed)

    } else {
        position = createVector(targets[target_index].x, targets[target_index].y -= speed)

    }
}

function move_x(up) {
    if (up) {
        position = createVector(targets[target_index].x += speed, targets[target_index].y)

    } else {
        position = createVector(targets[target_index].x -= speed, targets[target_index].y)

    }
}

function number_is_larger(num1, num2) {
    return num1 > num2 ? true : false
}

function number_is_smaller(num1, num2) {
    return num1 < num2 - 1 ? true : false
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>


Solution

  • The main problem in your code is that when you increase the speed you shoot over the target as you may not hit the target accurately.

    First of all the initial position vector should be a copy of the first target:

    position = targets[0].copy()
    

    Calculate the vector from the position to the next target and the Euclidean lenght of the vector (this is the distance of the position to the next target:

    let direction = p5.Vector.sub(targets[target_index], position)
    let distance = direction.mag()
    

    Distinguish whether the distance to the next target is greater or less than the speed:

    if (distance <= speed) {
        // less
        // [...]
    } else {
        // greater
        // [...]
    } 
    

    If it is less, the next position is the next target and the target index need to be incremented:

    position = targets[target_index].copy()
    target_index ++;
    

    If it is greater, make on step forwards. Calculate the normalized direction vector. A normalized vector is a Unit vector and has a length of 1. Multiply the vector with the speed. Now the vector is length the speed. Add the vector to the position:

    position.add(direction.normalize().mult(speed))
    

    var targets
    var target_index = 0
    var position
    var speed = 3
    
    function setup() {
        createCanvas(400, 400);
        targets = [createVector(0, 0), createVector(50, 50), createVector(0, 0), createVector(0, 50), createVector(200, 200)]
        position = targets[0].copy()
    }
    
    function draw() {
        background(220);
        move_c()
        draw_c()
    }
    
    function draw_c() {
        strokeWeight(10);
        point(position.x, position.y);
    }
    
    function move_c() {
        if (targets.length - 1 > target_index) {
    
            let direction = p5.Vector.sub(targets[target_index], position)
            let distance = direction.mag()
            if (distance <= speed) {
                position = targets[target_index].copy()
                target_index ++;
            } else {
                position.add(direction.normalize().mult(speed))
            } 
        } else {
            target_index = 0
        }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>