Здравствуйте, Нomunculus, Вы писали:
Н>Ну что мы в объект тряпки сунем? Ну, очевидно, какие-то физические и геометрические свойства, размеры, массу, плотность, гибкость и так далее. Все это — внутри тряпки. Шикарно и инкапсуляшно.
Это если заниматься инкапсулизмом. А для ООП нужно определиться, какое решение будете моделивать. Т.е. вам нужна вычислительная модель до, а не после.
Какое состояние, какие методы должен поддерживать этот класс зависит от того, как вы смоделировали решение. Например, это может быть двумерный или трехмерный массив точек и дополнительные параметры. А ветер это будет свойство сцены.
Н>Неужели в каждой тряпке должна быть ссылка на сцену? Мы каждой тряпке должны это указывать? Н>Не, разумеется, проблемы нет. Но блин чо-то вся красота ООП-ти летит в задницу. В реальности тряпки не знают ничего про то, где они находятся.
Здравствуйте, Osaka, Вы писали:
Н>>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР??? O>Тряпка состоит из Molecule[], которые .Impact(молекула ветра), после чего тряпка пересчитывает свою геометрию.
Как будет пересчитываться геометрия — нужно определиться до того, как вводим объекты ветер и тряпка. А когда определились — тогда и вводим абстракции.
Может окажется так, что не будет никакой тряпки, а будет просто игровой объект с капабилити 'точки' и 'свойства', его мы отдаем калькулятору геометрии, и применяем полученные изменения.
Здравствуйте, Нomunculus, Вы писали:
Н>>>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР??? O>>Тряпка состоит из Molecule[], которые .Impact(молекула ветра), после чего тряпка пересчитывает свою геометрию.
Н>То есть при смене направления ветра мы должны каждой тряпке это сказать?
А как вы хотели? Если тряпка из молекул, то нужно пересчитать геометрию.
Здравствуйте, Нomunculus, Вы писали:
Н>Вопрос в том кто про что должен знать. Расчеты трепыхания тряпки должны быть внутри тряпки? Но тогда тряпка должна знать о внешнем мире. И это криво
Это зависит от вашего решения. На самом деле важно решение с минимальной сложностью и высокой maintainability.
Простые вычисления ветра и никто кроме тряпки с ветром не взаимодействует — суньте в тряпку.
Появятся еще объекты, которые гнутся под ветром — добавьте класс ветер.
Вычисления сложные, типа дифуры, новье-стокса — выделите класс WindCalculator, а тряпка и ветер будут просто набор капабилитей.
Можно даже сделать тряпку тряпкой, и не хранить в ней никаких точек, пусть отрисовывается полу-рандомный трепыхающийся объект. Тоже как вариант.
Важно, что у вас пока нет решения, а вы уже инкапсулизмом занимаетесь
Место ООП — перевод готового решения в код и управление сложностью итогового кода.
Здравствуйте, Osaka, Вы писали:
Н>>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР??? O>Тряпка состоит из Molecule[], которые .Impact(молекула ветра), после чего тряпка пересчитывает свою геометрию.
Опасный совет — щас он пронаследует молекулу, у нас же ООП — значит надо всё от всего наследовать, впихнет туда через DI сто зависимостей, и скажет что де идея не палит, т.к. модель не влазит в память.
Здравствуйте, Нomunculus, Вы писали: Н>Где ж нам взять ветер? Ведь это должно быть свойство сцены. И если в сцене миллион тряпок, то поменяв одну единственную цифирьку в векторе направления ветра, все миллион тряпок должны начать двигаться иначе.
ветер сам по себе сложный обьект. это поле — то бишь 3д вектор в каждый точке, который как-то меняется со временем. он может, например, уметь интерполирвать между известными точными знаниями чтобы не держать вектор для точки или просто сбрасываться в константу везде. и доступ к нему можно да просто через синглтон сделать, если неохота никуда пробрасывать. вот и вся проблема.
тряпка имеет геометрию и свойства геометрии. есть физический движок, который умеет геометрию обсчитывать с учетом того же ветра. сама тряпка ничего не считает
Тряпка это физическая система, в ней есть внутренние процессы, есть процессы вызванные внешними (граничиными) силами/условиями. Ветер одно из них, другое может быть человек, который эту тряпку носит или солнце, которое ее сушит в каких-то местах и вызывает градиент плотности (в первом приближении), от чего происходит какая-то динамика. Соответственно, ветер в каком-то сцен менеджере проходится по всем тряпкам и, если взаимодействует с ними, выставляя скорости / импульсы частиц/треугольников, с которыми он взамодействует.
Здравствуйте, Нomunculus, Вы писали:
Н>Вот проектируем мы объект, все чтоб по красоте было, удобно, инкапсуляшно, ооп-шно.
Н>А объект этот — тряпка. Не в смысле слабохарактерного мужчины, а в прямом смысле — кусок ткани. Н>И хотим мы чтоб тряпка эта была ну прям как взаправдышная
Н>Ну что мы в объект тряпки сунем? Ну, очевидно, какие-то физические и геометрические свойства, размеры, массу, плотность, гибкость и так далее. Все это — внутри тряпки. Шикарно и инкапсуляшно.
Н>Далее для физической симуляции тряпки мы понимаем, что нам нужен… ВЕТЕР!! Но ветер блин вообще нифига не в тряпке. А без ветра вся физическая симуляция превращается в обвисшее недоразумение.
Н>Где ж нам взять ветер? Ведь это должно быть свойство сцены. И если в сцене миллион тряпок, то поменяв одну единственную цифирьку в векторе направления ветра, все миллион тряпок должны начать двигаться иначе.
Н>Неужели в каждой тряпке должна быть ссылка на сцену? Мы каждой тряпке должны это указывать? Н>Не, разумеется, проблемы нет. Но блин чо-то вся красота ООП-ти летит в задницу. В реальности тряпки не знают ничего про то, где они находятся.
Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Здравствуйте, Нomunculus, Вы писали:
Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Потому что объекты реального мира это не всегда реальные классы. Тряпка описывается некоторыми точками в пространстве, а ветер это некоторый алгоритм трансформаций над этими точками. В принципе, это может быть отдельный класс, а может быть и простая функция.
Некоторый псевдокод
class Tryapka:
vector dots
color c = RED
transform(Transformation as alg) -> bool
foreach dot in dots
alg(dot)
class Veter implements Transformation:
define call(dot)
apply dx, dy on dot
main -> void
Transformation alg = Veter(2m/s)
Tryapka traypka
traypka.transform(alg)
Можно не использовать Veter как класс, а просто как функцию которая принимает массив точек. В сложном случае всё скатится до двойной диспетчеризации и шаблона Visitor
P.S.Поищи сообщения Sinclar, он много дельного писал на тему ООП.
Здравствуйте, Нomunculus, Вы писали:
Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Ооо, опять земля.копайся.
Нет у вас никакого объекта "тряпка". И объекта "ветер" тоже нет.
ООП — оно про обязанности и поведение.
Поведение в данном случае одно: по состоянию мира в момент времени T и промежутку t построить состояние мира в момент времени T+t.
Всё. Физика именно так и работает. Флаг не обменивается никакими сообщениями с ветром и флагштоком.
Если вы посмотрите внутрь ПО по моделированию физических процессов (вроде https://www.comsol.com/), то там предмет исследования не будет ООП-объектом.
Так что если вы хотите моделировать поведение флага в окружающей среде — то надо физику.
А если вас интересуют практические вещи, то "физика" у вас будет ограничена набором макро-правил.
Очень хорошая серия на эту тему есть у Эрика Липперта.
То есть опять же, не будет у флага метода "отреагировать на ветер".
У вас будет набор правил вида "под действием ВЕТРА тканевые объекты начинают развеваться", "мокрые объекты не могут развеваться", "под воздействием ВОДЫ тканевые объекты становятся мокрыми".
Каждое правило будет объектом определённого класса; у вас будет тот самый главный GodObject, который трансформирует мир под действием этих правил.
Так что если игрок кастует "заклинание штормового ветра", в локации начинает "действовать ВЕТЕР" и срабатывают все правила про действие ветра на все предметы.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Нomunculus, Вы писали: Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Я всегда всем говорю, что в программировании мозгов не нужно, но все упорно это отрицают и пытаются умствовать. Программирование это как чукотская песня — что вижу, то и пою. Если у тебя ветер не вписывается в тряпку, значит модель не полна и ее нужно дополнять. Дополняем модель какой-нибудь фигней, которая сломает существующее положение дел и смотрим.
В данном случае дополняем модель двумя параллельными близко стоящими зданиями и перпендикулярным им ветром. Даже чукче понятно, что каков бы не был ветер в сцене, между домами он параллелен домам. Соответственно нужный нам для тряпки ветер это не ветер сцены, а свойство точки на сцене. Собственно, как и тряпка.
Всё, что нас не убивает, ещё горько об этом пожалеет.
Здравствуйте, Sinclair, Вы писали:
S>То есть опять же, не будет у флага метода "отреагировать на ветер".
Но флаг как некоторый объект в мире будет присутствовать или это будет набор данных который задаёт геометрические параметры внутри сцены?
Здравствуйте, Нomunculus, Вы писали:
Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Куда суётся — туда и суйте Вы формулируете вопрос таким образом, как будто есть сложности с поиском решения. На самом деле проблема с вашей постановкой задачи. Процесс дизайна — это построение системы неравенств, которая описывает разные аспекты "как мы точно делать не будем". Чем больше требований, тем больше неравенств, тем более чёткая картина получается. В какой-то момент всё приходит к тому, что в систему укладывается буквально полтора решения, плюсы и минусы которых совсем не очевидны — и из которых можно выбрать любое.
Требования, которые нужно учитывать — это и критерий успеха (как выглядит успех, сколько времени займёт решение, уложимся ли в бюджет), и жизненный цикл (это мы развлекаемся за завтраком — и дальше всё, или пишем коммерческий игровой движок, который нужно будет поддерживать и развивать), и т.д. И где-то там на 1482-м месте технические вопросы типа "знает ли тряпка про ветер, или ветер про тряпку"
Есть более простая задача — при объектно-ориентированном дизайне геометрических фигур — должен ли прямоугольник наследоваться от квадрата, или квадрат от прямоугольника, или никто ни от кого?
Здравствуйте, Kernan, Вы писали: K>Но флаг как некоторый объект в мире будет присутствовать или это будет набор данных который задаёт геометрические параметры внутри сцены?
В упрощённой модели — будет. Но это будет "anemic object", просто коллекция свойств с наследованием. То есть, флаг будет относиться к "тканевым объектам", а меч — к "оружию".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Нomunculus, Вы писали:
Н>Вот проектируем мы объект, все чтоб по красоте было, удобно, инкапсуляшно, ооп-шно. Н>А объект этот — тряпка. Не в смысле слабохарактерного мужчины, а в прямом смысле — кусок ткани. Н>И хотим мы чтоб тряпка эта была ну прям как взаправдышная Н>Ну что мы в объект тряпки сунем? Ну, очевидно, какие-то физические и геометрические свойства, размеры, массу, плотность, гибкость и так далее. Все это — внутри тряпки. Шикарно и инкапсуляшно.
Н>Далее для физической симуляции тряпки мы понимаем, что нам нужен… ВЕТЕР!! Но ветер блин вообще нифига не в тряпке. А без ветра вся физическая симуляция превращается в обвисшее недоразумение. Н>Где ж нам взять ветер? Ведь это должно быть свойство сцены. И если в сцене миллион тряпок, то поменяв одну единственную цифирьку в векторе направления ветра, все миллион тряпок должны начать двигаться иначе. Н>Неужели в каждой тряпке должна быть ссылка на сцену? Мы каждой тряпке должны это указывать? Н>Не, разумеется, проблемы нет. Но блин чо-то вся красота ООП-ти летит в задницу. В реальности тряпки не знают ничего про то, где они находятся. Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Да вроде ничего сложного с ветром
using System.Collections.Generic;
using System.Numerics;
interface ISumulation
{
void Step();
}
abstract class BasePhysicalObject: ISumulation
{
public Vector3 Position { get; protected set; }
public float Mass { get; }
Matrix4x4 positionTransform = Matrix4x4.Identity;
protected void AddPositionTransform(Matrix4x4 transform)
{
positionTransform = positionTransform * transform;
}
public abstract void ApplyWind(Vector3 wind);
public void Step()
{
Position = Vector3.Transform(Position, positionTransform);
}
}
class Rag: BasePhysicalObject
{
public override void ApplyWind(Vector3 wind)
{
this.AddPositionTransform(/* преобразование ветра в нужную матрицу в зависимости от позиции, массы и всего остального*/);
}
}
class SimulationEnvironment: ISumulation
{
private List<BasePhysicalObject> objects = new();
public IReadOnlyList<BasePhysicalObject> Objects => objects.AsReadOnly();
public Vector3 Wind { get; set; }
public void AddObject(BasePhysicalObject o) => objects.Add(o);
public void Step()
{
foreach (var o in objects)
{
// ...
o.ApplyWind(Wind);
// ...
o.Step();
}
}
}
Как раз задачи симуляции независимых объектов решаются хорошо в рамках ООП.
плохо начинается тогда, когда надо в рамках "сцены" взаимодействовать между собой. Например в рамках симуляции надо просчитывать коллизии. Этот расчет будет разным в зависимости от разных пары типов объектов в сцене. Причем сам расчет будет зависеть от некоторых внутренних свойств объектов. В классическом Java-подобном ООП это красиво никак не сделать. Или визиторы городить, или код копипастить.
В современном C# это можно сделать с помощью паттерн-матчинга, но все равно накладывает ограничения на изменения типов объектов в будущем (ломает принцип OCP).
Здравствуйте, Нomunculus, Вы писали:
Н>Вопрос на миллион — КУДА СУНУТЬ ВЕТЕР???
Точно не в тряпку иначе ты приходишь к тому, что ветер потому, что листья на деревьях шевелятся.
Здравствуйте, Нomunculus, Вы писали:
Н>То есть при смене направления ветра мы должны каждой тряпке это сказать?
А почему нет? Свойства тряпки — это её текстура (цвет, фактура волокон, всякие пятна-дырки-подпалины). А вот ветер уже является модификатором. Причем если упороться по архитектуре, то модификатор не будет сам менять тряпку, ведь источников ветра может быть несколько: ветер природный (ambient), его отражение от препятствий на сцене, локальный ветер от вентилятора, который есть на нашей сцене (или винт самолёта, турбина и т.п.). Будет внешний объект-композер, который сможет посчитать равнодействующую этих модификаторов и применить к тряпке (и тут мы можем разделить отдельно модели, и отдельно вью-модели той же тряпки, ветра и т.п.)
Здравствуйте, alpha21264, Вы писали:
A>Ветер должен быть методом объекта тряпки.
Не обязательно. Особенно если мы говорим про анемичный подход — зачем сущности "тряпка" сооружать усложнение с ветром? его порывы, направление, сила (которые могут быть меняющимися по разным принципам, исходя из контекста а-ля "открыли форточку — закрыли форточку")
Здравствуйте, Mr.Delphist, Вы писали:
Н>>То есть при смене направления ветра мы должны каждой тряпке это сказать?
MD>А почему нет? Свойства тряпки — это её текстура (цвет, фактура волокон, всякие пятна-дырки-подпалины). А вот ветер уже является модификатором. Причем если упороться по архитектуре, то модификатор не будет сам менять тряпку, ведь источников ветра может быть несколько: ветер природный (ambient), его отражение от препятствий на сцене, локальный ветер от вентилятора, который есть на нашей сцене (или винт самолёта, турбина и т.п.). Будет внешний объект-композер, который сможет посчитать равнодействующую этих модификаторов и применить к тряпке (и тут мы можем разделить отдельно модели, и отдельно вью-модели той же тряпки, ветра и т.п.)
Мне нравится идея. Как при расчёте света, только ещё интереснее, потому что ветер — это движение воздуха с его потоками, местами простоя и завихрениями и ни в 2D а в 3D (если время отбросить ).