Навигация
Поддержать материально
Steam Greenlight

Логотипы
Медальки
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Темы форума
WoL
24.04.2024
 Shirson
185 - RPG
9.02.2024
 Vaskrol
В каком банке открыт…
24.01.2024
 Darthman
185 - ?
30.12.2023
 Mefistofel
TESTAMENT - Тактичес…
15.11.2023
 KregHek
RES - Движок для пик…
27.09.2023
 rimush
177 - One Button Str…
20.09.2023
 VoroneTZ
JS 13k contest
13.09.2023
 Mefistofel
184 - Arcade II
14.08.2023
 tiger1025
184 - ?
14.07.2023
 Kaps
Сейчас на сайте
Гостей: 5
На сайте нет зарегистрированных пользователей

Пользователей: 1,789
новичок: NickName
Обсуждение «Здесь могла бы быть ваша реклама»
Страница 2 из 3 < 1 2 3 >
bsivko
Avatar пользователя

Опубликовано 06.07.2015 13:09 (9 лет назад)    #
MysticCoder написал:
Я решил применить компонентный подход для юнитов. Если кто не знает, это когда логика класса разделена по своим ролям на другие классы.

Компонетный подход - это когда статически создается множество компонент (базовых функциональных блоков), а потом пользователь комбинирует их в зависимости от задачи в ран-тайме.

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

Аналогично здесь. Компонентный подход - статически создаются компоненты (т.е. заранее). И далее ты в динамике собираешь то, что тебе нужно (т.е. в рантайме, по конфигурации, по обстоятельствам).

Идея компонентов в программной индустрии прослеживается как минимум до 1969 (Mass Produced Software Components).

Реализовывать компоненты не обязательно с помощью классов. Если же хочется это переложить на современный язык ООП и программной архитектуры, то по твоему описанию это скорее паттерн Decorator (классика GoF: Design Patterns, 1994). Этот паттерн более общий, в зависимости от твоего разделения может быть чуть другой паттерн (если делится например только логика, или если ссылка всегда на один объект на всех и т.д.)

редакция от bsivko, 06.07.2015 13:13

MysticCoder
Avatar пользователя

Опубликовано 06.07.2015 13:41 (9 лет назад)    #
Ну, может быть, в твоей вселенной это и так, а в моей вселенной, пусть будет так как я думаю) Если хочешь, могу исходники выложить, глянешь, компонентный у меня подход или некомпонентный. Мне вот кажется - компонентный. Декораторами тут даже и не пахнет вроде, хотя если я правильно понял, любой класс можно обозвать декоратором для TObject и быть довольным.
В общем не суть все это важно, судя по активности, здесь мало кому интересны технические подробности которые я выкладываю, видимо плюшек подавай да красивостей, поэтому посты будут реже и если будет что показать.
bsivko
Avatar пользователя

Опубликовано 06.07.2015 14:19 (9 лет назад)    #
MysticCoder написал:
Ну, может быть, в твоей вселенной это и так, а в моей вселенной, пусть будет так как я думаю) Если хочешь, могу исходники выложить, глянешь, компонентный у меня подход или некомпонентный. Мне вот кажется - компонентный. Декораторами тут даже и не пахнет вроде, хотя если я правильно понял, любой класс можно обозвать декоратором для TObject и быть довольным.

Всего лишь попытался раскрыть оригинальную идею компонентности. Которая никак не отрицает твою реализацию компонентности (и не только её, т.е. ты же там не только компонентность реализовал) на классах.

редакция от bsivko, 06.07.2015 14:19

bsivko
Avatar пользователя

Опубликовано 06.07.2015 14:43 (9 лет назад)    #
AtomKrieg написал:
Реализовывал небольшую игру через компоненты и пришел к выводу что полиморфизм и наследование идут лесом при использовании компонент.

Лес замечательно живет с компонентами.

Например, у тебя есть класс, а у него контейнер компонент Components, каждый элемент тип Base либо его наследник.

От Base наследуем Draw. От Draw всякие реализации рисования, но у Draw есть метод рисования. (это про наследование)

А теперь запускаем полиморфизм. Для исходного класса можно написать цикл по Components, который смотрит, если элемент принадлежит к Draw, то вызвать метод рисования.

