Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Шарики двигаются внутри pictereBox-a и отталкиваются от стенок.

68K
22 июня 2011 года
RiGs
11 / / 22.06.2011
Балуясь, написал программульку. Шарики двигаются внутри pictereBox-a и отталкиваются от стенок.
Вот как это выглядит

Хочется реализовать ещё и отталкивание шаров друг от друга, но не смог реализовать алгоритм. Помогите если кто сможет.
Код вроде откомментил, если что-то не понятно, спрашивайте
Код:
using System;
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); // Вызов функции отрисовки
        }  
 
    }
}
278
22 июня 2011 года
Alexander92
1.1K / / 04.08.2008
Задача интересная, на самом деле. Прежде всего, потому что потенциально в каждый момент времени может сталкиваться не два шарика, а больше (в химической кинетике, к примеру, эта задача приводит к такому понятию, как порядок химической реакции). В простейшей модели (когда шариков немного) можно ограничиться действительно взаимодействием только двух шариков. Соответственно, самый простой алгоритм (без оптимизации) выглядит следующим образом:
1. Для каждой пары шариков проверить условие (x2 - x1)^2 + (y2 - y1)^2 <= R (произошло ли соударение).
2. По известным значениям величин скоростей и их направлений вычислить скорости после соударения. В простейшем, опять же, случае, вводятся два приближения: 1) удар абсолютно упругий; и 2) удар центральный. Соответственно, пользуетесь законами сохранения импульса и энергии.
За подробностями обращайтесь в любой курс механики, по теме "Упругие соударения двух тел".
7
22 июня 2011 года
@pixo $oft
3.4K / / 20.09.2006
«Скорость: Max…Min»
Вот мне интересно,этим ползунком ведь не скорость задаётся,а задержка,да?Обычно минимальное значение слева,а не справа
68K
22 июня 2011 года
RiGs
11 / / 22.06.2011
Цитата: @pixo $oft
«Скорость: Max…Min»
Вот мне интересно,этим ползунком ведь не скорость задаётся,а задержка,да?Обычно минимальное значение слева,а не справа



Тупо задержка таймера умноженная на value trackBar-a

416
23 июня 2011 года
MaitreDesir
380 / / 02.01.2008
Совет по "юзабилити" - поменяй мин и макс местами, а умножай задержку таймера не на TrackBar.Value, а на TrackBar.Max-TrackBar.Value.
А не хотите добавить такую характеристику, как массу и упругость шариков? Тогда, мне кажется, процессы соударения (описанные камрадом Alexander92) будут выглядеть на порядок эффектнее.
278
23 июня 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: MaitreDesir

А не хотите добавить такую характеристику, как массу и упругость шариков? Тогда, мне кажется, процессы соударения (описанные камрадом Alexander92) будут выглядеть на порядок эффектнее.


На самом деле, при соударении роль играют не массы шариков, а их отношение. Так что если все шарики одинаковые, то вводить массу бессмысленно, она все равно посокращается в процессе вычислений. А вот коэффциент упругости действительно ввести можно. :) Только там расчеты получатся сложнее в пару раз.

416
30 июня 2011 года
MaitreDesir
380 / / 02.01.2008
Цитата: Alexander92
Так что если все шарики одинаковые, то вводить массу бессмысленно, она все равно посокращается в процессе вычислений.



А кто говорил, что массы одинаковы??? ;)

278
30 июня 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: MaitreDesir
А кто говорил, что массы одинаковы??? ;)



Нет, ну если ТС хочется ОЧЕНЬ много геморроя, могу предложить ввести разные массы, разные радиусы, рассмотреть нецентральный удар, перевести задачу из 2D в 3D и много чего еще. :D

416
30 июня 2011 года
MaitreDesir
380 / / 02.01.2008
Цитата: Alexander92
Нет, ну если ТС хочется ОЧЕНЬ много геморроя, могу предложить ввести разные массы, разные радиусы, рассмотреть нецентральный удар, перевести задачу из 2D в 3D и много чего еще. :D



Это было бы вообще круто. Можно еще отойти от формы идеального шара, да и от вакуума, в котором шарики летают отказаться в пользу более реалистичной среды.... :D
Будем надеяться, что ТС наши идей хоть немного помогут (те, которые были высказаны до моего предыдущего сообщения, когда уже "понесло")!

5
30 июня 2011 года
hardcase
4.5K / / 09.08.2005
Вы еще вращение шаров забыли, а оно также немало влияет.
68K
02 июля 2011 года
RiGs
11 / / 22.06.2011
Ну вы даете.... я тут думаю как сделать чтобы при соударении они просто отлетали в разные стороны, а вы...
278
02 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Ну по сабжу - читайте мой первый ответ, дальше "понесло".=)
68K
03 июля 2011 года
RiGs
11 / / 22.06.2011
Цитата: Alexander92
Ну по сабжу - читайте мой первый ответ, дальше "понесло".=)



по вашему совету и делаю, но (x2 - x1)^2 + (y2 - y1)^2 <= R^2
x1 и y1 это координаты центра одной окружности, а x2 и y2 это точка на "поверхности" другой окружности... и как мне её найти?

278
03 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Я прошу прощения, вышла маленькая опечатка. Имелось в виду
(x2 - x1)^2 + (y2 - y1)^2 <= (2*R)^2,
то бишь и (x1; y1), и (x2; y2) - координаты центров шариков.
68K
03 июля 2011 года
RiGs
11 / / 22.06.2011
Почти сделал, единственная проблема: у меня координаты центра хранятся в массиве arr, где четные элементы это координаты X, а не четные - Y. Так вот при прохождении массива и вычитании координат 2-х шаров arr и arr[j] как избежать операцию с одним и тем же шаром? То есть когда j-тый элемент это и есть i-тый элемент. Надеюсь понятно объяснил.

Приведу код для большего понимания

Код:
for (int i = 0; i < kolvo; i = i + 2)
            {
                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];
                    }
                }
68K
03 июля 2011 года
RiGs
11 / / 22.06.2011
Решил. Ввел проверку i!=j. заработало наконец. теперь появилось ещё 2 проблемы: как быть если в самом начале программы шарики генерируются "один в другом" и в какую сторону направлять их после соударения. тупо в противоположную сторону как-то не то
278
03 июля 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: RiGs
как быть если в самом начале программы шарики генерируются "один в другом"


Перед генерацией каждого следующего шарика проверять, что он не оказался внутри какого-то из существующих.

Цитата: RiGs
в какую сторону направлять их после соударения


Направления и величины скоростей после соударения расчитываются, исходя из их значений до удара. Еще раз направляю вас к курсу механики, там все прописано. :) Если коротко:

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-компоненты скорости второго шарика после удара

7
03 июля 2011 года
@pixo $oft
3.4K / / 20.09.2006
Кстати,рекомендую унифицировать проверку на непересечение шариков в одну функцию Collide.Тогда можно и при генерации,и уже при отображении пользоваться одной и той же функцией и не городить одинаковый код
68K
08 июля 2011 года
RiGs
11 / / 22.06.2011
Вот выкладываю прогу в текущем состоянии. [ATTACH]5219[/ATTACH]
Переписал полностью, вывел шары в отдельный класс. На данный момент 2 проблемы:
1) Создание шаров "один в другом". Решение с помощью проверки на пересечение при генерации не подходит я думаю, т.к. при большом кол-ве шаров им просто не будет хватать места... нужно что-то другое
2) Так и не смог ничего сделать чтобы шары реалистично отталкивались. Пока тупо отправляются в разные стороны при соударении.
Подскажите как решить это, желательно в виде кода).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог