Суббота, 26.05.2012, 00:05

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
Страница 1 из 11
Модератор форума: Vinchensoo 
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Не получается сделать таймер. (аналог step в GM)
Не получается сделать таймер.
AGENTX001Дата: Понедельник, 12.12.2011, 01:50 | Сообщение # 1
старожил
Сообщений: 1664
Сейчас нет на сайте
Всем привет! Возник вопрос, как в консоли реализовать подобие таймера? Мне нужно, чтобы каждые 3 милисекунды выполнялся код моего сервера... Сделал счётчик, но вместа ождаемого fps = 300, увидел всего 60. Пробовал в делфи 7 и лазарусе, одинаково... Помогите, пжст smile
Code
while (true) do
   begin
   if GetTickCount - t1 >= 3 then
    begin
      t1 := GetTickCount;
      Inc(kol);
      {тут будет код серва}
    end;

   if GetTickCount - t2 >= 1000 then {каждую секунду показываю фпс}
    begin
      t2 := GetTickCount;
      WriteLn('fps: ',kol);
      kol := 0;
    end;
   end;


Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
GECKДата: Понедельник, 12.12.2011, 04:45 | Сообщение # 2
заслуженный участник
Сообщений: 658
Сейчас нет на сайте
Quote (AGENTX001)
но вместа ождаемого fps = 300, увидел всего 60

Значит код серва жрет намного больше времени, чем ожидалось smile

Можешь еще попробовать
Code
while (true) do begin
   {код чего угодно}
   Delay(3); // зажержка
end;


Всё гениальное просто. И хреново работает.
 
AGENTX001Дата: Понедельник, 12.12.2011, 11:37 | Сообщение # 3
старожил
Сообщений: 1664
Сейчас нет на сайте
Quote (GECK)
Значит код серва жрет намного больше времени, чем ожидалось

Там пока вообще пусто!))
Quote (GECK)
Можешь еще попробовать

Ага, попробую.

Добавлено (12.12.2011, 11:37)
---------------------------------------------
GECK, сапсибо, так действительно лучше!)
ps нет функции delay, есть sleep biggrin


Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Понедельник, 12.12.2011, 13:57 | Сообщение # 4
старожил
Сообщений: 1588
Сейчас нет на сайте
Quote (AGENTX001)
как в консоли реализовать подобие таймера?

Можно сделать так называемый "мультимедиа таймер". Кстати, он гораздо надёжнее и точнее обычного компонента-таймера, и чаще используется в играх... Хотя есть более рациональный вариант - в событии "ничего не делания" проверять системное время...
Вот код примера использования мультимедийного таймера:
Code
uses MMSystem; //Модуль с мультимедиа-функциями
var Timer1:Integer; //Идентификатор таймера, с помощью которого происходит управление таймером
//Функция, вызываемая таймером
procedure TimeCallBack(TimerID, Msg: Uint; dwUser, dw1, dw2: DWORD); pascal;
begin
     //Делаем что-нибудь здесь
end;
//Создание таймера
procedure TForm1.Button1Click(Sender: TObject);
begin
      Timer1:=TimeSetEvent(10, {Слева период вызова функции справа в миллисекундах} 0, @TimeCallBack, 0, TIME_PERIODIC);
end;
//Убить таймер
procedure TForm1.FormDestroy(Sender: TObject);
begin
    TimeKillEvent(Timer1);
end;

***
Ну и в консольном режиме тоже можно сделать такое. Подробнее о функции TimeSetEvent читай в интернете.



Сообщение отредактировал TimKruz - Понедельник, 12.12.2011, 14:04
 
ilnarkoДата: Понедельник, 12.12.2011, 14:19 | Сообщение # 5
был не раз
Сообщений: 16
Сейчас нет на сайте
var
i:integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
i:=5; //Допустим надо отсчитать 5 секунд
Timer1.Enabled:=true; //Запускаем таймер
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
i:=i-1; //Отнимаем по секунде
// Если время закончилось, то останавливаем таймер и показываем сообщение.
if i=0 then
begin
Timer1.Enabled:=false;
ShowMessage('Время истекло');
end;
end;

Сообщение отредактировал ilnarko - Понедельник, 12.12.2011, 14:22
 
