Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.07.2013, 17:01   #1
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
Лампочка Мой движок (Epic Fail Engine)

Здравствуйте форумчане! Я вас снова потревожу (
Дело такое, я пишу свой эпически-отстойный движек для моей эпически-отстойной игрушки (которую я еще не придумал, надо заметить).
И у меня уж есть успехи! Да, да... есть первый квадрат и он бегает по экрану )

Вопрос вот в чем, я прикрутил измеритель кадров в секунду и при выходе в консоле показывается информация о последних фпс.
Ну так вот, я пробовал по разному и с вертикальной синхронизацией (60фпс) и без (1500 фпс).

А вот если я захочу ограничить скажем верхний потолок 30-ю кадрами или 100 в секунду.
Это что и как мне нужно будет сделать ?
Я предполагаю в процедуре где разруливаются сообщения винды нужно будет ставить какие-то замеры времени и их проверки, как это сделать?

Приведу чутку кода чтобы было понятно от чем я.
Код:
int main() 
{

	// Setup Engine
	if (engineInit()) 
	{
		engineRegisterRender(DrawFrame);
		engineRegisterKeyboard(Keys);
		engineRegisterMouse(Mouse);
	
		//engineRegisterKeyboardListener(keyA);
		//engineRegisterKeyboardListener(keyB);

		//engineRegisterMouseListener(cameraMouse);
		engineRegisterTimeEvent(CubeMove, 0.01);

		// Main game loop
		while (engineRun()) 
		{

		
		}
	}

	// Free Engine resources
	printf("render frame time %f sec\n", engineGetRenderTime());
	printf("render fps %f\n", 1.0f / engineGetRenderTime());
	engineFree();

	// Wait some time before exit
	Sleep(2000);

	return 0;
}
Вот тут чет добавить нужно будет мне кажется.
Код:
int engineRun() 
{
	int OurAppGotAMessage = 0;
	MSG msg = {0};
	PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );

#ifdef ENGINE_DEBUG
	printf("engineRun()\n");
#endif

	while( WM_QUIT != msg.message  )
	{
		if( iFocus )
			OurAppGotAMessage = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 );
		else
			OurAppGotAMessage = ( GetMessage( &msg, NULL, 0U, 0U ) != 0 );

		if( OurAppGotAMessage )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{
			
			fLastTime = engineGetTicks();
			
			processTimeEvents(); // watch for timers vector

			if (pRenderProc != NULL) pRenderProc(fElapsedTime); // draw frame
			
			fElapsedTime = engineGetTicks() - fLastTime;

			// TODO!!!
		}
	}

	return (int) msg.wParam;
}
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 09.07.2013, 20:08   #2
Kix.IV
Участник клуба
 
Регистрация: 11.08.2012
Сообщений: 1,226
По умолчанию

А почему Epic? Пока ещё просто Fail.
Я точно не знаю, как устроено ограничение фпс. Наверно в обработке каждого кадра ставится задержка, которая зависит от времени обработки предыдущего кадра.
Типо так:
sleep((1000 div FPS) - LT);
, где FPS - Нужны фпс, а LT время обработки прошлого кадра.
Kix.IV вне форума Ответить с цитированием
Старый 09.07.2013, 22:06   #3
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
Лампочка

Цитата:
А почему Epic? Пока ещё просто Fail.
Ну потому что, если уж замахиваться на что-нибудь, то на что-нибудь грандиозное, эпичное и провалить это все с треском.
В добавок возможно с твоей колокольни оно просто менее эпичным смотрится, это да ни взять ни отнять.

Цитата:
Я точно не знаю, как устроено ограничение фпс. Наверно в обработке каждого кадра ставится задержка, которая зависит от времени обработки предыдущего кадра.
я вот написал такую чудо процедуру
Код:
// приватные в engine.c 
static int iFpsLimitRate = 0; // no limit
static float fFpsLimitLast = 0.0f;

// из engine.h
int engineLimitFpsTo(int rate) 
{
	iFpsLimitRate = rate;
	fFpsLimitLast = engineGetTicks();

	return ENGINE_RETURN_OK;

}

// в engine.c 
int _fpsLimiter(int rate) 
{
	static float fElapsed = 0.0f;
	static float fCurrent = 0.0f;
	float fDelta = 0.0f;
	float fps = 0.0f;

	fCurrent = engineGetTicks();

	fDelta = fCurrent - fFpsLimitLast;
	fps = 1.0f / rate;

	fElapsed += fDelta;
	fFpsLimitLast = fCurrent;

	if (fElapsed > fps) 
	{
		fElapsed -=fps;
		return 1;
	}
	else
		return 0;

}
И воткнул ее для проверки в главный разрулительный цикл.
И оно вроде бы работает, но фпс все равно больше чем задаю примерно в 2 раза, хз почему.

Код:
	while( WM_QUIT != msg.message  )
	{
		if( iFocus )
			OurAppGotAMessage = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 );
		else
			OurAppGotAMessage = ( GetMessage( &msg, NULL, 0U, 0U ) != 0 );

		if( OurAppGotAMessage )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{
			
			
			processTimeEvents(); // watch for timers vector

			if (iFpsLimitRate != 0) 
			{
				if (_fpsLimiter(iFpsLimitRate)) 
				{
					fLastTime = engineGetTicks();

					if (pRenderProc != NULL) pRenderProc(fElapsedTime); // draw frame
					
				}
				fElapsedTime = engineGetTicks() - fLastTime;

				
			}
			else 
			{
				fLastTime = engineGetTicks();

				if (pRenderProc != NULL) pRenderProc(fElapsedTime); // draw frame
				fElapsedTime = engineGetTicks() - fLastTime;
	
			}

			
			

			// TODO!!!
		}
	}

	return (int) msg.wParam;
}
Картинка в целом вроде соответсвует задаваемым лимитам, но вот замеры пургу зачастую показывают -4000 фсп, например ))
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 10.07.2013, 09:30   #4
Kix.IV
Участник клуба
 
Регистрация: 11.08.2012
Сообщений: 1,226
По умолчанию

Из кода я мало чего понял (лень вникать в плохо знакомый мне синтаксис, из-за больших расстояний между словами я теряюсь). Возможно, у вас не правильно замеряется время обработки кадра. Для этого лучше всего использовать GetTickCount (у вас в коде присутствует engineGetTicks, что это такое я не знаю).
И ориентироваться только на время просчёта предыдущего кадра - это неправильно. Я лишь для примера это привёл. Попробуйте добавить ожидание, зависимое от среднего времени обработки последних 10 кадров. Это повысит точность. Ну и учитывайте, что подсчёт нужного ожидания сам занимает некоторое время.
UPD: Написал небольшой код. Посмотрите, там всё нормально работает. Фпс держится стабильно. Расчёт идёт только на время обработки предыдущего "кадра". Если время обработки не стабильно (постоянно прыгает), то надо добавить расчёт среднего времени обработки кадра.
Вложения
Тип файла: zip Time.zip (81.0 Кб, 14 просмотров)

Последний раз редактировалось Kix.IV; 10.07.2013 в 10:13.
Kix.IV вне форума Ответить с цитированием
Старый 10.07.2013, 11:22   #5
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Цитата:
у вас в коде присутствует engineGetTicks, что это такое я не знаю
это круче чем GetTickCount, покрайней мере точнее на порядок.

// вызывается при инициализации движка.
Код:
void initTimer() 
{
	QueryPerformanceFrequency(&qpc);
	freq = (1.0 / qpc.QuadPart);
}

//  Вызывается каждый раз когда нужно узнать кол-во тиков
double engineGetTicks()
{
	QueryPerformanceCounter(&qpc);
	return freq * qpc.QuadPart;
}
Цитата:
Ну и учитывайте, что подсчёт нужного ожидания сам занимает некоторое время.
ну пару тройку циклов да, это время задержки между кадрами в секунде, которое нужно выжидать. fps дальше сравнивается с прошедшим временем.
Код:
fps = 1.0f / rate;
Цитата:
Попробуйте добавить ожидание
if t > 0 then sleep(t);

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

