3d array movement in p5.js?

Hiya!

I'm in dire need of help with a graduation project that I'm working on. What I'm trying to achieve here in the code below is -to put it very simply- to initialize a 3d array of box() objects (this works) and then introduce another box() object (the end goal is to have an array of these as well) to move about within the same 3D grid. The moving unit picks a random location for initialization and a random target for destination (both within the 3D grid). But the problem is that I need the moving unit not to overlap with the static base units, also move orthogonally, and always move one unit size each time. If I run the code below the moving unit reaches the target but without any of the restrictions that I mentioned above. It just takes the shortest vector and goes there regardless.

PS: Since p5js doesn't support wireframe in webgl mode I tried to show them with some transparency for better visual legibility. Although, the loadImage() functions are still there and could be replaced with any image of your liking to better differentiate units from one another.

I'd sincerely appreciate help with this since I'm also very short on time. Thanks in advance.

Here's the verifiable code:

var matrixSize = 5;
var locations = new Array(matrixSize);
var locBool = new Array(matrixSize);

//unit stuff
var unitSize = 40;
var units_a = []
var units_b;

function setup() {
    createCanvas(windowWidth, windowHeight, WEBGL);

    //3D array of location vectors & booleans
    for(var i = 0; i < locations.length; i++){
        locations[i] = new Array(matrixSize);
        locBool[i] = new Array(matrixSize);
        for(var j = 0; j < locations[i].length; j++){
            locations[i][j] = new Array(matrixSize);
            locBool[i][j] = new Array(matrixSize);
            for(var k = 0; k < locations[i][j].length; k++){
                locations[i][j][k] = 
                createVector(i*unitSize, j*unitSize, k*unitSize);
                locBool[i][j][k] = false;
            }
        }
    }

    //base units
    var threshold = 2; //decides on the percentage to be initialized
    for (var i = 0; i < matrixSize; i++) {
        for(var j = 0; j < matrixSize; j++){
            for(var k = 0; k < matrixSize; k++){
                stateRndm = random(10);
                if(stateRndm <= threshold){
                    state = 1;
                    locBool[i][j][k] = true;
                }else{
                    state = 0
                }
                units_a.push(new UnitOne(
                    i*unitSize,j*unitSize,k*unitSize, state));
            }
        }
    }
    units_b = new UnitTwo(); 
}

function draw() {
    background(20);
    ambientLight(235);
    orbitControl();
    rotateX(10);
    rotateY(-10);
    rotateZ(0);

    //center the window and display the units
    push();
    translate(-unitSize*matrixSize/2, -unitSize*matrixSize/2, 0);
    for(var i = 0; i < units_a.length; i++){
        units_a[i].display();
    }
    units_b.display();
    units_b.update();
    units_b.move();
    pop();
}

function UnitOne (x, y, z, state){
    this.x = x;
    this.y = y;
    this.z = z;
    this.state = state;

    //this.img = loadImage("assets/tex_1.jpg");

    //basic movement parameters
    this.acceleration = createVector();
    this.velocity = createVector();
    this.location = createVector(this.x, this.y, this.z);


    this.update = function(){
        this.velocity.add(this.acceleration);
        this.location.add(this.velocity);
        this.acceleration.mult(0);
    }

    this.display = function(){
        if(this.state == 1){
            push();
            scale(1);
            //texture(this.img);
            ambientMaterial(50, 200, 100, 20);
            translate(this.x, this.y, this.z);
            box(unitSize);
            pop();
        }
    }
}

function UnitTwo() {
    //assign random initial location
    this.selector;
    for(var i = 0; i < locations.length; i++){
        for(var j = 0; j < locations[i].length; j++){
            for(var k = 0; k < locations[i][j].length; k++){
                this.selector = createVector(
                    floor(random(i))*unitSize, 
                    floor(random(j))*unitSize, 
                    floor(random(k))*unitSize);
            }
        }
    }
    print(this.selector);

    //assign random target 
    this.targetSelector;
    for(var i = 0; i < locations.length; i++){
        for(var j = 0; j < locations[i].length; j++){
            for(var k = 0; k < locations[i][j].length; k++){
                this.targetSelector = createVector(
                    floor(random(i))*unitSize, 
                    floor(random(j))*unitSize, 
                    floor(random(k))*unitSize);
            }
        }
    }
    print(this.targetSelector);

    //basic movement parameters
    this.location = createVector(
                    this.selector.x,
                    this.selector.y,
                    this.selector.z);
    this.acceleration = createVector();
    this.velocity = createVector();

    this.maxSpeed = 1;
    this.maxForce = 2;

    //this.img = loadImage("assets/tex_2.jpg");

    this.display = function(){
        push();
        //texture(this.img);
        ambientMaterial(200, 100, 40);
        translate(this.location.x, 
                this.location.y, this.location.z);
        scale(1);
        box(unitSize);
        pop();
    }

    this.update = function(){
        this.velocity.add(this.acceleration);
        this.location.add(this.velocity);
        this.acceleration.mult(0);
    }
}

UnitTwo.prototype.move = function(){
    var target = createVector(this.targetSelector.x,
                              this.targetSelector.y,
                              this.targetSelector.z);
    var desired = p5.Vector.sub(target, this.location);

    var d = desired.mag();

    //check the distance to slow down
    if (d < unitSize/2)
        desired.setMag(this.maxSpeed/2);
    else
        desired.setMag(this.maxSpeed);

    var steer = p5.Vector.sub(desired, this.velocity);
    steer.limit(this.maxForce);
    this.acceleration.add(steer);
}

Answers

  • edited March 2017

    Just from afar:

    you can't do an animation with a for loop; instead just move it with draw's own looping

    For moving the block:

    just approach x,y,z separately and one after another. First only treat x, move block until x matches with target's x, then y .... , then z.....

  • This link might be helpful: http://p5js.org/reference/#/p5/draw

    Kf

  • The for loops are just there to make the decisions on where to go. They don't provide the animation. That happens in the UnitTwo.prototype.move() function which is then called within the draw loop. Manually trying out some stuff last night, I also found out that individual axis treatment is my best option. I haven't tried it out yet but I'm also guessing that it'd be reasonable to also implement a switch to make the decision on the next movement axis. Looking at way finding algorithms now. 8-}
    Still struggling with the whole thing, haven't cracked it yet. @-)

  • Looking at way finding algorithms now.

    Start by saying

    if(state==adjustXValue) {
        if(blockX > targetX)
            moveX=-1;
        else if(blockX < targetX)
            moveX=1;
        else {
            state=adjustYValue; //xIsDoneSuccessfully
        }
    } else if(state==adjustYValue) {
     // ...............
    }
    

    and before setup :

    final int adjustXValue=0; 
    final int adjustYValue=1; 
    final int adjustZValue=2; 
    final int adjustmentDone=3; 
    int state=adjustXValue;
    
Sign In or Register to comment.