TimKruzДата: Понедельник, 12.12.2011, 14:25 | Сообщение # 6
старожил
Сообщений: 1588
Сейчас нет на сайте
ilnarko, эээ, ты предлагаешь использовать компонент TTimer, а он, насколько я понимаю, доступен только в визуальном режиме. А у него консольная программа. Да и тем более - этот компонент довольно-таки не точный и имеет серьёзное ограничение на минимальный период (кажется, 30 мс).

 
AGENTX001Дата: Суббота, 24.12.2011, 15:55 | Сообщение # 7
старожил
Сообщений: 1664
Сейчас нет на сайте
TimKruz, о май мозг! ну меня в принципе и sleep устраивает!))

Добавлено (24.12.2011, 15:55)
---------------------------------------------
Всем привет, снова вопрос по теме:) Собственно всё вроде как создаётся, НО программа благополучно вылетает, даже не думая выполнять мой цикл...

Code
program lofh;

{$mode objfpc}{$H+}

uses
   MMSystem,
   sysutils,
   windmill,
   windows;

{$R *.res}

var
   step_timer : integer;

procedure MainLoop (uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD); stdcall;
begin
   work();
end;

begin
   WindowIni ('Land Of Hero',640,524,false,false,0,'Cursor.cur');
   GraphicsIni (0,false,COLOR(255,38,27,0));
   SceneManagerIni(525);
   ResourceIni();
   InputIni();
   TextIni('font.png','font.dat',32);

   step_timer := TimeSetEvent(20, 0, @MainLoop, 0, TIME_PERIODIC);
end.          


Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Суббота, 24.12.2011, 16:10 | Сообщение # 8
старожил
Сообщений: 1588
Сейчас нет на сайте
AGENTX001, так ты же создаёшь простую программу. Без окна и, что самое важное, обработчика сообщений. Она у тебя после строчки step_timer:=... просто и благополучно завершается, и всё. Не знаю, что делают функции ...Ini (Из модуля windmill? Что-то такое припоминается, но не помню название), но даже если создаётся окно, обработки сообщений нет. Что это вообще за сообщения такие? Сообщения Windows, посылаемые программе (окну), когда пока она "висит" в памяти. Она постоянно (в бесконечном цикле) должна проверять наличие сообщений и обрабатывать их. Минимальная программа Windows на Delphi выглядит так (код из книги "OpenGL в Delphi" М.Краснова):


***
Собственно, нужно узнать, что и как делает твой движок, и придумать, какой сделать цикл, чтобы программа не завершалась раньше времени.

***
В принципе, можно использовать не таймер из MMSystem, а напрямую из WinAPI, если тебе нужна минимальная программа. Там примерно то же, только обработка сообщения таймера (WM_TIMER) происходит в цикле обработки сообщений... Для его создания - SetTimer(указатель на окно, идентификатор таймера, период, указатель на функцию[для обработки в обработчике сообщений - nil]), и для убийства - KillTimer (указатель на окно, идентификатор таймера);



Сообщение отредактировал TimKruz - Суббота, 24.12.2011, 16:19
 
AGENTX001Дата: Суббота, 24.12.2011, 16:18 | Сообщение # 9
старожил
Сообщений: 1664
Сейчас нет на сайте
Quote (TimKruz)
что делают функции ...Ini

Инициализируют движок
Quote (AGENTX001)
WindowIni ('Land Of Hero',640,524,false,false,0,'Cursor.cur');

Создаёт окно.
Quote (TimKruz)
Собственно, нужно узнать, что и как делает твой движок, и придумать, какой сделать цикл, чтобы программа не завершалась раньше времени.

