Processing:Примеры/Столкновение эллипсов: различия между версиями
Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки |
Myagkij (обсуждение | вклад) Нет описания правки |
||
Строка 1: | Строка 1: | ||
{{Processing панель перехода}} | {{Processing панель перехода}} | ||
{{Перевод от Сubewriter}} | {{Перевод от Сubewriter}} | ||
{{Myagkij-редактор}} | {{Myagkij-редактор}} | ||
=Описание<ref>[https://processing.org/examples/circlecollision.html processing.org - Circle Collision with Swapping Velocities by Ira Greenberg]</ref>= | =Описание<ref>[https://processing.org/examples/circlecollision.html processing.org - Circle Collision with Swapping Velocities by Ira Greenberg]</ref>= | ||
Строка 348: | Строка 345: | ||
<references /> | <references /> | ||
{{Навигационная таблица/Портал/Processing}} | {{Навигационная таблица/Портал/Processing}} |
Текущая версия от 07:54, 27 августа 2023
Содержание | Среда разработки Processing | Справочник языка Processing | Библиотеки | Примеры | Режимы программирования |
Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.
Описание[1]
Этот скетч-пример основан на примере из книги «Основы анимации с помощью AutoScript: Двигай это!» Кита Питерса.
Пример
Ball[] balls = {
new Ball(100, 400, 20),
new Ball(700, 400, 80)
};
void setup() {
size(640, 360);
}
void draw() {
background(51);
for (Ball b : balls) {
b.update();
b.display();
b.checkBoundaryCollision();
}
balls[0].checkCollision(balls[1]);
}
class Ball {
PVector position;
PVector velocity;
float radius, m;
Ball(float x, float y, float r_) {
position = new PVector(x, y);
velocity = PVector.random2D();
velocity.mult(3);
radius = r_;
m = radius*.1;
}
void update() {
position.add(velocity);
}
void checkBoundaryCollision() {
if (position.x > width-radius) {
position.x = width-radius;
velocity.x *= -1;
} else if (position.x < radius) {
position.x = radius;
velocity.x *= -1;
} else if (position.y > height-radius) {
position.y = height-radius;
velocity.y *= -1;
} else if (position.y < radius) {
position.y = radius;
velocity.y *= -1;
}
}
void checkCollision(Ball other) {
// считываем расстояние между эллипсами:
PVector distanceVect = PVector.sub(other.position, position);
// рассчитываем длину вектора, разделяющего эллипсы:
float distanceVectMag = distanceVect.mag();
// минимальное расстояние до столкновения эллипсов:
float minDistance = radius + other.radius;
if (distanceVectMag < minDistance) {
float distanceCorrection = (minDistance-distanceVectMag)/2.0;
PVector d = distanceVect.copy();
PVector correctionVector = d.normalize().mult(distanceCorrection);
other.position.add(correctionVector);
position.sub(correctionVector);
// считываем угол «distanceVect»:
float theta = distanceVect.heading();
// заранее рассчитываем тригонометрические значения:
float sine = sin(theta);
float cosine = cos(theta);
/* Массив «bTemp» будет хранить позиции вращающихся эллипсов.
Вас должна волновать лишь позиция bTemp[1] */
PVector[] bTemp = {
new PVector(), new PVector()
};
/* Это позиция второго эллипса относительно позиции первого,
поэтому вы можете использовать вектор между ними (bVect)
в качестве ориентира для уравнений,
с помощью которых осуществляется расчет вращения.
«bTemp[0].position.x» и «bTemp[0].position.y»
будут автоматически инициализированы со значением «0.0»,
и это то как раз, что нужно, потому что эллипс b[1]
будет вращаться вокруг эллипса b[0]. */
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
// меняем предварительные углы направления векторов:
PVector[] vTemp = {
new PVector(), new PVector()
};
vTemp[0].x = cosine * velocity.x + sine * velocity.y;
vTemp[0].y = cosine * velocity.y - sine * velocity.x;
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
/* Теперь, когда углы направления векторов изменены,
можно воспользоваться 1D-преобразованием уравнений импульса
для расчета финальных углов направления векторов по оси X. */
PVector[] vFinal = {
new PVector(), new PVector()
};
// финальный угол направления вектора для эллипса b[0]:
vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
vFinal[0].y = vTemp[0].y;
// финальный угол направления вектора для эллипса b[1]:
vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m);
vFinal[1].y = vTemp[1].y;
// небольшой трюк, чтобы избежать комкования:
bTemp[0].x += vFinal[0].x;
bTemp[1].x += vFinal[1].x;
/* Инвертируем позиции эллипсов и углы направления векторов
при помощи тригонометрических уравнений. */
// вращаем эллипсы:
PVector[] bFinal = {
new PVector(), new PVector()
};
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
// обновляем позиции эллипсов на экране:
other.position.x = position.x + bFinal[1].x;
other.position.y = position.y + bFinal[1].y;
position.add(bFinal[0]);
// обновляем углы направления векторов:
velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
}
}
void display() {
noStroke();
fill(204);
ellipse(position.x, position.y, radius*2, radius*2);
}
}
См.также
Внешние ссылки
Примеры на Processing | |
---|---|
Основы |
|
Продвинутые графические эффекты |
|
Примеры из сторонних библиотек |