LoginSignup
5
9

More than 5 years have passed since last update.

processingで障害物を回避する

Last updated at Posted at 2017-05-09

20170509.jpg

シフマンさんの自律エージェントを応用してグレーの円を回避するパーティクル群を作ってみました。
各パーティクルは右方向に移動するベクトルを持っていますが、円の付近に近づくと円の中心に対して
反対方向のベクトルが作用するように設定しています。しかし、円から離れたらまた右方向の流れに
戻したいので、PVector(自分のx + 100, 元いたy)にシフトするようにしています。

ArrayList<Agent> agents;

void setup () {

    size (800, 600, P2D);

    agents = new ArrayList<Agent> ();

    for (int i = 0; i < 1000; i++) {
        agents.add (new Agent (random (width), random (height), random (2, 4)));
    }

}

void draw () {

    background (255);

    for (Agent a : agents) {
        a.separate (agents);
        a.update ();
        a.border ();
        a.render ();
    }

    if (agents.size () > 1200) {
        agents.remove (0);
    }

    fill (200);
    stroke (127);
    ellipseMode (CENTER);
    ellipse (mouseX, mouseY, 100 * 2, 100 * 2);

}

void mouseDragged () {

    agents.add (new Agent (mouseX, mouseY, random (2, 4)));

}

class Agent {

    PVector location;
    PVector velocity;
    PVector acceleration;

    PVector circle;
    PVector diff;

    float r;
    float maxforce;
    float maxspeed;
    float base_y;

    Agent (float x, float y, float ms) {

        location = new PVector (x, y);
        velocity = new PVector (ms, 0);
        acceleration = new PVector (0, 0);

        diff = new PVector ();

        r = 100.0;
        maxforce = 0.2;
        maxspeed = ms;
        base_y = y;

    }

    void update () {

        velocity.add (acceleration);
        velocity.limit (maxspeed);
        location.add (velocity);
        acceleration.mult (0);

    }

    void render () {

        fill (127);
        stroke (0);
        strokeWeight (1);
        pushMatrix ();
        translate (location.x, location.y);
        ellipse (0, 0, 4, 4);
        popMatrix ();

    }

    void applyForce (PVector force) {

        acceleration.add (force);

    }

    void separate (ArrayList<Agent> agents) {

        float desired_separation = r * 1.4;

        circle = new PVector (mouseX, mouseY);

        for (Agent a : agents) {
            float d = PVector.dist (location, circle);
            if ((d > 0) && (d < desired_separation)) {
                PVector diff01 = PVector.sub (location, circle);
                PVector diff02 = new PVector (maxspeed * abs (circle.y - location.y) * 0.8, 0);
                diff = PVector.add (diff01, diff02);
                diff.normalize ();
                diff.div (d);
            } else {
                diff = PVector.sub (new PVector (velocity.x + 100, base_y - location.y), velocity);
                diff.normalize ();
            }
        }

        diff.setMag (maxspeed);
        PVector steer = PVector.sub (diff, velocity);
        steer.limit (maxforce);
        applyForce (steer);

    }

    void border () {

        if (location.x < -r) location.x = width + r;
        if (location.y < -r) location.y = height + r;
        if (location.x > width + r) location.x = -r;
        if (location.y > height + r) location.y = -r;

    }

}
5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9