Профит.
Darthman
Древний организм
Avatar пользователя

Опубликовано 06.07.2015 15:54 (9 лет назад)    #
У нас в бластоффе у каждого юнита много составляющих. Поведение, пэинтер, физика и т.д.
Это позволяет собирать юниты очень гибко. Вести он может себя также как другой, а выглядеть совсем иначе и пускать розовый дым с бабочками вместо ядерных выхлопов.
Сделать такую систему, конечно же, намного геморройнее, но вот профит огромный. Гибкость настройки потом будет поражать простой и удобством.
phomm
Avatar пользователя

Опубликовано 07.07.2015 06:17 (9 лет назад)    #
bsivko написал:
AtomKrieg написал:
Реализовывал небольшую игру через компоненты и пришел к выводу что полиморфизм и наследование идут лесом при использовании компонент.

Лес замечательно живет с компонентами.

Кстати, да. Тоже пилил небольшие пробы, и как раз оные концепции были как нельзя к месту, даже не знаю, как бы реализовывал без них. Разные компоненты конечно вряд ли под это пойдут, т.к. они по своему смыслу различаются, бо атомарны, а вот скрывающийся за абстракцией атома-компонента конкретный реализатор очень хорошо идёт и с наследованием и тем более с полиморфизмом, тем более если этих реализаторов несколько.

MysticCoder написал:судя по активности, здесь мало кому интересны технические подробности которые я выкладываю, видимо плюшек подавай да красивостей, поэтому посты будут реже и если будет что показать.

Зря, мне как раз интересны особенности в реализации, нежели чем непонятные ролики, можно и обсудить, просто не хочется сбивать с намеченного курса, и даже просто посмотреть к чему придведёт такой курс и сравнить со своим.

Код выкладывать - это всегда хорошо, тем более родной паскаль/дельфи, могу свою поделку выложить с моим видением компонентной работы, однако, я перманентно в исследованиях подобных моделей и пока не нашёл и не вник в какую-то из них, чтобы меня она устраивала, и моя тоже меня ещё не устраивает во всём, просто проба пера из далёкого 12 года.
Для кода я предпочитаю Битбакет с Меркуриалом, было бы удобно увидеть Ваш код тоже там, возможно даже повзаимодействовать, но не проблема и гит и/или гитхаб или свн и фордж.

P.S. И да, тактика - очень хорошо ! Давно хотел отписаться в этой теме, но не хотелось марать бумаги простыми словами, а сейчас самое то.

редакция от phomm, 07.07.2015 06:23

MysticCoder
Avatar пользователя

Опубликовано 07.07.2015 21:29 (9 лет назад)    #
2phomm,
спасибо за комментарии, все таки без интереса извне энтузиазм быстро угасает)
Залил сорцы на bitbucket.org. Комментов там естесственно нет. Ну, тем интереснее будет мне узнать насколько мой код прозрачен и читабелен :)
git clone https://MysticCoder@bitbucket.org/MysticCoder/eve.git

Видео я залил, чтобы можно было увидеть, что вообще уже есть наглядно. Например по нему видно, что сетевая часть в каком то виде есть и функционирует. Запускается отдельно сервак и отдельно клиенты и то, что происходит на экране одного клиента полностью соответствует тому, что происходит на экране другого клиента. Есть один вид оружия, один вид пули, можно стрелять и наносить урон. Ну и модельку анимированную добавил.
Ну теперь немного технических подробностей...
Мои бодания с сетевым кодом вроде как подошли к концу. Самое главное отличие работы с UDP от TCP про которое нигде в интернете не упоминают - это необходимость соблюдать пропускную способность канала. Хотя наверное я ошибаюсь и у TCP тоже такая проблема присутствует, ведь если в сокет напихать полтора гига фильма за секунду при канале в мегабит, то никакие перестраховки TCP в виде переотправок пакетов не спасут, т.к. системные буфера все таки ограничены и не будут хранить в себе полтора гига. Хотя раз буфер ограничен, что то мне подсказывает, что при его переполнении send просто будет возвращать ошибку, то есть все таки полтора гига в секунду не сможем залить. В таком случае у TCP такая проблема отсутствует. Может кто из знающих более подробно разложет такую ситуацию по полочкам?
Так вот, в случае с UDP, при пихании большего объема информации чем пропускная способность канала в сокет пакеты начинают теряться и приходиться городить систему подтверждений для важных пакетов либо искусственное ограничение скорости пихания данных в сокет. У себя я реализовал оба варианта.
Сокет я поместил в отдельный поток, в нем в цикле сокет читает все доступные на данный момент пакеты в буфера, потом отправляет все помещенные в очередь на отправку пакеты. От каллбеков я отказался, теперь главный поток приложения при необходимости вызывает функцию получения очередного прочитанного пакета и обрабатывает его. Таким образом поток сокета только читает и отправляет пакеты в\из список\ка, а главный поток выбирает\помещает в эти списки пакеты. Сделано это с мыслями о хорошей производительности при больших нагрузках.
Для синхронизации заюзал критические секции, обложив ими необходимый минимум по работе со списками пакетов. С большим удивлением, обнаружил для себя такую ситуацию:


