Шарики двигаются внутри pictereBox-a и отталкиваются от стенок.
Вот как это выглядит
Хочется реализовать ещё и отталкивание шаров друг от друга, но не смог реализовать алгоритм. Помогите если кто сможет.
Код вроде откомментил, если что-то не понятно, спрашивайте
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int kolvo; // Количество шаров, получается из textBoxa
List<int> arr = new List<int>(); // Список с координатами шаров. Четные элементы - координата Х, не четные - У
List<int> spis = new List<int>(); // Список определяющий сколько пикселей пройдет шар за один проход таймера (скорость шара)
private void button3_Click(object sender, EventArgs e)
{
timer1.Enabled = true; // запуск таймера
kolvo = Convert.ToInt32(textBox2.Text) * 2 - 1; // Получение количества элементов массива ( "кол-во шаров" * 2 - 1)
Random r = new Random();
for (int i = 0; i <= kolvo; i++)
{
arr.Add(r.Next(10,300)); // Рандомное создание начальных координат шаров
spis.Add(r.Next(1,10)); // Заполнение списка "скорости" шара
}
}
private void timer1_Tick(object sender, EventArgs e)
{
// Цикл описывающий "отталкивание" шаров от края экрана
for (int i = 0; i < kolvo; i = i + 2)
{
if (arr <= 10) spis = -spis; // Если координата Х <= 10 то меняем направление движения по оси Х на противоположное
if (arr >= pictureBox3.Width-10) spis = -spis;// меняется направление
if (arr[i + 1] <= 10) spis[i + 1] = -spis[i + 1]; // Если координата У <= 10 то меняем направление движения по оси У на противоположное
if (arr[i + 1] >= pictureBox3.Height-10) spis[i+1] = -spis[i+1];
arr += spis; // координаты точки , которая будет удаляться от полюса + текущее смещение шара по оси Х
arr[i + 1] += spis[i+1]; // По оси У
pictureBox3.Invalidate(); // Перерисовка pictureBox-a
}
}
// Функция рисования шаров
void ris(PaintEventArgs e)
{
Graphics rg = e.Graphics;
Pen pen = new Pen(Color.Red);
// Отрисовка шаров
for (int i = 0; i < kolvo; i = i + 2)
{
rg.DrawEllipse(pen, arr - 10, arr[i + 1] - 10, 20, 20);
}
}
private void Paint(object sender, PaintEventArgs e)
{
ris(e); // Вызов функции отрисовки
}
}
}
1. Для каждой пары шариков проверить условие (x2 - x1)^2 + (y2 - y1)^2 <= R (произошло ли соударение).
2. По известным значениям величин скоростей и их направлений вычислить скорости после соударения. В простейшем, опять же, случае, вводятся два приближения: 1) удар абсолютно упругий; и 2) удар центральный. Соответственно, пользуетесь законами сохранения импульса и энергии.
За подробностями обращайтесь в любой курс механики, по теме "Упругие соударения двух тел".
Вот мне интересно,этим ползунком ведь не скорость задаётся,а задержка,да?Обычно минимальное значение слева,а не справа
Вот мне интересно,этим ползунком ведь не скорость задаётся,а задержка,да?Обычно минимальное значение слева,а не справа
Тупо задержка таймера умноженная на value trackBar-a
А не хотите добавить такую характеристику, как массу и упругость шариков? Тогда, мне кажется, процессы соударения (описанные камрадом Alexander92) будут выглядеть на порядок эффектнее.
А не хотите добавить такую характеристику, как массу и упругость шариков? Тогда, мне кажется, процессы соударения (описанные камрадом Alexander92) будут выглядеть на порядок эффектнее.
На самом деле, при соударении роль играют не массы шариков, а их отношение. Так что если все шарики одинаковые, то вводить массу бессмысленно, она все равно посокращается в процессе вычислений. А вот коэффциент упругости действительно ввести можно. :) Только там расчеты получатся сложнее в пару раз.
А кто говорил, что массы одинаковы??? ;)
Нет, ну если ТС хочется ОЧЕНЬ много геморроя, могу предложить ввести разные массы, разные радиусы, рассмотреть нецентральный удар, перевести задачу из 2D в 3D и много чего еще. :D
Это было бы вообще круто. Можно еще отойти от формы идеального шара, да и от вакуума, в котором шарики летают отказаться в пользу более реалистичной среды.... :D
Будем надеяться, что ТС наши идей хоть немного помогут (те, которые были высказаны до моего предыдущего сообщения, когда уже "понесло")!
по вашему совету и делаю, но (x2 - x1)^2 + (y2 - y1)^2 <= R^2
x1 и y1 это координаты центра одной окружности, а x2 и y2 это точка на "поверхности" другой окружности... и как мне её найти?
(x2 - x1)^2 + (y2 - y1)^2 <= (2*R)^2,
то бишь и (x1; y1), и (x2; y2) - координаты центров шариков.
Приведу код для большего понимания
{
for (int j = 0; j < kolvo; j = j + 2)
{
a = arr - arr[j];
b = arr[i+1] - arr[j + 1];
if (Math.Pow(a, 2) + Math.Pow(b, 2) <= Math.Pow(razm,2))
{
spis = -spis;
spis[i + 1] = -spis[i + 1];
}
}
Перед генерацией каждого следующего шарика проверять, что он не оказался внутри какого-то из существующих.
Направления и величины скоростей после соударения расчитываются, исходя из их значений до удара. Еще раз направляю вас к курсу механики, там все прописано. :) Если коротко:
m1 * V1x + m2 * V2x = m1 * u1x + m2 * u1x - закон сохранения импульса
m1 * V1y + m2 * V2y = m1 * u1y + m2 * u2y - закон сохранения импульса
m1 * (V1x^2 + V1y^2) + m2 * (V2x^2 + V2y^2) = m1 * (u1x^2 + u1y^2) + m2 * (u2x^2 + u2y^2) - закон сохранения энергии
V1x, V1y - x- и y-компоненты скорости первого шарика до удара
V2x, V2y - x- и y-компоненты скорости второго шарика до удара
u1x, u1y - x- и y-компоненты скорости первого шарика после удара
u2x, u2y - x- и y-компоненты скорости второго шарика после удара
Переписал полностью, вывел шары в отдельный класс. На данный момент 2 проблемы:
1) Создание шаров "один в другом". Решение с помощью проверки на пересечение при генерации не подходит я думаю, т.к. при большом кол-ве шаров им просто не будет хватать места... нужно что-то другое
2) Так и не смог ничего сделать чтобы шары реалистично отталкивались. Пока тупо отправляются в разные стороны при соударении.
Подскажите как решить это, желательно в виде кода).