Processing:Примеры/Неперпендикулярное отражение 2
Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Содержание | Среда разработки Processing | Справочник языка Processing | Библиотеки | Примеры | Режимы программирования |
Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.
Описание[1]
Этот скетч-пример основан на примере из книги «Основы анимации с помощью AutoScript: Двигай это!» Кита Питерса.
Пример
Orb orb;
PVector gravity = new PVector(0,0.05);
// «земля» - это массив объектов «Ground»:
int segments = 40;
Ground[] ground = new Ground[segments];
void setup(){
size(640, 360);
// объект «orb», который будет падать и отскакивать от поверхности:
orb = new Orb(50, 50, 3);
// рассчитываем высоту «гор»:
float[] peakHeights = new float[segments+1];
for (int i=0; i<peakHeights.length; i++){
peakHeights[i] = random(height-40, height-30);
}
/* Значение «segs» типа «float» необходимо
для расчета ширины «гор», чтобы «земля» растянулась
на весь экран независимо от количества «гор». */
float segs = segments;
for (int i=0; i<segments; i++){
ground[i] = new Ground(width/segs*i, peakHeights[i], width/segs*(i+1), peakHeights[i+1]);
}
}
void draw(){
// фон:
noStroke();
fill(0, 15);
rect(0, 0, width, height);
// перемещаем и показываем шар:
orb.move();
orb.display();
// проверяем, сталкивается ли шар с границами экрана:
orb.checkWallCollision();
// проверяем, сталкивается ли шар с «горами»:
for (int i=0; i<segments; i++){
orb.checkGroundCollision(ground[i]);
}
// рисуем «землю»:
fill(127);
beginShape();
for (int i=0; i<segments; i++){
vertex(ground[i].x1, ground[i].y1);
vertex(ground[i].x2, ground[i].y2);
}
vertex(ground[segments-1].x2, height);
vertex(ground[0].x1, height);
endShape(CLOSE);
}
class Orb {
// у шара есть позиция и направление движения:
PVector position;
PVector velocity;
float r;
// скорость шара будет замедляться на 20%
// после столкновения с «землей»:
float damping = 0.8;
Orb(float x, float y, float r_) {
position = new PVector(x, y);
velocity = new PVector(.5, 0);
r = r_;
}
void move() {
// перемещаем шар:
velocity.add(gravity);
position.add(velocity);
}
void display() {
// рисуем шар:
noStroke();
fill(200);
ellipse(position.x, position.y, r*2, r*2);
}
// проверяем, сталкивается ли шар с границами экрана:
void checkWallCollision() {
if (position.x > width-r) {
position.x = width-r;
velocity.x *= -damping;
}
else if (position.x < r) {
position.x = r;
velocity.x *= -damping;
}
}
void checkGroundCollision(Ground groundSegment) {
// считываем расстояние между шаром и «землей»:
float deltaX = position.x - groundSegment.x;
float deltaY = position.y - groundSegment.y;
// заранее рассчитываем тригонометрические значения:
float cosine = cos(groundSegment.rot);
float sine = sin(groundSegment.rot);
/* Определяем углы склонов «гор»
и направление движения шара,
чтобы рассчитать их столкновение. */
float groundXTemp = cosine * deltaX + sine * deltaY;
float groundYTemp = cosine * deltaY - sine * deltaX;
float velocityXTemp = cosine * velocity.x + sine * velocity.y;
float velocityYTemp = cosine * velocity.y - sine * velocity.x;
/* Столкновение с «землей»:
определяем, есть ли столкновение с поверхностью,
а также то, находится ли шар
в пределах левого/правого края «горы». */
if (groundYTemp > -r &&
position.x > groundSegment.x1 &&
position.x < groundSegment.x2 ) {
// не даем шару провалиться под «землю»:
groundYTemp = -r;
// выполняем отскок и замедление шара:
velocityYTemp *= -1.0;
velocityYTemp *= damping;
}
// обновляем значения для расстояния между шаром и «землей»,
// а также для направления движения и позиции шара:
deltaX = cosine * groundXTemp - sine * groundYTemp;
deltaY = cosine * groundYTemp + sine * groundXTemp;
velocity.x = cosine * velocityXTemp - sine * velocityYTemp;
velocity.y = cosine * velocityYTemp + sine * velocityXTemp;
position.x = groundSegment.x + deltaX;
position.y = groundSegment.y + deltaY;
}
}
class Ground {
float x1, y1, x2, y2;
float x, y, len, rot;
// конструктор:
Ground(float x1, float y1, float x2, float y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
x = (x1+x2)/2;
y = (y1+y2)/2;
len = dist(x1, y1, x2, y2);
rot = atan2((y2-y1), (x2-x1));
}
}
См.также
Внешние ссылки
Примеры на Processing | |
---|---|
Основы |
|
Продвинутые графические эффекты |
|
Примеры из сторонних библиотек |