var
List : TSomeObjectList; // список с которым работает 2 потока
procedure ThreadOne;
var
SomeObject : TSomeObject;
begin
while true do
begin
SomeObject := List[0]; // берем нулевой обьект из списка
SomeObject.DoSomething; // а здесь он иногда оказывается нелегитимным
end;
end;

procedure ThreadTwo;
begin
while true do
begin
....
List.Add(OtherObject); // этот поток просто иногда добавляет в список новый обьект.
end;
end;

Список по идее только растет, значит нулевой объект всегда должен быть, поэтому и синхронизировать вроде бы не надо. Но почему то иногда вместо него возвращался мусор. Копания в дебрях TList.Add привели к функции ReallocMem, в справке к которой написано, что если памяти памяти свободной по текущему указателю нет, то она может перенести указатель в другое место. Соответственно, в первом потоке при расширении списка во втором потоке иногда возвращалось значение по старой памяти, которое почему то уже было забито левыми данными. Вот, казалось бы простую операцию SomeObject := List[0]; приходится обкладывать критическими секциями.

После того как сделал механизм отправки\приема пакетов настало время как то посылать данные о юнитах. Я дал каждому юниту свой МемориСтрим, в который начал складывать(по умному вроде сериализировать) данные каждой компоненты юнита. Этот стрим уже передавал по сети от сервера к клиенту и обратно. После прохода по каждому классу с кучей NetStream.Write(Field1, SizeOf(Field1)), а также зеркально Read, энтузиазма как то поубавилось. На каждое поле приходилось 2 длинных строки. А уж при мысли о том, что надо будет поддерживать весь этот зоопарк при расширении полей и всяких компонент хотелось забиться в угол и тихо плакать. Но главное - стало возможным играть по сети.
После некоторых тестов на VPS, я пришел к удручающему выводу, что пять локальных клиентов(+10 левых юнитов, в итоге 15 юнитов на карте), уже жрут всю мою хилую пропускную способность инета в 250КБ/с. Была вспомнена мудрая мысль о том, что можно слать только те данные которые реально изменились. При мысли о том, что надо будет как то искать какие данные изменились, а это придется делать на каждое поле отдельную проверку, начинал подергиваться глаз. Через некоторое время, родился простой и элегантный механизм. Каждой компоненте юнита добавил еще один список. Список хранит записи, а точнее классы, задача которых запоминать указатель на конкретное поле родительского класса, создавать второе хранилище этого поля и сравнивать их между собой. Изменилось поле или не изменилось. Сам класс:

T_NetDiffRec = class
pVariable : Pointer; // указатель на поле, которое необходимо контролировать
pOldVariable : Pointer; // второе хранилище, в нем хранится "старое" значение поля
Size : integer; // размер поля
FromClientAgreed : Boolean; // Этим флагом обозначаются поля которые серв может принимать от клиента. Например, Серв не должен принимать от клиента поле Life, но может принять wasd кнопки.
constructor Create(AVariable : Pointer; ASize : integer);
function IsDiffed : boolean; // есть ли изменение поля?
procedure Update; // синхронизировать поле с его хранилищем
end;