Цитата:
надо добавить расчёт среднего времени обработки кадра.
Какой смысл в нем? Имхо для расчетов нужно лишь прошедшее чтобы провернуть логику событий на нужную дельту и так каждый кадр.

смотри предположим мы за Секунду(хочу заметить именно за сек.) имеем разное время прорисовки - elapsedtime()

В первом случае будем иметь 0.1 сек т.е 10 раз за сек (10 fps)
player.x += elapsedtime(0.1 sec) x player.speed(10) = 1 delta move
Во втором случае предположим будем иметь время прорисовки 1 сек. (1 fps)
player.x += elapsedtime(1 sec) x player.speed(10) = 10 delta move

можно подсчитать что 1 delta move (10 раз) = 10 delta move которые мы получили во втором случае. Зачем мне среднее время ? Мне кажется это как-то не здорово будет влиять на просчеты, объекты будут странно как-то ускоряться то замедляться в зависимости от того какая нагрузка на прорисовку была за измеряемый интервал.
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 10.07.2013, 11:59   #6
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Цитата:
это круче чем GetTickCount, покрайней мере точнее на порядок.

// вызывается при инициализации движка.
Код:

void initTimer()
{
QueryPerformanceFrequency(&qpc);
freq = (1.0 / qpc.QuadPart);
}

// Вызывается каждый раз когда нужно узнать кол-во тиков
double engineGetTicks()
{
QueryPerformanceCounter(&qpc);
return freq * qpc.QuadPart;
}
оно то может и круче, но, на мой взляд, нужно только на этапе разработки при проведии работ по улучшению производительности.
кстати, Intel учит, что в старых моделях процессоров частота счетчика производительности привязана к частоте ядра и может меняться во время работы. Также на некоторых моделях многоядерных процов, не насмотря на то что скорость прироста счетчика стабильна, значения счетчика на разных ядрах различны, поэтому рекомендуется привязывать поток считающий интервалы времени к одному ядру. Вот такая фигня.
f.hump вне форума Ответить с цитированием
Старый 10.07.2013, 15:47   #7
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Цитата:
поэтому рекомендуется привязывать поток считающий интервалы времени к одному ядру. Вот такая фигня.
ну да типо СетАффиниту нужно юзать .
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 10.07.2013, 19:38   #8
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Как бы сделать само удаление объектов на Си. Типо деструкторов в с++.

Например.
Во время запуска приложения я загружаю массив текстур которые будут использоваться в игре.
tex[0] = engineloadTexture("1.bmp");
tex[1] = engineloadTexture("2.bmp");
tex[2] = engineloadTexture("3.bmp");

а во время выхода они бы само удалились.

т.е. чтобы не пришлось каждый раз писать для каждой текстурки

engineTextureFree(&tex[0]);
engineTextureFree(&tex[1]);
engineTextureFree(&tex[2]);

Они бы делались, но где-то и автоматически.

В общем пока вопрос открыт, как ?
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 10.07.2013, 20:12   #9
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

auto_ptr<>
waleri вне форума Ответить с цитированием
Старый 10.07.2013, 20:31   #10
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Ты это серьезно?)
Ты мне предлагаешь заюзать на СИ-89 года, шаблоны с умными указателями?
И как это будет выглядеть?)
Помоему на Си лишь дико макросами можно спамить в коде.
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Fail fast Arween Помощь студентам 0 31.05.2012 00:22
Fail Prince En Помощь студентам 0 07.03.2011 15:27
string epic fail Red_Line Общие вопросы C/C++ 5 09.02.2011 17:43
мой движок для текствых игр Juffin Gamedev - cоздание игр: Unity, OpenGL, DirectX 8 10.06.2009 18:24
Помогитеу становить движок на сайт. Движок Joomla acmilan WordPress и другие CMS 2 01.04.2009 11:26