Пытался while (true) - жутко виснет...(

Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Суббота, 24.12.2011, 16:20 | Сообщение # 10
старожил
Сообщений: 1588
Сейчас нет на сайте
Quote (AGENTX001)
Пытался while (true) - жутко виснет...(

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

 
AGENTX001Дата: Суббота, 24.12.2011, 16:21 | Сообщение # 11
старожил
Сообщений: 1664
Сейчас нет на сайте
TimKruz, а как сделать, при этом не трогая формы? Там у движка начинается жуткий крах, всё глючит так, что капец...

Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Суббота, 24.12.2011, 16:25 | Сообщение # 12
старожил
Сообщений: 1588
Сейчас нет на сайте
Quote (AGENTX001)
Создаёт окно.

Видимо, окно-то она создаёт, но без основного окна оно не функционирует... или без цикла обработки сообщений... В любом случае, тут нужно либо копать движок, либо искать инструкции на официальном сайте...
А вот функция
Quote (AGENTX001)
GraphicsIni (0,false,COLOR(255,38,27,0));

обязательно применяется к своему окну движка (которое создаётся WindowIni), или можно применить к любому? Или, возможно, WindowIni может "прикрепляться" к существующему окну, т.е. не создавать новое?

 
AGENTX001Дата: Суббота, 24.12.2011, 16:33 | Сообщение # 13
старожил
Сообщений: 1664
Сейчас нет на сайте
Quote
GraphicsIni (0,false,COLOR(255,38,27,0));

Прикрепляется к любому, там первый аргумент - хэндл, но если поставить 0, то применется к окну созданному WindowIni

Добавлено (24.12.2011, 16:33)
---------------------------------------------
TimKruz, есть ещё функция RunEngine(@main_procedure), но если юзать её, то баг с графикой, всё ужасно мигает.


Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Суббота, 24.12.2011, 16:36 | Сообщение # 14
старожил
Сообщений: 1588
Сейчас нет на сайте
А специального таймера там, случаем, нет?
Quote (AGENTX001)
Прикрепляется к любому, там первый аргумент - хэндл, но если поставить 0, то применется к окну созданному WindowIni

Вот оно! Вот и сделай по примеру минимальное окно, цикл обработки сообщений, и при появлении сообщения wm_create инициализируй движок, прикрепляя графику к своему окну...

 
AGENTX001Дата: Суббота, 24.12.2011, 16:52 | Сообщение # 15
старожил
Сообщений: 1664
Сейчас нет на сайте
TimKruz, удалось сделать всё гараздо проще!))
Code

program lofh;

{$mode objfpc}{$H+}

uses
   MMSystem,
   sysutils,
   windmill,
   windows;

{$R *.res}

var
   step_timer : integer;

procedure GameLoop ();
begin
   Print('!!!',100,100,1,2,COLOR(255,255,0,0)) {тут Игра}
end;

procedure RenderLoop (uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD); stdcall;
begin
   work(); {тут ТОЛЬКО рендер}
end;

begin
   {инициализация двига}
   WindowIni ('Land Of Hero',640,524,false,false,0,'Cursor.cur');
   GraphicsIni (0,false,COLOR(255,0,0,0));
   SceneManagerIni(525);
   ResourceIni();
   InputIni();
   TextIni('font.png','font.dat',32);
   RunEngine(@GameLoop);

   {запуск таймера}
   step_timer := TimeSetEvent(20, 0, @RenderLoop, 0, TIME_PERIODIC);
end.  

Добавлено (24.12.2011, 16:52)
---------------------------------------------
TimKruz, спасибо за время которое на меня потратил!)


Уроки по GM/39DLL
[MMOG]Battle City World - легендарные танчики в новом обличие!
 
TimKruzДата: Суббота, 24.12.2011, 17:12 | Сообщение # 16
старожил
Сообщений: 1588
Сейчас нет на сайте
Quote (AGENTX001)
Print('!!!',100,100,1,2,COLOR(255,255,0,0))

Как я понимаю, Print выводит текст на окно? А лишний текст мешать не будет?.. Хотя, конечно, там может быть что-то полезное... Вообще-то надо читать документацию по движку, чтобы всё правильно сделать...
Quote (AGENTX001)
{запуск таймера}

А удалить?.. Хотя, кажется, Windows сама всё чистит...

В принципе, можно вместо
Quote (AGENTX001)
step_timer := TimeSetEvent(20, 0, @RenderLoop, 0, TIME_PERIODIC);

написать
Quote
SetTimer(FindWindow(nil,'Land Of Hero') {или переменная-указатель, если такую можно вытащить из движка}, idTimer {константа}, 20, @RenderLoop)

и тогда выкинуть MMSystem, т.к. это WinAPI-функция... Собственно, у мультимедиа-таймера есть несколько дополнительных возможностей, но тебе же нужен просто таймер. А вот на счёт различия в точности между ними не знаю... Теоретически, API-функции всегда лучше использовать, хотя иногда сложнее...

Quote (AGENTX001)
TimKruz, спасибо за время которое на меня потратил!)

Всегда рад помочь. smile

 
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Не получается сделать таймер. (аналог step в GM)
Страница 1 из 11
Поиск:

Все права сохранены. GcUp.ru © 2008-2012 Рейтинг