Processing:Примеры/Силы (гравитация и сопротивление жидкости) с векторами

Материал из Онлайн справочника
Версия от 07:59, 27 августа 2023; Myagkij (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Описание[1]

Демонстрация воздействия на тела (класс Mover) двух разных сил. На тела постоянно воздействует сила притяжения (гравитация), но после попадания в «воду» на них также начинает воздействовать сопротивление жидкости.

Об основах работы с PVector читайте тут, а также на странице «Примеры» в разделе «Векторы».

Пример

// пять падающих тел:
Mover[] movers = new Mover[10];

// жидкость:
Liquid liquid;

void setup() {
  size(640, 360);
  reset();
  // создаем «воду»:
  liquid = new Liquid(0, height/2, width, height/2, 0.1);
}

void draw() {
  background(0);

  // рисуем «воду»:
  liquid.display();

  for (Mover mover : movers) {

    // находится ли тело в жидкости?
    if (liquid.contains(mover)) {
      // рассчитываем силу сопротивления:
      PVector drag = liquid.drag(mover);
      // применяем силу сопротивления к падающему телу:
      mover.applyForce(drag);
    }

    // рассчитываем гравитацию на основе массы объекта:
    PVector gravity = new PVector(0, 0.1*mover.mass);
    // применяем гравитацию:
    mover.applyForce(gravity);

    // обновляем экран:
    mover.update();
    mover.display();
    mover.checkEdges();
  }

  fill(255);
  text("click mouse to reset", 10, 30);
   //  "кликните мышкой, чтобы сбросить результаты"
}

void mousePressed() {
  reset();
}

// перезапускаем все объекты Mover,
// задавая всем им случайный размер:
void reset() {
  for (int i = 0; i < movers.length; i++) {
    movers[i] = new Mover(random(0.5, 3), 40+i*70, 0);
  }
}


/**
 * Силы (гравитация и сопротивление жидкости) с векторами 
 * Автор – Дэниэл Шиффман.  
 * 
 * Демонстрация воздействия на тела (класс Mover) разных сил.
 * Тела постоянно подвергаются силе притяжения.
 * Попадая в «воду», тела начинают испытывать сопротивление жидкости.
 */


class Mover {

  // позиция, скорость и ускорение: 
  PVector position;
  PVector velocity;
  PVector acceleration;

  // значение массы привязано к размеру тела:
  float mass;

  Mover(float m, float x, float y) {
    mass = m;
    position = new PVector(x, y);
    velocity = new PVector(0, 0);
    acceleration = new PVector(0, 0);
  }

  // второй закон Ньютона: F = M * A, т.е. сила, действующая на тело,
  // равна произведению массы тела на сообщаемое этой силой ускорение 
  // (или A = F / M):
  void applyForce(PVector force) {
    // делим силу на массу:
    PVector f = PVector.div(force, mass);
    // задаем ускорению значение, рассчитанное выше:
    acceleration.add(f);
  }

  void update() {

    // скорость меняется в зависимости от ускорения:
    velocity.add(acceleration);
    // позиция меняется с помощью скорости:
    position.add(velocity);
    // с каждым кадром ускорение нужно удалять:
    acceleration.mult(0);
  }

  // рисуем объект Mover:
  void display() {
    stroke(255);
    strokeWeight(2);
    fill(255, 200);
    ellipse(position.x, position.y, mass*16, mass*16);
  }

  // рассчитываем столкновение тела с дном:
  void checkEdges() {
    if (position.y > height) {
      velocity.y *= -0.9;  // небольшое затухание
                           // при столкновении с дном
      position.y = height;
    }
  }
}


/**
 * Силы (гравитация и сопротивление жидкости) с векторами
 * Автор – Дэниэл Шиффман.
 * 
 * Демонстрация воздействия на тела (класс Mover) разных сил.
 * Тела постоянно подвергаются силе притяжения.
 * Попадая в «воду», тела начинают испытывать сопротивление жидкости.
 */

// класс Liquid:
class Liquid {


  // «вода» - это прямоугольник:
  float x, y, w, h;
  // коэффициент сопротивления:
  float c;

  Liquid(float x_, float y_, float w_, float h_, float c_) {
    x = x_;
    y = y_;
    w = w_;
    h = h_;
    c = c_;
  }

  // объект Mover находится в воде?
  boolean contains(Mover m) {
    PVector l = m.position;
    if (l.x > x && l.x < x + w && l.y > y && l.y < y + h) {
      return true;
    } else {
      return false;
    }
  }

  // рассчитываем сопротивление жидкости:
  PVector drag(Mover m) {
    // рассчитываем сопротивление,
    // умножая коэффициент сопротивления на квадрат скорости:
    float speed = m.velocity.mag();
    float dragMagnitude = c * speed * speed;

    // задаем направление вектору сопротивления жидкости,
    // инвертируя направление движения (скорость) падающего тела:
    PVector drag = m.velocity.copy();
    drag.mult(-1);

    // присваиваем направлению движения (drag)
    // значение сопротивления жидкости (dragMagnitude):
    drag.setMag(dragMagnitude);
    return drag;
  }

  void display() {
    noStroke();
    fill(127);
    rect(x, y, w, h);
  }
}

См.также

Внешние ссылки