В процедуре формирования и разборки сетевого стрима для компоненты я убрал все эти ненавистные NetStream.Write(Field1, SizeOf(Field1)) и Read, заменив их одним циклом по списку изменений. Теперь для того, чтобы сделать какое либо поле "сетевым", т.е. передаваемым между клиентом и сервом, надо всего лишь зарегистрировать эту переменную в конструкторе следующим образом:
...
RegisterNetDiffVar(@LookAngle, SizeOf(LookAngle), True);

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

редакция от MysticCoder, 07.07.2015 21:34

Darthman
Древний организм
Avatar пользователя

Опубликовано 08.07.2015 08:33 (9 лет назад)    #
Ссылку-то на битбакет-то дал бы. Чего квесты тут наводить?

https://bitbucket.org/MysticCoder/eve

редакция от Darthman, 08.07.2015 08:35

Daemon
Avatar пользователя

Опубликовано 08.07.2015 08:53 (9 лет назад)    #
Порицать за glut и glBegin/glEnd можно? И в целом за код рисования прямо в юнитах, без абстракций?
phomm
Avatar пользователя

Опубликовано 08.07.2015 09:04 (9 лет назад)    #
Ага, ссылка корявая, ну, понять как её поправить труда не особо надо много.
Я стащил проект, компилирую (пришлось добавить в tga-шный модуль Xproger'a "мод дельфи", а то лазарь ошибки выдавал), на меня смотрит чёрный прямоугольник - полазил, тыкнул параметр командной строки -s тоже результата нет, подебажил малость, не увидел ничего существенного. Нашёл только закоменченый кусок (модуль сцен_апок со строки 390) для инициализации карты - попробовал его, падает листеррор. поставил СимплГенМап для неконсольного режима - при запуске на меня смотрит статичная (и судя по думающему курсору винды, чего-то подвисает ещё, в чёрном прямоугольнике тож также было) картинка, аналогичная видео из темы, но без человечков, только пачка красных и зелёных прямоугольников на сером фоне.

За сим решил пока не продолжать а послушать инструкций от автора. На всякий случай - вин7х32, нвГТ630, лаз 1.2.0, фпц 2.6.2 , линукса нет, чтобы проверить, пока ленно на виртуалке подымать.

О своём - закинул свой проект (поглядел дату создания, оказалось ноябрь 2011 а не 12 даже год), ссыль https://bitbucket.org/phomm-/mapwanderers он конечно убог, но пару минут поиграться в нём можно, и код при желании поглядеть, он небольшой, меньше килостроки. Там инструкция есть как чего , чтобы "побегать".
Если кто не знает, то скачать из раздела Downloads целиком весь репо можно, экзешка приложена, ничего компилить не надо.

Daemon порицать много чего можно :) у каждого из нас. Имхо, лучше чем порицать, продуктивнее было бы форк-небольшой чейндж- пулреквест (или вдруг автор врайтдоступ даст). Если заведу у себя сей проект, может чего и покалякаю даже.

Хотя, учтывая
Ну, тем интереснее будет мне узнать насколько мой код прозрачен и читабелен :)

можно и устно чего изложить, хотя многое будет субъективно, да и толку мало даст, не кидаться же исправлять кодстайл в 260+ кб кода

редакция от phomm, 08.07.2015 09:23

Daemon
Avatar пользователя

Опубликовано 08.07.2015 09:30 (9 лет назад)    #
phomm
продуктивнее было бы форк-небольшой чейндж- пулреквест

Да тут не обойтись мелкими патчами, "господь, жги!" :) В целом архитектура несколько неудачная. Именно по части рендера. Если рендер тестовый, то все равно его стоило инкапсулировать где-то единожды, чтобы потом поменять его без особых проблем.
Darthman
Древний организм
Avatar пользователя

Опубликовано 08.07.2015 09:36 (9 лет назад)    #
Ну, тем интереснее будет мне узнать насколько мой код прозрачен и читабелен :)

Отсуствие у филдов префикса F, четкого разделения области видимости, отсуствие пропертей и странные укороченные названия не добавляют читаемости и удобства в использовании твоего кода. Это уж точно.
Кстати, а зачем все модули называть с подчеркивания? что за мания такая?
Daemon
Avatar пользователя

Опубликовано 08.07.2015 10:21 (9 лет назад)    #
Darthman
По кодстайлу там вообще много вопросов :)

Еще могу потрындеть, что никакой инкапсуляции нет. Классы-куртизанки :)
ZblCoder
Главный Говнюк
Avatar пользователя

Опубликовано 08.07.2015 10:21 (9 лет назад)    #
Да, код немного странный. Любовь к символу "_" заметна сразу.
procedure _LoadMaterials;
T_Mesh = class
procedure T_Mesh.Draw;

хоть А ставит в названии входных параметров.
function T_Map.AddUnit(AUnit: TObject; ADoGenerateID: boolean): TObject;

TObject у юнита? Сделал бы кастомный класс юнита, что ли.

так же, нет деструкторов у классов, это БЕЗУМИЕ.
пример:
убивать созданный TList кто будет?
constructor TS_TextureManager.Create;
begin
Textures := TList.Create;
end;

редакция от ZblCoder, 08.07.2015 10:22

MysticCoder
Avatar пользователя

Опубликовано 08.07.2015 10:35 (9 лет назад)    #
Daemon написал:
Порицать за glut и glBegin/glEnd можно? И в целом за код рисования прямо в юнитах, без абстракций?


Daemon написал:
phomm
продуктивнее было бы форк-небольшой чейндж- пулреквест

Да тут не обойтись мелкими патчами, "господь, жги!" :) В целом архитектура несколько неудачная. Именно по части рендера. Если рендер тестовый, то все равно его стоило инкапсулировать где-то единожды, чтобы потом поменять его без особых проблем.


Давай, порицай, излагай поподробнее, что да как тебе не нравится и как бы ты это поменял. А то я нуб и не очень понимаю, что за код рисования прямо в юнитах без абстракций, и как рендер инкапсулировать?

phomm написал:

За сим решил пока не продолжать а послушать инструкций от автора.


Каюсь, в винде я не тестил, тестил только под вайном. Работает сие так:
Верни комментарий в сцен_апок на место.
Запускаешь "Eve -s" - запускается сервер(не создается никакого окна). После запуска сервера надо запустить клиент "Eve 127.0.0.1"(может немного подумает, потом окно из видео с человечком),
под линуксом почему то срабатывало и просто "Eve", что в коде
xTo.sin_addr := sockets.StrToNetAddr(ParamStr(1));
устанавливает адрес коннекта в 0.0.0.0 вроде бы. Под виндой надо явно указать.
Ну и далее управление - wasd + левый клик мышкой. Если wasd не пашет, то переключаешь язык на английский. Ща потестил немного в винде, обнаружил шо какие то подвисания при старте происходят, надо бы этот вопрос изучить. А пока, после старта сервера, возможно клиент понадобится запускать с задержкой.

Darthman написал:
Ну, тем интереснее будет мне узнать насколько мой код прозрачен и читабелен :)

Отсуствие у филдов префикса F, четкого разделения области видимости, отсуствие пропертей и странные укороченные названия не добавляют читаемости и удобства в использовании твоего кода. Это уж точно.
Кстати, а зачем все модули называть с подчеркивания? что за мания такая?


Филды с префиксом F в основном используются как хранилище для проперти. Проперти я не использую, поэтому и на F называть ничего не надо. Не использую просто потому, что у Лазаруса с отладкой пока не все так идеально, он не умеет вызывать функции во время отладки, так что значения проперти прочитать не получится. Да и вспоминается код на работе, где простая строчка "Angle := Angle + delta" в классе корабля, в отладчике в режиме входа в процедуры превращалась в увлекательное путешествие по килобайтам кода, в котором пересчитывался центр тяжести, геометрический центр, координаты всех устройств на корабле, координаты контрола корабля, еще куча чего то. Вот в отладке проперти ясности точно не добавят)
Про области видимости - замечание хорошее, но это все после рефакторинга. Ну а с подчеркивания - чтобы ясно различать где свой, а где левый юнит, да и в юзесы через контрол-пробел добавлять свои юниты удобнее когда они начинаются с подчеркивания. То же самое относится к названиям классов.
MysticCoder
Avatar пользователя

Опубликовано 08.07.2015 10:43 (9 лет назад)    #
ZblCoder написал:
Да, код немного странный. Любовь к символу "_" заметна сразу.
procedure _LoadMaterials;
T_Mesh = class
procedure T_Mesh.Draw;

хоть А ставит в названии входных параметров.
function T_Map.AddUnit(AUnit: TObject; ADoGenerateID: boolean): TObject;

TObject у юнита? Сделал бы кастомный класс юнита, что ли.

так же, нет деструкторов у классов, это БЕЗУМИЕ.
пример:
убивать созданный TList кто будет?
constructor TS_TextureManager.Create;
begin
Textures := TList.Create;
end;


в T_Map.AddUnit, заюзал TObject, потому что там проблема перекрестных ссылок на модули была. По идее Map это всего лишь карта, и игровые юниты должны её юзать, поэтому в interface _apoc_unit, вставил uses _apoc_map. Но карта должна оперировать с юнитами, а в Interface _apoc_map уже не засунешь _apoc_unit. Так что как то так. Про деструкторы - хай так будет, утечки памяти легко исправляются, лучше исправить их одним скопом, чем при добавлении очередного списка в деструктор его паралелльно прописывать. Еще Билл Гейтс сказал, что 64 кб хватит всем)
Darthman
Древний организм
Avatar пользователя

Опубликовано 08.07.2015 10:50 (9 лет назад)    #
Если до сих пор возникают проблемы перекрестных ссылок, значит что-то пишется до сих пор неверно.
MysticCoder
Avatar пользователя

Опубликовано 08.07.2015 10:55 (9 лет назад)    #
Darthman написал:
Если до сих пор возникают проблемы перекрестных ссылок, значит что-то пишется до сих пор неверно.


Окай, покажи как правильно?
У меня раньше и карта и юниты были в одном модуле, и такой проблемы не было. Разнес их логику по разным модулям. Появился такой косяк. Утешил себя тем, что он небольшой. Всего то пара процедур.
phomm
Avatar пользователя

Опубликовано 08.07.2015 11:10 (9 лет назад)    #
6E3YMNE ¿ ƎTO CnAPTA ¡

Раз пошла такая пьянка, то:
1. Общее.
1а глобалки
1б уже упомянутый код рендера в логике
1в немало литералов - в данные или хотя бы в константы
1г довольно немало магии всякой, работы с указателями, записями, массивами, в итоге всякие циклы, хитрая индексация и т.п. при том что списки тоже в ходу.. лучше бы всё на списках и классах с уже упомянутой необходимостью контроля времени жизни
1д упомянутая инкапсуляция - введение её поможет сделать удобнее то, что в предыдущем пункте
1е использование объектов и поинтеров и последующие касты (тоже можно к магии отнести, но выделяю особняком)
1ё именование несколько напряжное
2 Субъективное
2а коробят конечно подчёрки, но видимо автору нормально и привычно..
2б меня напрягает неслежение за регистром идентификаторов, а также за пробелами между идентификаторами и прочим синтаксом, скачет отступ возле : и параметрами/переменными, скачет идентация у блоков
2в размеры методов - сложно конечно судить насколько возможно что-то с ними сделать, но тем не менее, великоваты

По архитектуре надо сперва покопать, а для этого надо бы инструкцию как собрать чтобы бегало как на видео.


P.S. дико повеселил Cooldawn (идентифаер в сцен_арена_шутер), может ещё какую перловочку найду ))
Daemon
Avatar пользователя

Опубликовано 08.07.2015 11:34 (9 лет назад)    #
Давай, порицай, излагай поподробнее, что да как тебе не нравится и как бы ты это поменял. А то я нуб и не очень понимаю, что за код рисования прямо в юнитах без абстракций, и как рендер инкапсулировать?


Это сарказм? Если нет, то завтра отпишу, что бы и как я поменял.
Страница 2 из 3 < 1 2 3 >
Перейти на форум:
Конкурсы
Открытые конкурсы:
Активных нет
Недавние конкурсы:
 185 - RPG XII
 184 - Arcade II
 183 - Novel
 182 - RPG XI
 181 - Pixel Craft 128
 Все конкурсы
Случайная игра
Мини-чат
Вам необходимо залогиниться.

Архив чата

25,392,459 уникальных посетителей

Создано на базе русской версии PHP-Fusion copyright © 2003-2006 by Nick Jones.
Released as free software under the terms of the GNU/GPL license.