【创意编程作业】《代码本色》第2章——力

非 Y 不嫁゛ 提交于 2020-01-14 18:03:23

Part1 实现效果以及扩展

在这里插入图片描述
水平方向给一个向左或向右的(风)力,垂直方向给一个重力或反重力,力的方向随帧数而改变。灰色小球为阻力小球,该区域内阻力系数不同。
操作说明:
1、点击鼠标重置。
2、移动鼠标来移动阻力球。
3、滚动滑轮来缩放阻力球大小。

Part2 力

力是一个向量。力的书面化概念源自牛顿运动定律。
牛顿三大运动定律:
1、物体有保持静止或运动的趋势。
2、力等于质量乘以加速度,F=M*A。
3、每个作用力都有一个大小相等、方向相反的作用力。
其中第二条定律编程时最为重要,在处理像素时,常常令所有对象的质量等于1。于是根据公式有A=F,即物体的加速度等于力。
因为加速度控制速度,速度控制位置,于是力就是物体运动的起因。
而当考虑质量时,加速度=力/质量。

程序常用的外力有:风力、摩擦力、空气和流体阻力、引力等。

《代码本色》参考案例:
1、制造两个外力:风力和重力。指向不同的方向,大小不相等,同时作用在对象上。
风力和重力
2、流体阻力
物体通过流体或者气体时同样会受摩擦力的作用。流体阻力产生的效果和摩擦力相同(物体会减速),计算阻力公式如下:
在这里插入图片描述
简化公式,以便于Processing模拟: 在这里插入图片描述
设置一块流体区域,该区域内阻力系数与区域外不同,当物体进入区域时,会产生与速度方向相反的阻力。
在这里插入图片描述

Part3 设计思路

参照上述案例一,给窗口中的小球两个力:一个水平力和一个垂直力,力的方向随帧数增加而改变(每500帧)。同时,小球的颜色也每500帧改变一次,可以起到提示用户力的方向发生改变的作用。
参照案例二,设置一个阻力小球,在球体范围内的物体受到阻力的作用。阻力小球的半径随鼠标滚轮变化,位置跟随鼠标移动。
通过该实验可以直观地感受出外力(风力、重力、反重力)对物体的作用,以及阻力对于物体的影响,同时具有较强的交互性,具有一定的趣味性和较好的视觉感受。

Part4 代码实现

①主代码

Mover[] movers = new Mover[9];

Liquid liquid;
int Radius=100;
int t=1;
float H;
void setup() {
  colorMode(HSB, 360, 100, 100, 300);  //颜色模型
  size(640, 360);
  reset();
  liquid = new Liquid(width/2,height/2,50,0.1);  //起始位置,半径,阻力系数
}

void draw() {
  background(360);
  liquid.display();

  for (int i = 0; i < movers.length; i++) {
    if (liquid.contains(movers[i])) {
      PVector dragForce = liquid.drag(movers[i]);
      movers[i].applyForce(dragForce);
    }
    if(frameCount%500==0)   //每隔500帧改变一次力的方向
    {t=-t;
     H=random(360);
     }
     
    PVector wind = new PVector(t*0.01*movers[i].mass,0);
    PVector gravity = new PVector(0, t*0.1*movers[i].mass);
    movers[i].applyForce(wind);
    movers[i].applyForce(gravity);

    movers[i].changeColor(H);
    movers[i].update();
    movers[i].display();
    movers[i].checkEdges();
  }
  
  fill(0);
  text("click mouse to reset", 5, 10);
  text("move mouse to move Drag Ball", 5, 25);
  text("roll mouse to zoom Drag Ball", 5, 40);
}

void mouseWheel(MouseEvent event){
  float e=event.getCount();
  Radius+=e*5;
  liquid = new Liquid(mouseX,mouseY,Radius,0.1);
}

void mouseMoved() {
   liquid = new Liquid(mouseX,mouseY,Radius, 0.1);
}

void mousePressed() {
  reset();
}

void reset() {
  H=random(360);
  for (int i = 0; i < movers.length; i++) {
    movers[i] = new Mover(1, 40+i*70, 0,H);
  }
}

②流体-Liquid类

class Liquid {
  float x, y, r;
  float c;

  Liquid(float x_, float y_, float r_, float c_) {
    x = x_;
    y = y_;
    r = r_;
    c = c_;
  }


  boolean contains(Mover m) {
    PVector l = m.position;
    float d;
    d=sqrt(sq(x-l.x)+sq(y-l.y));
    return d<r+24;        //24为小球半径
  }


  PVector drag(Mover m) {
    float speed = m.velocity.mag();
    float dragMagnitude = c * speed * speed;

    PVector dragForce = m.velocity.get();
    dragForce.mult(-1);
    dragForce.normalize();
    dragForce.mult(dragMagnitude);
    return dragForce;
  }

  void display() {
    noStroke();
    fill(20,200);
    ellipse(x, y, r*2,r*2);
  }
}

③Mover类

class Mover {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float H;
  float mass;

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

  void applyForce(PVector force) {
    PVector f = PVector.div(force, mass);
    acceleration.add(f);
  }

  void update() {
    velocity.add(acceleration);
    position.add(velocity);
    acceleration.mult(0);
  }
  
  void changeColor(float H){
    this.H=H;
  }


  void display() {
    stroke(0);
    strokeWeight(1);
    fill(H,90,50, 200);
    ellipse(position.x, position.y, 48, 48);
  }

  void checkEdges() {

    if (position.x > width) {
      position.x = width;
      velocity.x *= -1;
    } 
    else if (position.x < 0) {
      velocity.x *= -1;
      position.x = 0;
    }

    if (position.y > height) {
      velocity.y *= -1;
      position.y = height;
    }
    else if (position.y < 0) {
      velocity.y *= -1;
      position.y = 0;
    }
  }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!