Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

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

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


Ответ
 
Опции темы
Старый 09.07.2013, 17:01   #1
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Адрес: Живу в горшке, ем мух
Сообщений: 342
Репутация: 32
Лампочка Мой движок (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,243
Репутация: 279
По умолчанию

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

Цитата:
А почему 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,243
Репутация: 279
По умолчанию

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

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

Цитата:
у вас в коде присутствует 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
Адрес: Home Sweet Home
Сообщений: 1,327
Репутация: 633
По умолчанию

Цитата:
это круче чем 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
Адрес: Живу в горшке, ем мух
Сообщений: 342
Репутация: 32
По умолчанию

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

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

Например.
Во время запуска приложения я загружаю массив текстур которые будут использоваться в игре.
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
Адрес: Нижний Новгород
Сообщений: 5,562
Репутация: 1743
По умолчанию

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

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

Опции темы

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

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

Быстрый переход

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


10:33.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru