Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Processing:Примеры/Неперпендикулярное отражение 2

Материал из Онлайн справочника
Перейти к: навигация, поиск


Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

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


Ambox content.png Черновик


Описание[1]

Этот скетч-пример основан на примере из книги «Основы анимации с помощью AutoScript: Двигай это!» Кита Питерса.

Пример

  1. Orb orb;
  2.  
  3. PVector gravity = new PVector(0,0.05);
  4. // «земля» - это массив объектов «Ground»:
  5. int segments = 40;
  6. Ground[] ground = new Ground[segments];
  7.  
  8. void setup(){
  9.   size(640, 360);
  10.   // объект «orb», который будет падать и отскакивать от поверхности:
  11.   orb = new Orb(50, 50, 3);
  12.  
  13.   // рассчитываем высоту «гор»:
  14.   float[] peakHeights = new float[segments+1];
  15.   for (int i=0; i<peakHeights.length; i++){
  16.     peakHeights[i] = random(height-40, height-30);
  17.   }
  18.  
  19.   /* Значение «segs» типа «float» необходимо
  20.      для расчета ширины «гор», чтобы «земля» растянулась
  21.      на весь экран независимо от количества «гор». */
  22.   float segs = segments;
  23.   for (int i=0; i<segments; i++){
  24.     ground[i]  = new Ground(width/segs*i, peakHeights[i], width/segs*(i+1), peakHeights[i+1]);
  25.   }
  26. }
  27.  
  28.  
  29. void draw(){
  30.   // фон:
  31.   noStroke();
  32.   fill(0, 15);
  33.   rect(0, 0, width, height);
  34.  
  35.   // перемещаем и показываем шар:
  36.   orb.move();
  37.   orb.display();
  38.   // проверяем, сталкивается ли шар с границами экрана:
  39.   orb.checkWallCollision();
  40.  
  41.   // проверяем, сталкивается ли шар с «горами»:
  42.   for (int i=0; i<segments; i++){
  43.     orb.checkGroundCollision(ground[i]);
  44.   }
  45.  
  46. // рисуем «землю»:
  47.   fill(127);
  48.   beginShape();
  49.   for (int i=0; i<segments; i++){
  50.     vertex(ground[i].x1, ground[i].y1);
  51.     vertex(ground[i].x2, ground[i].y2);
  52.   }
  53.   vertex(ground[segments-1].x2, height);
  54.   vertex(ground[0].x1, height);
  55.   endShape(CLOSE);
  56. }
  57.  
  58.  
  59.  
  60. class Orb {
  61.   // у шара есть позиция и направление движения:
  62.   PVector position;
  63.   PVector velocity;
  64.   float r;
  65.   // скорость шара будет замедляться на 20%
  66.   // после столкновения с «землей»:
  67.   float damping = 0.8;
  68.  
  69.   Orb(float x, float y, float r_) {
  70.     position = new PVector(x, y);
  71.     velocity = new PVector(.5, 0);
  72.     r = r_;
  73.   }
  74.  
  75.   void move() {
  76.     // перемещаем шар:
  77.     velocity.add(gravity);
  78.     position.add(velocity);
  79.   }
  80.  
  81.   void display() {
  82.     // рисуем шар:
  83.     noStroke();
  84.     fill(200);
  85.     ellipse(position.x, position.y, r*2, r*2);
  86.   }
  87.  
  88.   // проверяем, сталкивается ли шар с границами экрана:
  89.   void checkWallCollision() {
  90.     if (position.x > width-r) {
  91.       position.x = width-r;
  92.       velocity.x *= -damping;
  93.     }
  94.     else if (position.x < r) {
  95.       position.x = r;
  96.       velocity.x *= -damping;
  97.     }
  98.   }
  99.  
  100.   void checkGroundCollision(Ground groundSegment) {
  101.  
  102.     // считываем расстояние между шаром и «землей»:
  103.     float deltaX = position.x - groundSegment.x;
  104.     float deltaY = position.y - groundSegment.y;
  105.  
  106.     // заранее рассчитываем тригонометрические значения:
  107.     float cosine = cos(groundSegment.rot);
  108.     float sine = sin(groundSegment.rot);
  109.  
  110.     /* Определяем углы склонов «гор»
  111.        и направление движения шара,
  112.        чтобы рассчитать их столкновение. */
  113.     float groundXTemp = cosine * deltaX + sine * deltaY;
  114.     float groundYTemp = cosine * deltaY - sine * deltaX;
  115.     float velocityXTemp = cosine * velocity.x + sine * velocity.y;
  116.     float velocityYTemp = cosine * velocity.y - sine * velocity.x;
  117.  
  118.     /* Столкновение с «землей»:
  119.      определяем, есть ли столкновение с поверхностью,
  120.      а также то, находится ли шар
  121.      в пределах левого/правого края «горы». */
  122.     if (groundYTemp > -r &&
  123.       position.x > groundSegment.x1 &&
  124.       position.x < groundSegment.x2 ) {
  125.       // не даем шару провалиться под «землю»:
  126.       groundYTemp = -r;
  127.       // выполняем отскок и замедление шара:
  128.       velocityYTemp *= -1.0;
  129.       velocityYTemp *= damping;
  130.     }
  131.  
  132.     // обновляем значения для расстояния между шаром и «землей»,
  133.     // а также для направления движения и позиции шара:
  134.     deltaX = cosine * groundXTemp - sine * groundYTemp;
  135.     deltaY = cosine * groundYTemp + sine * groundXTemp;
  136.     velocity.x = cosine * velocityXTemp - sine * velocityYTemp;
  137.     velocity.y = cosine * velocityYTemp + sine * velocityXTemp;
  138.     position.x = groundSegment.x + deltaX;
  139.     position.y = groundSegment.y + deltaY;
  140.   }
  141. }
  142.  
  143. class Ground {
  144.   float x1, y1, x2, y2;  
  145.   float x, y, len, rot;
  146.  
  147.   // конструктор:
  148.   Ground(float x1, float y1, float x2, float y2) {
  149.     this.x1 = x1;
  150.     this.y1 = y1;
  151.     this.x2 = x2;
  152.     this.y2 = y2;
  153.     x = (x1+x2)/2;
  154.     y = (y1+y2)/2;
  155.     len = dist(x1, y1, x2, y2);
  156.     rot = atan2((y2-y1), (x2-x1));
  157.   }
  158. }

См.также

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

  1. processing.org - Non-orthogonal Collision with Multiple Ground Segments by Ira Greenberg.