forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Алгоритмика (http://forum.boolean.name/forumdisplay.php?f=21)
-   -   Индикатор загрузки (http://forum.boolean.name/showthread.php?t=1313)

Valet 15.08.2006 21:13

Индикатор загрузки
 
Господа, не будет ли здесь кого-нибудь, кто разъяснит мне принцип работы loading_bara и метод его создания в Blitz3D? Заранее благодарю :@

impersonalis 16.08.2006 00:33

Re: Индикатор загрузки
 
При создании программ вы рано или поздно сталкиваетесь с проблемой: программа выполняет какую-то неинтерактивную процедуру слишком долго. Причём в ходе написания она не раз зависала на этой процедуре, а вы тупо сидели минут пятнадцать в ожидании успешной загрузки; в более поздних стадиях, вы думали – «ну ещё секунд 20, и готово!» - на деле: вы сидели и ждали, вместо того, чтобы пройтись по комнате (в особо тяжких случаях – перекусить); и, наконец, когда игра была роздана друзьям-тестерам вы не раз наблюдали, как «тестер», посмотрев несколько секунд ваш чёрный экран (или, что того ещё хуже – застывший с выбранной кнопкой «START» GUI), кричал – «О, Боже! Всё повисло!»- и, в мгновение ока, дважды клацал по ctrl-alt-del.
Всё это из-за отсутствия визуализации процесса.
А ведь всего этого бы не произошло, если бы вы заметили, что кол-во процентов выполненной части процедуры подозрительно долго не меняется, или индикатор загрузки, ещё не скоро дойдёт до конца, или перед тестером висела надпись «LOAD…» и крутились красивые шестеренки.
Самый простой и привычный способ визуализации – прогресс бар (progress bar).

Давайте посмотрим на наш гипотетический код:
[highlight=blitzbasic]
For i=1 To 100
m(i)=LoadAnimMesh(MODEL_FOLDER$+"car"+i+".x")
Next
[/highlight]
Очевидно, что время уходит в нём на загрузку моделей (car1.x,car2.x и т.д.).
Допустим, одна модель грузиться 10 мсек., т.е. наш цикл эквивалентен:
[highlight=blitzbasic]
For i=1 To 100
Delay 10
Next
[/highlight]
Премудростей здесь искать не надо – я просто избавил код от конкретики, чтобы упростить объяснение.
Теперь нам надо чтобы определённая область закрашивалась соразмерно ходу выполнения цикла. Допустим область – это прямоугольник со сторонами 10 на 202 пикселей:
[highlight=blitzbasic]

Graphics 800,600
size_y%=10
size_x%=202
Color 255,0,0
For i=1 To 100
Rect 20,20,size_x,size_y,0
Flip
Delay 10
Next

[/highlight]
Степень проникновения в процесс загрузки у нас вообще никакая: мы модем только что-то сделать ДО и ПОСЛЕ. Следственно – обновить прогресс бар (сообщить о ходе загрузки) мы сможем только 100 раз. Значит, за один раз мы будем закрашивать 100-ую часть области.
Размеры этой части соответственно:
[highlight=blitzbasic]
ind_size_x%=(202-2)/100
ind_size_y%=10-2
[/highlight]
А вот так мы будем рисовать индикатор:
[highlight=blitzbasic]
Graphics 800,600
SetBuffer BackBuffer()
size_y%=10
size_x%=202
ind_size_x%=(202-2)/100
ind_size_y%=10-2
For i=1 To 100
Color 255,0,0
Rect 20,20,size_x,size_y,0
Color 120,120,120
Rect 20+1+ind_size_x*(i-1),20+1,ind_size_x,ind_size_y
Flip
Delay 10
Next

[/highlight]

Собственно – индикатор можно закрашивать и по-другому. Например, не 10 раз по одной 10ой со смещением, а 1/10 – затем, поверх неё, 2/10 и так далее. Или вывести в область картинку и поверх неё нарисовать чёрный прямоугольник, который будет всё время уменьшаться, однако на чёрном фоне окна, это создаст эффект появления картинки.
Можно использовать различные абстрактные формы и траектории движений – всё зависит от конкретики игры и вашей фантазии.
Единственное – не надо увлекаться: Время расчёта и вывода индикатора должно быть намного меньше времени выполнения одной итерации цикла. Если это никак не получается – обновляйте индикатор не каждый проход, а раз в N проходов. Или, возможно, вы выбрали неудачный масштаб? Например, при большом кол-ве вложенных циклов – обновлять прогресс бар в самом вложенном, почти всегда нерационально.
Если у вас несколько громоздких операций (к примеру – 2 цикла), рассчитайте коэффициенты для закраски соответствующим образом.

impersonalis 16.08.2006 00:40

Re: Индикатор загрузки
 
Прогресс бар обычно является объектом GUI и для него предусмотрены уже готовые функции. Вот, например, как это может выглядеть на С++ с использованием MFC:
Мы создаём (в коде или редакторе) на форме объект – прогресс-бар, затем получаем на него указатель:
[highlight=cpp]
CProgressCtrl *PROG1=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
[/highlight]
Устанавливаем диапазон принимаемых значений:
[highlight=cpp]
PROG1->SetRange(0,COUNT);
[/highlight]
Устанавливаем величину шага:
[highlight=cpp]
PROG1->SetStep(1);
[/highlight]
Ставим сам индикатор на 0
[highlight=cpp]
PROG1->SetPos(0);
[/highlight]
И каждую итерацию делаем один шаг индикатора:
[highlight=cpp]
PROG1->StepIt();
[/highlight]

Maxus 17.08.2006 13:31

Re: Индикатор загрузки
 
[highlight=blitzbasic]
Graphics3D800,600,32,2
size_y# = 10
size_x# = 202
min# = 1
max# = 100
For i# = min To max
Color 255,0,0
Rect 20, 20, size_x, size_y, 0
Rect 22, 22, (i/max)*size_x-4, size_y-4, 1
Delay 30
Flip
Next[/highlight]
А вот модифицированный вариант.
Намного эффективнее.

impersonalis 17.08.2006 14:35

Re: Индикатор загрузки
 
И вот так ещё:
[highlight=blitzbasic]
Graphics3D 800,600,32,2
size_y# = 10
size_x# = 202
min# = 1
max# = 100
Color 255,0,0
Rect 20, 20, size_x, size_y, 0
For i# = min To max
Rect 22, 22, (i/max)*size_x-4, size_y-4, 1
Delay 30
Flip
Next
[/highlight]

Maxus 17.08.2006 18:33

Re: Индикатор загрузки
 
Цитата:

Сообщение от impersonalis
И вот так ещё:
[highlight=blitzbasic]
Graphics3D 800,600,32,2
size_y# = 10
size_x# = 202
min# = 1
max# = 100
Color 255,0,0
Rect 20, 20, size_x, size_y, 0
For i# = min To max
Rect 22, 22, (i/max)*size_x-4, size_y-4, 1
Delay 30
Flip
Next
[/highlight]

В твоем варианте невозможно будет преобразовать в функцию.
Да и прогрессбар по идее должен весь перерисовываться, а не по отдельности.


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

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot