Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > C++

Ответ
 
Опции темы
Старый 23.06.2010, 11:25   #1
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Описатели (Descriptors)

в своем движке применяю такую технику - объекты (движОк, текстура, окно, шрифт) создаются не через параметры, например:
Texture *tex = eng->LoadTexture("somefile.jpg",TF_ANISOTROPIC,TBM_ADD)
или
Font *fnt = eng->LoadFont("Times New Roman",14,FF_BOLD,FM_TEXCASH)
а черех описатели (Descriptors)

Texture * tex = eng->LoadTexture(TextureDesc("somefile.jpg").blend(TBM_ADD));
или
Font *fnt = eng->LoadFont(FontDesc("Times New Roman").bold(1));
минусы техники:
* обычно - больше букаф
* дополнительный класс на объект

плюсы техники:
* в сочетании с патерном мост облегчает несколько сопровождение кода при добавлении нового параметра (не нужно менять список параметров конструктора(ов) в IObject.h, CObject.h и CObject.cpp)
* можно хранить дескриптор в объекте и пользоваться фишками типа:
Font *newfont = eng->LoadFont(oldfont->GetDescriptor().bold(0));
- не знаю что за шрифт oldfont, но хаачу такой же - только нежирным чтобы был.
* можно пользоваться чем-то вроде именованных параметров, при грамотном определении умолчаний можно существенно сократить количество вводимых параметров.
* можно использовать "специальные" конструкторы. например для текстуры size(int) будет задавать одновременно и ширину и высоту (и глубину, если текса трехмерная)
* инвариант параметров. например ширина окна не может быть больше ширины дисплея, если только окно не фейковое. Правда его прийдется в конструкторе класса один фиг проверять снова, так как члены данных придется делать открытыми, чтобы конструкторы объектов имели к ним доступ. ненадежно.
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо HolyDel за это полезное сообщение:
Mhyhr (23.06.2010), Mr_F_ (23.06.2010), Samodelkin (27.06.2010)
Старый 27.06.2010, 16:21   #2
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 979
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: Описатели (Descriptors)

А можно попробовать объединить Описатель и класс IObject. Если к CObject применить умные указатели (которые считают количество ссылок на объект), то CObject достаточно создать один раз а IObject будет и как Описатель и как Указатель - то есть можно работать с CObject через разные Описатели. Если у Object много общих ресурсов но по разному параметризированных то это сильно сократит расходы памяти. К тому же Object будет всегда гарантировано удаляться если даже заранее не известна последовательность вызовов delete из разных потоков.

* инвариант параметров. например ширина окна не может быть больше ширины дисплея, если только окно не фейковое. Правда его прийдется в конструкторе класса один фиг проверять снова, так как члены данных придется делать открытыми, чтобы конструкторы объектов имели к ним доступ. ненадежно.
В том случае что я описал в функцию создания объекта окна можно передать Указатель-Описатель объекта дисплея (хотя скорей всего данные дисплея хранятся в объекте конфиге или в чем то подобном) и тогда Описатель окна обращатеся к параметрам Описателя дисплея и корректно их читает.
(Offline)
 
Ответить с цитированием
Старый 27.06.2010, 22:36   #3
jimon
 
Сообщений: n/a
Ответ: Описатели (Descriptors)

Samodelkin
А можно попробовать объединить Описатель и класс IObject. Если к CObject применить умные указатели (которые считают количество ссылок на объект), то CObject достаточно создать один раз а IObject будет и как Описатель и как Указатель - то есть можно работать с CObject через разные Описатели. Если у Object много общих ресурсов но по разному параметризированных то это сильно сократит расходы памяти.
это конечно хорошо, но в грамотно построенном приложении время создания и удаления объектов намного меньше времени просчёта основной логики, потому вводить чрезмерное ооп ради того чтобы в стеке не выделилось 10 кб раз в 10 секунд - оптимизации которые себя не оправдывают

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

К тому же Object будет всегда гарантировано удаляться если даже заранее не известна последовательность вызовов delete из разных потоков.
это хорошо, пока что-то не отвалится
 
Ответить с цитированием
Старый 02.07.2010, 17:19   #4
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 979
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: Описатели (Descriptors)

Вот вобщем попробовал совместить умный указатель с описателем. Конечно тут еще много чего не реализовано, но я буду продолжать.

это конечно хорошо, но в грамотно построенном приложении время создания и удаления объектов намного меньше времени просчёта основной логики, потому вводить чрезмерное ооп ради того чтобы в стеке не выделилось 10 кб раз в 10 секунд - оптимизации которые себя не оправдывают
А может там целая текстура в 50мб как ресурс. Вобщем то такую вещь можно и в менеджерах ресурсов исползовать.

кеш промахах и выравнивании
Это уже очень важно - если один объект и набор описателей будут все время находится в кеше то прирост производительности будет очень большой. Хотя конечно на последних цп кеши довольно большие - очень много объектов влезет и так.

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

DescTest.cpp
#include "DescTest.h"

void Func() {

	/*
	======================================================================================
	Создадим указатель-описатель и сам объект.
	Вообще созданием объекта может заниматься другая функция
	или его можно получать из другой библиотеки.
	При присваивании указателю-описателю объекта счетчик указателей увеличивается на один.
	======================================================================================
	*/
	SmartPointerT<MyDesc, MyObject> sp(new MyObject());

	/*
	=================================================
	Настраиваем параметры для указателя-описателя sp.
	=================================================
	*/
	sp.desc.param1 = 'a';
	sp.desc.param2 = 10;
	sp.desc.param3 = 5.0f;
	sp.desc.PrintStat(); // Выводим параметры на экран

	/*
	==============================================================================
	Затем создадим второй указатель-описатель sp2 и скопируем параметры с sp один.
	Также можно копировать параметры и с описателей другого типа.
	Счетчик ссылок увелитися еще на один.
	==============================================================================
	*/
	SmartPointerT<MyDesc, MyObject> sp2(sp);
	sp.desc.param3 = 6.0f; // Изменим только третий параметр.
	sp.desc.PrintStat(); // Выведем на экран.

	/*
	========================================================
	Вызовы функций объекта через разные указатели-описатели.
	Тут можно активно использовать КЭШИРОВАНИЕ ДАННЫХ - 
	например один раз посчитал нахождение пути для sp и sp2
	может пользоваться готовым результатом.
	========================================================
	*/
	sp.SetParam(); // Применяем к объекту параметры дескриптора sp и работаем с объектом.
	sp.p.FuncOne();
	sp.p.FuncTwo();
	sp.SetParam(); // Применяем параметры sp2 и работаем (также можно попробовать сделать автоматическое применение параметров при вызове методов с текущего указателя).
	sp2.p.FuncThree();

	/*
	============================================
	Перед выходом из функции sp и sp2 удаляются,
	следовательно вызываются их деструкторы,
	следовательно удаляется объект MyObject.
	============================================
	*/
}

int main() {

	Func();

	// Остановим консоль.
	char a;
	std::cin >> a;	

	return 0;
}
DescTest.hpp

#include <stdio.h>
#include <iostream>


/************************************************

 Base

************************************************/

class MyDesc;

class Base {
public:
	unsigned int	count;

					Base() : count(0) {
						std::cout << "Base::Base" << std::endl;
					}
	virtual			~Base() {
						std::cout << "Base::~Base" << std::endl;
					}
};


/*************************************************

 MyObject

*************************************************/

class MyObject : public Base {
public:
	virtual	void	FuncOne() {}
	virtual void	FuncTwo() {}
	virtual void	FuncThree() {}

	void			SetParam(MyDesc& desc) {
						// Применяем параметры
					}
					
					MyObject() {
						std::cout << "MyObject::MyObject" << std::endl;
					}
	virtual			~MyObject() {
						std::cout << "MyObject::~MyObject" << std::endl;
					}
};


/*****************************************

 DescBase - MyDesc

*****************************************/

class DescBase {
public:
	virtual void	PrintStat() = 0;

					DescBase() {}
	virtual			~DescBase() {}
};

class MyDesc : public DescBase {
public:
	char			param1;
	int				param2;
	float			param3;

	virtual void	PrintStat() {
						std::cout << "PrintStat: " << param1 << ", " << param2 << ", "<< param3 << std::endl;
					}

	explicit		MyDesc() {}
	explicit		MyDesc(MyDesc& desc) {
						param1 = desc.param1;
						param2 = desc.param2;
						param3 = desc.param3;
					}
	virtual			~MyDesc() {}
};


/*****************************************

 SmartPointer (template)

*****************************************/

template<typename D, typename P>
class SmartPointerT {
private:
	void		operator =(SmartPointerT<D, P> sp) {}
	void*		operator new(size_t bytes) {}
	void		operator delete(void* address) {}
	void		operator delete(void* address, size_t bytes) {}

public:
	P&			p;
	D			desc;

	void		SetParam() {
					p.SetParam(desc);
				}

	explicit	SmartPointerT(P& object) : desc(), p(object) {
					p.count++;
					std::cout << "SmartPointerT::SmartPointerT\np.count = " << p.count << std::endl;
				}
	explicit	SmartPointerT(P* object) : desc(), p(*object) {
					p.count++;
					std::cout << "SmartPointerT::SmartPointerT\np.count = " << p.count << std::endl;
				}
	explicit	SmartPointerT(SmartPointerT<D, P>& sp) : p(sp.p), desc(sp.desc) {
					p.count++;
					std::cout << "SmartPointerT::SmartPointerT\np.count = " << p.count << std::endl;
				}
	virtual		~SmartPointerT() {
					p.count--;
					std::cout << "SmartPointerT::~SmartPointerT\np.count = " << p.count << std::endl;
					if(p.count == 0)
						delete &p;
				}
};
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
HolyDel (02.07.2010)
Старый 02.07.2010, 20:36   #5
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Ответ: Описатели (Descriptors)

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

вобщем допустим у нас есть некий описатель шрифта для гуй
FontDesc gui_fond_dsc("Impact");
gui_fond_dsc.size = 16;
gui_fond_dsc.bold = true;
и шрифт там для игры самой
FontDesc game_font_dsc("Verdana");
game_font_dsc.size=12;
так вот, в игре должны быть ДВА разных шрифта обязательно. потому, что шрифт это не совсем не описатель это самостоятельная сущность. Она будет долго конструироваться, так как нужно не только загрузить сам шрифт (wglUseOutline, FT2_LoadFont, и LoadTexture) - чтобы получить сам растр(векторные данные) шрифта довольно долго будут выполняться. А кроме этого нужно еще составить кэш-текстуру для букв из юникода (если все они не влезут в одну текстуру), можно кешировать часто выводимые фразы, вобщем можно много чего сделать в конструкторе.

то, что ты предлагаешь, кстати, напоминает паттерн Приспособленец (Flyweight)
http://www.citforum.ru/SE/project/pattern/#3.1.8
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Samodelkin (02.07.2010)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 13:05.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com