Примеры элементов GUI
Решил поделиться своим меню. Материал написан скорее для новичков, тем более, что в свое время я искал такой материал с примерами, но не нашел.
http://www.boolean.name/archive/gadgets/gadjets.htm Старался описать функции по максимуму, если есть вопросы - пишите. В конце статьи есть пример для нетерпеливых. Он рассчитан на копипаст, потому без комментов.:pardon: |
Re: Примеры элементов GUI
Вложений: 1
Сорри, после переезда немогу отредактировать пост, добавляю аттач с уроком:
|
Re: Примеры элементов GUI
Вложений: 5
А для тех кому удобнее смотреть прямо в постах, скопирую сюда:
Интерактивные элементы интерфейса в примерах. Этот материал не претендует на оригинальность и не гарантирует ознакомление с эталонами алгоритмов построения меню, а также правильного написания функций интерактивных элементов интерфейса. Все ниже написанное взято из моих исходников и было написано без использования специальной литературы. Целью статьи является упрощение жизни начинающих блитцеров, ознакомление с готовыми функциями и как это работает . Ничто не мешает улучшить имеющиеся примеры и оптимизировать под свои потребности. Итак, самый первый интерактивный элемент в приложениях - это кнопка (по крайней мере, у меня было так :). Так же это самый простой элемент, возвращающий бинарное значение и использующийся в большинстве своем для моментальных действий, таких как перемещение по меню или применение параметров. Кнопка может быть как текстовой надписью, так и картинкой. Второе предпочтительнее, так как может иметь свой дизайн и требует меньше ресурсов. Однако для каждой кнопки в таком случае необходимо заготавливать свою картинку с названием. Оптимальным было бы генерировать картинки при загрузке меню, рендеря надписи на фоне картинки, но это по желанию. В моем случае такая подготовка не делалась, и на экран выводилась картинка кнопки, а поверх ее название. Для начала нам понадобятся некоторые картинки: |
Re: Примеры элементов GUI
а так же глобальные переменные для меню:
Global opt_apply=0 ;эта группа переменных - ключи возвращающие состояние кнопок Global save=0 ;«сохранить», «загрузить», «применить» для последующего перехода Global load=0 ;к этим функциям. Global exploration$=0 ;переменная для хранения текущей подсказки Global help_delay=0 ;счетчик задержки перед появлением подсказки Global maxhelp_delay=100 ;величина задержки Const RIC1=220,GIC1=180,BIC1=120 ;color1 цветовая палитра интерфейса Const RIC2=100,GIC2=100,BIC2=10 ;color2 в данном случае три оттенка: Const RIC3=45,GIC3=35,BIC3=25 ;color3 текст, рамка,фон Global TrackerImxSize=128 ;ширина выпадающего списка (нужно при использовании картинки) Global TrackerImySize=32 ;высота списка Global ButtonImxSize=128 ;ширина кнопки(в соответствии с шириной картинки) Global ButtonImySize=32 ;высота кнопки(тое в соответствии) Global CheckImSize=32 ;сторона чекбокса, используется квадратное изображение ;заранее считаем половины всех размеров Global TrackerImxHalfSize=TrackerImxSize*.5 Global ButtonImxHalfSize=ButtonImxSize*.5 Global TrackerImyHalfSize=TrackerImySize*.5 Global ButtonImyHalfSize=ButtonImySize*.5 Global CheckImHalfSize=CheckImSize*.5 ;кэш мыши, необходим для избавления от глюков и тормозов Global Mouse_HitX=0 ;координаты последнего клика мыши Global Mouse_HitY=0 Global Mouse_HitZ=0 ;то же для колесика Global Mouse_HitZold=0 Global Mouse_Hit=0 ;была ли нажата ЛКМ (левая кнопка мыши) Global Mouse_Hit2=0 ;грузим шрифты Global fnt1=LoadFont("Arial",18,True,True,False) Global fnt2=LoadFont("Arial Black",18,0,0,False) Global fnt3=LoadFont("Arial",32,True,0,False) ;картинки и путь к ним, изменить под ваши файлы Global GLBUIpath$="..\ui\" Global MenuButtonMPASS=LoadImage(GLBUIpath$+"buttpass.png ") Global MenuButtonMON=LoadImage(GLBUIpath$+"button.png") Global MenuButtonMPRESS=LoadImage(GLBUIpath$+"buttpress.p ng") Global MenuCheckOFF=LoadImage(GLBUIpath$+"CheckOFF.png") Global MenuCheckON=LoadImage(GLBUIpath$+"CheckON.png") Некоторые переменные не нужны непосредственно для кнопки, однако, чтобы не добавлять их с каждым элементом, я выложил сразу основные группы. |
Re: Примеры элементов GUI
Кнопка Сама функция:; atx – положение центра элемента на экране (в окне, если хотите) по горизонтали ; аty – то же по вертикали ; name$ - имя элемента ; expl$ - содержимое всплывающей подсказки ; clr – флаг активности кнопка (активна/отключена) ; state – здесь для специальных кнопок, вызывающих подфункцию ("сохранить", "старт") Function CrtMenuButton(atx,aty,name$,expl$,clr,state) ;button tx=atx-ButtonImxHalfSize ;координаты габаритов элемента, ty=aty-ButtonImyHalfSize ;левый верхний угол i=0 ;состояние кнопки: нажата/отпущена ;если мышь наведена на кнопку и кнопка активна, тогда If (Mouse_HitX>tx) And (Mouse_HitX<tx+ButtonImxSize) And (Mouse_HitY>ty) And (Mouse_HitY<ty+ButtonImySize) And clr Then ;если был ЛКМ, тогда показываем нажатую кнопку и применяем статус If Mouse_Hit Then DrawImage MenuButtonMPRESS, tx,ty,ty i=1 If state=1 opt_apply=1 ;apply Options If state=2 save =1 ;saving If state=3 load=1 ;loading Mouse_Hit=0 ;иначе показываем подсвеченную кнопку и запускаем счетчик задержки ;если мышь не сдвинется, по окончании счета появится подсказка Else DrawImage MenuButtonMON, tx,ty ;если счетчик достиг предела, копируем подсказку в ;обрабатываемую переменную If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ EndIf ;если мышь не наведена, рисуем простую, не подсвеченную кнопку Else DrawImage MenuButtonMPASS, tx,ty EndIf SetFont fnt2 Color 100-100*clr,100-100*clr,100-100*clr Text atx,aty,name$,1,1 ;подписываем кнопку Return I ;результат возвращаемый функцией - нажата кнопка или нет End Function Этот элемент возвращает бинарный результат. Однако существуют кнопки ("сохранить", "применить"..), для которых необходимо сразу же вызывать определенную функцию, не относящуюся к построению меню. Для этого, при создании кнопки, мы укажем ее тип, и в случае нажатия будет установлен один из ключей (save, load, opt_apply). |
Re: Примеры элементов GUI
Чекбокс Теперь давайте вспомним еще один графический элемент интерфейса, возвращающий бинарное значение, - чекбокс (CheckBoxGadget в визуале). По сути чекбокс - это ни что иное как кнопка с фиксатором положений (какие можно встретить на ЭЛТ мониторах и телевизорах). Можно было бы использовать картинку кнопки для этого элемента, но дабы разнообразить интерфейс, я рендернул в максе лампочку, как на приборной панели:Function CrtMenuCheck(atx,aty,name$,expl$,clr,state) ;check tx=atx-CheckImHalfSize ty=aty-CheckImHalfSize ;попадает ли курсор на чекбокс If (Mouse_HitX>tx) And (Mouse_HitX<tx+CheckImSize) And (Mouse_HitY>ty) And (Mouse_HitY<ty+CheckImSize) And clr Then ;если ЛКМ то инвертируем состояние (state здесь используется как состояние вкл/выкл)и рисуем соотв. картинку If state=0 Then DrawImage MenuCheckOFF,tx,ty Else If Mouse_Hit Then DrawImage MenuCheckOFF,tx,ty state=0 Mouse_Hit=0 If state=1 Then DrawImage MenuCheckON,tx,ty Else If Mouse_Hit Then DrawImage MenuCheckON,tx,ty state=1 Mouse_Hit=0 ;если счетчик достиг предела - назначаем подсказку If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ Else ;если не ЛКМ рисуем текущее состояние If state=0 Then DrawImage MenuCheckOFF,tx,ty If state=1 Then DrawImage MenuCheckON,tx,ty EndIf ;имя чекбокса справа от него SetFont fnt2 Color 100+150*clr,100+150*clr,100+150*clr Text atx+CheckImHalfSize,aty,name$,0,1 ;возвращаем состояние Return state End Function |
Re: Примеры элементов GUI
Система кнопок Чекбокс удобно использовать в опциях с двумя вариантами, например, для включения антиалайзинга, звука, спецэффектов или теней. Если же необходимо выбрать разрешение экрана, уровень деталей, сложность, мод или что-либо, имеющее более двух вариантов ответа, необходимо пользоваться другим методом. Первый из них основан на уже описанных выше элементах, и является системой кнопок, объединенных таким образом, что при нажатии на одну из них - она фиксируется во включенном положении, в то время как остальные - отключаются (RadioButtonGadget).Сам код: ;этот радиобаттн всего на три кнопки, если хотите сделать больше, ;необходимо добавить соответствующих элементов и параметров Function CrtMenuTracker(atx1,aty1,atx2,aty2,atx3,aty3,name1 $,name2$,name3$,typ,clr,state) tx1=atx1-TrackerImxHalfSize ;вычисляем положение для каждой картинки отдельно ty1=aty1-TrackerImyHalfSize ;предполагая что они могут быть разными по размеру tx2=atx2-TrackerImxHalfSize ;в нашем случае картинка одна ty2=aty2-TrackerImyHalfSize tx3=atx3-TrackerImxHalfSize ty3=aty3-TrackerImyHalfSize ;наведена ли мыщь и имеет ли место ЛКМ, соответственно рисуем картинку и меняем статус If ((Mouse_HitX>tx1) And (Mouse_HitX<tx1+TrackerImxSize) And (Mouse_HitY>ty1) And (Mouse_HitY<ty1+TrackerImySize) And clr) Then If Mouse_Hit Then DrawImage MenuButtonMPRESS, tx1,ty1 state=1 Mouse_Hit=0 Else DrawImage MenuButtonMON, tx1,ty1 Else DrawImage MenuButtonMPASS, tx1,ty1 EndIf ;то же для двух других кнопок If ((Mouse_HitX>tx2) And (Mouse_HitX<tx2+TrackerImxSize) And (Mouse_HitY>ty2) And (Mouse_HitY<ty2+TrackerImySize) And clr) Then If Mouse_Hit Then DrawImage MenuButtonMPRESS, tx2,ty2 state=2 Mouse_Hit=0 Else DrawImage MenuButtonMON, tx2,ty2 Else DrawImage MenuButtonMPASS, tx2,ty2 EndIf If ((Mouse_HitX>tx3) And (Mouse_HitX<tx3+TrackerImxSize) And (Mouse_HitY>ty3) And (Mouse_HitY<ty3+TrackerImySize) And clr) Then If Mouse_Hit Then DrawImage MenuButtonMPRESS, tx3,ty3 state=3 Mouse_Hit=0 Else DrawImage MenuButtonMON, tx3,ty3 Else DrawImage MenuButtonMPASS, tx3,ty3 EndIf ;если мышь вне кнопок, в зависимости от текущего состояния рисуем картинку активной кнопки If (state=1) Then DrawImage MenuButtonMPRESS, tx1,ty1 If (state=2) Then DrawImage MenuButtonMPRESS, tx2,ty2 If (state=3) Then DrawImage MenuButtonMPRESS, tx3,ty3 ;подписываем SetFont fnt2 Color 100-100*clr,100-100*clr,100-100*clr Text atx1,aty1,name1$,1,1 Color 100-100*clr,100-100*clr,100-100*clr Text atx2,aty2,name2$,1,1 Color 100-100*clr,100-100*clr,100-100*clr Text atx3,aty3,name3$,1,1 ;возвращаем текущее состояние Return state End Function |
Re: Примеры элементов GUI
Выпадающий свиток Визуально такой элемент является удобным и информативным, однако есть ситуации, где необходимо сделать выбор из десятка и более предложений. Вы, наверное, представили себе заполненный кнопками экран... Конечно, такой метод не годится для большого списка вариантов ответов. Для этих целей было бы неплохо создать динамический элемент, показывающий весь список ответов только при необходимости. Напишем свиток, а для него введем еще переменную:Global svit1=0 Она будет отвечать за состояние этого (и только) свитка. Если у вас два свитка в меню, добавьте еще одну переменную. Приступим к созданию выпадающего свитка: Function TrackerShort5_1(atx,aty,sizx,sizy,name1$,name2$,na me3$,name4$,name5$,expl$,typ,clr,state) ;switcher x5 If state=1 name$=name1$ ;этот выпадающий список рассчитан на максимум пять вариантов If state=2 name$=name2$ ;в случае, если вам необходимо больше, добавьте переменных If state=3 name$=name3$ ;name6$, name7$ и т.д. везде, где присутствуют name1$ - name5$. If state=4 name$=name4$ ;если же вы будете использовать меньше максимума - 4, просто при вызове If state=5 name$=name5$ ;функции вместо названия для name5$ укажите ноль ;если typ=1 то рисуем кнопку, она будет рамкой для списка If typ DrawImage MenuButtonMPASS, atx-5,aty-5 ;проверяем переменные начиная с конца, если находим ноль - уменьшаем список If name5$ Then d=5 Else If name4$ Then d=4 Else If name3$ Then d=3 Else If name2$ Then d=2 Else If name1$ Then d=1 Else d=0 ;проверяем наведена ли мышь на основное поле свитка If ((Mouse_HitX>atx) And (Mouse_HitX<atx+sizx) And (Mouse_HitY>aty) And (Mouse_HitY<aty+sizy) And clr) Then If Mouse_Hit Then ;если да и ЛКМ - ставим ключ что свиток развернут svit1=1 Mouse_Hit=0 Else ;если да но нет ЛКМ, рисуем нажатую кнопку и проверяем счетчик подсказки If typ DrawImage MenuButtonMON, atx-5,aty-5 If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ EndIf Else ;иначе если клик вне списка - сворачиваем его If Mouse_Hit And ((Mouse_HitX<atx) Or (Mouse_HitX>atx+sizx) Or (Mouse_HitY<aty) Or (Mouse_HitY>aty+sizy*(d+1))) Then svit1=0 EndIf Color 100-100*clr,100-100*clr,100-100*clr ;пишем в основном поле имя активного элемента списка Text atx+sizx*.5,aty+sizy*.5,name$,1,1 If svit1 ;если свиток развернут, рисуем фон для списка Color 0,0,0 Rect atx,aty+sizy,sizx,sizy*d,1 Color RIC1,GIC1,BIC1 Rect atx,aty,sizx,sizy*(d+1),0 ;подсвечиваем элемент списка что сейчас под курсором мышки For i=1 To d If (Mouse_HitX>atx) And (Mouse_HitX<atx+sizx) And (Mouse_HitY>aty+sizy*i) And (Mouse_HitY<aty+sizy*(i+1)) Then Color RIC3,GIC3,BIC3 Rect atx+1,aty+1+sizy*i,sizx-2,sizy-2,1 If Mouse_Hit Then state=(Mouse_HitY-aty)/sizy svit1=0 ;если ЛКМ, получаем номер выбранного элемента EndIf Next ;теперь выводим имена элементов в списке Color RIC1,GIC1,BIC1 t=atx+sizx*.5 If d>0 Text t,aty+sizy*1+sizy*.5,name1$,1,1 If d>1 Text t,aty+sizy*2+sizy*.5,name2$,1,1 If d>2 Text t,aty+sizy*3+sizy*.5,name3$,1,1 If d>3 Text t,aty+sizy*4+sizy*.5,name4$,1,1 If d>4 Text t,aty+sizy*5+sizy*.5,name5$,1,1 EndIf Return state End Function |
Re: Примеры элементов GUI
Цифры Все ранее описанное является большей частью основы графического интерфейса. Эти элементы используются практически во всех играх и приложениях, и прекрасно ведут себя с небольшим количеством (от одного до десятков), как правило, заранее определенных значений. Однако этого не достаточно, когда необходимо изменить уровень чего-то (звук, гамма, цвет чего-либо..) или выбрать какое-либо числовое значение в гораздо больших пределах (количество очков, время за раунд, число респаунов или патронов). Для этого я написал простейший числовой счетчик с индикацией. Он не предоставляет возможности вводить свое значение, но зажав на нем ЛКМ, вы можете прокручивать значение. Так же такой счетчик не сложно изменить под графическое отображение "конька". Для следующих примеров я использовал еще две переменные: Global GWeit=800Global GHeit=600 В моем случае они хранили разрешение экрана и использовались для определения положения графических элементов, и возвращения размера вьюпорта во весь экран: ;param - текущее значение в счетчике ;value - максимальное значение счетчика, счет идет с нуля Function CrtMenuRott(atx,aty,name$,expl$,typ,clr,param,valu e) ;rott slider 0~value tx=atx-CheckImHalfSize ;определение координат рабочей области, картинка не используется ty=aty-CheckImHalfSize newparam=param Color RIC3,GIC3,BIC3 ClsColor RIC3,GIC3,BIC3 Rect atx-20,aty-10,40,20,1 ;рисуем прямоугольник рабочей области Color RIC1,GIC1,BIC1 ;проверка наведен ли курсор If ((Mouse_HitX>tx) And (Mouse_HitX<tx+CheckImSize) And (Mouse_HitY>ty) And (Mouse_HitY<ty+CheckImSize) And clr) Then tempx=MouseX() ;создаем временный кеш2 для мыши tempy=MouseY() Viewport atx-20, aty-10, 40, 20 ;переключаемся на отображение только рабочей области While (MouseDown(1)) ;пока нажата мышь, меняем значение счетчика на дельту кеш-кеш2 Cls If (param>=0 And param<=value) Then newparam=param+(MouseX()-tempx)-(MouseY()-tempy) If newparam>value newparam=value If newparam<0 newparam=0 EndIf Text atx,aty,newparam,1,1 Flip Wend Mouse_Hit=0 ;обнуляем переменные, возвращаем вьюпорт на место, проверяем счетчик подсказки Viewport 0, 0, GWeit, GHeit If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ EndIf SetFont fnt2 ;прописываем параметр и его имя сверху, возвращаем результат Text atx,aty,newparam,1,1 Color 100+150*clr,100+150*clr,100+150*clr Text atx,aty-16,name$,1,1 Return newparam End Function |
Re: Примеры элементов GUI
Ввод Итак, у нас есть основные элементы выбора готовых значений и цифр, однако нам еще кое-чего не хватает. Если вы вдруг захотите, чтобы игрок мог ввести свое имя перед игрой, указать IP адрес сервера или же назвать файл своего сохранения, вам понадобится функция, обеспечивающая ввод символов прямо с клавиатуры. Ниже приведен пример простенького, но все же рабочего элемента с полем ввода символов:;функция ввода до max символов с начальным значением word$ Function CrtMenuInput$(atx,aty,name$,expl$,typ,clr,word$,ma x) ;Input Len=20 SetFont fnt2 ;устанавливаем шрифт half_letter=5 ;реальная ширина одной буквы используемого шрифта в пикселях, Input_size=max*half_letter ;для расчета ширины поля newword$=word$ num=Len(word$)+1 ;узнаем количество символов в текущем слове (числовом значении) savename=CreateBank(max+5) ;создаем банк памяти для динамической работы с newsymbol=32 ;определенным количеством значений и временный символ Color RIC3,GIC3,BIC3 ClsColor RIC3,GIC3,BIC3 Rect atx-Input_size,aty-10,Input_size*2,20,1 ;определяем область ввода и рисуем фон для текста Color RIC1,GIC1,BIC1 TC=0 ;переменная для смена цвета текста во время ввода For i=1 To num ;заносим текущее слово в банк для работы с ним k$=Mid$(newword$,i,1) PokeByte savename,i, Asc(k$) Next For i=num To max ;заполняем оставшуюся длину пробелами PokeByte savename,i, 32 Next Text atx,aty,newword$,1,1 ;вывод текущего слова на экран If ((Mouse_HitX>atx-Input_size) And (Mouse_HitX<atx+Input_size) And (Mouse_HitY>aty-10) And (Mouse_HitY<aty+10) And clr) Then ;проверяем наведен ли курсор на рабочую область TC=70 ;если да, изменяем цвет текста If (Mouse_Hit) ;если ЛКМ, обнуляем буффер клавы и мыши, Mouse_Hit=0 ;переводим вьюпорт на рабочую область Flip 0 FlushKeys() Viewport atx-Input_size, aty-10, Input_size*2, 20 While Not KeyHit(28) ;пока не нажали ввод Cls newsymbol=WaitKey() ;ждем ввода символа и If (newsymbol=8) Then ;если нажат BACKSPACE то If num>1 Then ;если символы еще есть num=num-1 ;уменьшаем их количество PokeByte savename,num,32 ;меняем символ в конце слова на пробел EndIf Else If (newsymbol=27) Then ;если нажат ESCAPE то выходим из функции возвращая newword$=word$ ;первоначальное слово Text atx,aty,newword$,1,1 Viewport 0, 0, GWeit, GHeit ;возвращаем вьюпорт на весь экран FreeBank savename Return word$ EndIf If (newsymbol>31) And (newsymbol<127) And (num<max+1) Then ;если нажат допустимый PokeByte savename,num,newsymbol ;символ и есть куда писать, добавляем его к слову num=num+1 EndIf EndIf newword$ = "" ;обнуляем временное слово For j=1 To max ;и заполняем символами из банка интерпретируя коды newword$ = newword$+Chr(PeekByte (savename,j)) Next Text atx,aty,newword$,1,1 ;выводим результат Flip 0 Wend Viewport 0, 0, GWeit, GHeit ;возвращаем вьюпорт на весь экран EndIf If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ ;проверяем счетчик подсказки EndIf Color RIC1+TC,GIC1+TC,BIC1+TC*.5 Text atx,aty,newword$,1,1 ;выводим в рабочую область слово newword$=Trim$(newword$) ;обрезаем пробелы в конце слова FreeBank savename ;освобождаем банк Return newword$ ;возвращаем результат End Function |
Re: Примеры элементов GUI
На этом пожалуй все, хотя нет, я упоминаю в каждом куске кода о подсказке при наведении мыши на элемент. Для его работы необходимо в функцию меню (там где используете графические элементы) добавить следующие строчки (в начало):
If MouseHit(1) Mouse_Hit=1 OMouse_HitX=Mouse_HitX OMouse_HitY=Mouse_HitY Mouse_HitX=MouseX() Mouse_HitY=MouseY() If (OMouse_HitX=Mouse_HitX And OMouse_HitY=Mouse_HitY) Then If help_delay<maxhelp_delay Then help_delay=help_delay+1 EndIf Else help_delay=0 exploration$=0 EndIf А после вызова всех элементов: If exploration$<>0 ShowHelp(Mouse_HitX,Mouse_HitY,exploration$) И сама функция с расчетом положения относительно краев экрана: Function ShowHelp(x,y,txt$) lt=ch_size*Len(txt$)/2 ;просчитываем, какую область покажет подсказка ltt=lt*.5 Color RIC3,GIC3,BIC3 If x>GWeit-ltt Then xt=x-lt Else If x<ltt Then xt=x Else xt=x-ltt ;если выходит за экран, If y<ch_size Then yt=y+ch_size+24 Else yt=y ;переносим в другое место Rect xt,yt-ch_size,lt,ch_size,1 Color RIC2,GIC2,BIC2 Rect xt,yt-ch_size,lt,ch_size,0 Color RIC1,GIC1,BIC1 Text xt+ltt,yt-ch_size,txt$,1,0 End Function |
Re: Примеры элементов GUI
Дополнения от АВТОМАТа: 1) Дам несколько комментариев к статье, которые помогут, на мой взгляд, упростить код: If state=1 opt_apply=1 ;apply OptionsIf state=2 save =1 ;saving If state=3 load=1 ;loading Здесь, по моему мнению, использование Ифов (If … End If) можно заменить на более простой Select … Case: Select state ; выбираем переменную stateCase 1 opt_apply=1 ; Если она равна 1, то ставим opt_apply = 1 Case 2 save =1 ; В случае, если она равна двум, то save = 1 Case 3 load=1 ; Если же 3, то load = 1 End select 2) Насчет координат элементов: ИМХО, удобнее и привычнее было бы указывать кнопкам не координаты их середин, а координаты их левого верхнего угла: так делают во многих визуальных редакторах интерфейса (в Delphi, например) - это поможет нам избавиться от переменных:Global TrackerImxHalfSize=TrackerImxSize*.5 Global ButtonImxHalfSize=ButtonImxSize*.5 Global TrackerImyHalfSize=TrackerImySize*.5 Global ButtonImyHalfSize=ButtonImySize*.5 Global CheckImHalfSize=CheckImSize*.5 Не нужно будет вычислять левый край элемента (он у нас будет непосредственно передаваться в функцию), на примере кнопки: tx=atx-ButtonImxHalfSize ;координаты габаритов элемента, ty=aty-ButtonImyHalfSize ;левый верхний угол и при проверке - наведен ли курсор на кнопку - вместо tx подставляем atx : If (Mouse_HitX>atx) And (Mouse_HitX<atx+ButtonImxSize) And (Mouse_HitY>aty) And (Mouse_HitY<aty+ButtonImySize) And clr Then |
Re: Примеры элементов GUI
От автора:
Привожу эти комментарии как пример того, что вы можете писать и оформлять функции элементов, как вам будет удобно. Внесу однако некоторые пояснения насчет второго пункта. Экономия количества переменных и просчетов окупится только в случае, если элементы графического интерфейса привязаны, например, к окнам или панелям, не меняющимся в размере и не зависящим от разрешения экрана. В моем же случае я поступал именно так, пока не "полезли косяки" при смене разрешений. Для того, чтобы элементы не выходили за экран и не оставляли пустых мест при смене разрешения, пришлось разбить экран на виртуальную сетку координат и позиционировать все меню по ней, располагая центры элементов по пересечениям сетки. Так, например, ряд кнопок при смене разрешения будет равномерно сжиматься или вытягиваться, а так же можно легко установить элемент по центру экрана или любой панели, нарисованной по той же сетке. И в конце приведу вам исходник (не рабочую версию игры, а часть ее интерфейса), как пример использования элементов без картинок. Просто скопируйте код в Блитц и запускайте: Global GWeit=200Global GHeit=200 Global life,have_pitomec,want_noeat,want_sleep,want_play Global Mouse_HitX=0 Global Mouse_HitY=0 Global Mouse_Hit=0 Global G_Menu=0 Global G_Exit=0 Global xq=GWeit/20 Global yq=GHeit/20 Global ch_size1=11 Global ch_size2=16 Global ch_size3=20 Global ch_size=ch_size1 Global RIC=160:Global GIC=170:Global BIC=255 Global RIC1=45:Global GIC1=45:Global BIC1=85 life=100:have_pitomec=0:want_noeat=10:want_sleep=5 0:want_play=20 Global opt_apply=1 ;apply Options Global opt_reset=1 ;reset changes in options Global Winstate=1 Global help_delay=0 Global maxhelp_delay=60 Global exploration$=0 Global svit1=0:Global svit2=0:Global svit3=0:Global svit4=0:Global svit5=0:Global svit6=0:Global svit7=0: Global guizone=0 Graphics3D GWeit,GHeit,32,2 Global fnt=LoadFont("Arial",ch_size,1,0,0) SetFont fnt While (Not (G_Exit)) Cls UpdateWorld RenderWorld If Not(have_pitomec) Then mainmenu() Color RIC,GIC,BIC Text 6,45,"TRIS: "+TrisRendered()+have_pitomec Rect 3,38,GWeit-6,GHeit-yq*2-38,0 gui() Flip 0 Wend End Function gui() Color RIC,GIC,BIC Text GWeit*.5,GHeit-yq*3,"FREEMEN studio ©",1,1 If MouseHit(1) Mouse_Hit=1 OMouse_HitX=Mouse_HitX OMouse_HitY=Mouse_HitY Mouse_HitX=MouseX() Mouse_HitY=MouseY() If (OMouse_HitX=Mouse_HitX And OMouse_HitY=Mouse_HitY) Then If help_delay<maxhelp_delay Then help_delay=help_delay+1 EndIf Else help_delay=0 exploration$=0 EndIf If guizone = 0 Then guizone=guizone+button(xq*1,yq*18.5,xq*3,yq,"еда", 0,1,0,"накормите питомца")*1+button(xq*5,yq*18.5,xq*3,yq,"игра",0,0 ,0,0)*2+button(xq*9,yq*18.5,xq*3,yq,"аптека",0,0,0 ,0)*3 If button(xq*16,yq*18.5,xq*3,yq,"меню",0,1,0,"выйти в главное меню") mainmenu() EndIf If guizone = 1 Then If button(xq*1,yq*18.5,xq*3,yq,"молоко",0,1,0,"придае т сил и уверенности") And (want_sleep<90) Then want_noeat=want_noeat+7 want_sleep=want_sleep+3 want_play=want_play+15 life=life+10 If button(xq*5,yq*18.5,xq*3,yq,"мясо",0,1,0,"самая сытная еда") And (want_sleep<70) Then want_noeat=want_noeat+20 want_sleep=want_sleep+28 want_play=want_play-8 life=life+4 If button(xq*9,yq*18.5,xq*3,yq,"рыба",0,1,0,"любимое всеми кошками") And (want_sleep<90) Then want_noeat=want_noeat+15 want_sleep=want_sleep+18 want_play=want_play+4 life=life+1 If button(xq*16,yq*18.5,xq*3,yq,"назад",0,1,0,"вернут ься") guizone=0 If want_noeat>100 want_sleep=want_sleep+18 want_play=want_play-2*(want_noeat-100) life=life-(want_noeat-100) want_noeat=100 If want_sleep>100 want_play=0 want_sleep=100 If want_play>100 want_play=100 If life>100 want_play=want_play+life-100 life=100 EndIf ShowLine() If exploration$<>0 ShowHelp(Mouse_HitX,Mouse_HitY,exploration$) Flip If (Mouse_HitX<>MouseX() Or Mouse_HitY<>MouseY()) Then Mouse_Hit=0 FlushMouse End Function Function ShowHelp(x,y,txt$) lt=ch_size*Len(txt$)/2 ltt=lt*.5 Color RIC1,GIC1,BIC1 If x>GWeit-ltt Then xt=x-lt Else If x<ltt Then xt=x Else xt=x-ltt If y<ch_size Then yt=y+ch_size+24 Else yt=y Rect xt,yt-ch_size,lt,ch_size,1 Color 230,200,100 Text xt+ltt,yt-ch_size,txt$,1,0 End Function Function ShowLine() Color 220,10,10 Rect 20,4,(GWeit-26)*.01*life,6 Color 220,120,10 Rect 20,12,(GWeit-26)*.01*want_noeat,6 Color 10,160,10 Rect 20,20,(GWeit-26)*.01*want_play,6 Color 30,30,250 Rect 20,28,(GWeit-26)*.01*want_sleep,6 If Mouse_HitY<11 And help_delay=maxhelp_delay Then exploration$="pet's life" Else If Mouse_HitY<20 And help_delay=maxhelp_delay Then exploration$="pet's satiety" Else If Mouse_HitY<29 And help_delay=maxhelp_delay Then exploration$="pet's joy" Else If Mouse_HitY<36 And help_delay=maxhelp_delay Then exploration$="pet's desire to sleep" EndIf EndIf EndIf EndIf End Function Function mainmenu() G_Menu=1 FlushMouse Mouse_Hit=0 menuzone = 2 While (G_Menu) RenderWorld Color RIC,GIC,BIC Rect 3,3,GWeit-6,GHeit-yq*2-3,0 Text GWeit*.5,GHeit-yq*3,"FREEMEN studio ©",1,1 If MouseHit(1) Mouse_Hit=1 OMouse_HitX=Mouse_HitX OMouse_HitY=Mouse_HitY Mouse_HitX=MouseX() Mouse_HitY=MouseY() If (OMouse_HitX=Mouse_HitX And OMouse_HitY=Mouse_HitY) Then If help_delay<maxhelp_delay Then help_delay=help_delay+1 EndIf Else help_delay=0 exploration$=0 EndIf If menuzone = 2 Then menuzone=menuzone+button(xq*5,yq*18.5,xq*3,yq,"opt ion",0,1,0,"опции")*1+button(xq*9,yq*18.5,xq*3,yq, "back",0,have_pitomec,0,"назад")*-1+button(xq*16,yq*18.5,xq*3,yq,"quit",0,1,0,"выход ")*-2 If button(xq*1,yq*18.5,xq*3,yq,"start",0,1,0,"начать игру") Then have_pitomec=1 G_Menu=0 EndIf ;options If menuzone = 3 Then menuzone=menuzone+button(xq*1,yq*18.5,xq*3,yq,"res et",0,0,2,0)*0+button(xq*5,yq*18.5,xq*3,yq,"accept ",0,1,1,"применить")*-1+button(xq*16,yq*18.5,xq*3,yq,"discard",0,1,0,"от мена")*-1 Winstate=TrackerShort5_1(xq,yq,xq*4,yq*2,"200x200" ,"300x300","400x400",0,0,0,1,Winstate) EndIf If menuzone = 4 Then menuzone=menuzone+button(xq*1,yq*18.5,xq*3,yq,"sta rt",0,1,0,"начать игру")*0+button(xq*5,yq*18.5,xq*3,yq,"option",0,1, 0,"опции")*0 EndIf If menuzone = 1 Then G_Menu=0 If menuzone = 0 Then G_Menu=0 G_Exit=1 If opt_apply If Winstate=1 GWeit=200 GHeit=200 If Winstate=2 GWeit=300 GHeit=300 If Winstate=3 GWeit=400 GHeit=400 FreeFont fnt xq=GWeit/20:yq=GHeit/20 Graphics3D GWeit,GHeit,32,2 If Winstate=1 ch_size=ch_size1 If Winstate=2 ch_size=ch_size2 If Winstate=3 ch_size=ch_size3 fnt=LoadFont("Arial",ch_size,1,0,0) SetFont fnt opt_apply=0 EndIf If opt_reset opt_reset=0 EndIf If exploration$<>0 ShowHelp(Mouse_HitX,Mouse_HitY,exploration$) Flip ClsColor 0,0,0 Cls If (Mouse_HitX<>MouseX() Or Mouse_HitY<>MouseY()) Then Mouse_Hit=0 FlushMouse Wend End Function Function button(atx,aty,sizx,sizy,name$,typ,clr,state,expl$ ) i=0 Color 200,200,200 Rect atx-3,aty-3,sizx+6,sizy+6,0 If (Mouse_HitX>atx) And (Mouse_HitX<atx+sizx) And (Mouse_HitY>aty) And (Mouse_HitY<aty+sizy) And clr Then If Mouse_Hit Then Color RIC,GIC,BIC Rect atx,aty,sizx,sizy,1 i=1 If state=1 opt_apply=1 ;apply Options If state=2 opt_reset=1 ;apply changes in Edit Mouse_Hit=0 Else If expl$<>0 And help_delay=maxhelp_delay Then exploration$=expl$ EndIf Color 255,255,255 Rect atx,aty,sizx,sizy,1 EndIf Else Color RIC,GIC,BIC Rect atx,aty,sizx,sizy,1 EndIf Color 100-100*clr,100-100*clr,100+100*clr Text atx+sizx*.5,aty+sizy*.5,name$,1,1 Return i End Function Function TrackerShort5_1(atx,aty,sizx,sizy,name1$,name2$,na me3$,name4$,name5$,typ,clr,state) ;switcher1 x5 If state=1 name$=name1$ If state=2 name$=name2$ If state=3 name$=name3$ If state=4 name$=name4$ If state=5 name$=name5$ If name5$ Then d=5 Else If name4$ Then d=4 Else If name3$ Then d=3 Else If name2$ Then d=2 Else If name1$ Then d=1 Else d=0 If ((Mouse_HitX>atx) And (Mouse_HitX<atx+sizx) And (Mouse_HitY>aty) And (Mouse_HitY<aty+sizy) And clr) Then If Mouse_Hit Then svit1=1 Else Color RIC1,GIC1,BIC1 Rect atx+1,aty+1,sizx-2,sizy-2,1 EndIf Else If Mouse_Hit And ((Mouse_HitX<atx) Or (Mouse_HitX>atx+sizx) Or (Mouse_HitY<aty+sizy) Or (Mouse_HitY>aty+sizy*(d+1))) Then svit1=0 ;Color 0,0,0 Rect atx,aty,sizx,sizy,1 EndIf Color RIC,GIC,BIC Rect atx,aty,sizx,sizy,0 Text atx+sizx*.5,aty+sizy*.5,name$,1,1 ; If svit1 Color 0,0,0 Rect atx,aty+sizy,sizx,sizy*d,1 Color RIC,GIC,BIC Rect atx,aty,sizx,sizy*(d+1),0 For i=1 To d If (Mouse_HitX>atx) And (Mouse_HitX<atx+sizx) And (Mouse_HitY>aty+sizy*i) And (Mouse_HitY<aty+sizy*(i+1)) Then Color RIC1,GIC1,BIC1 Rect atx+1,aty+1+sizy*i,sizx-2,sizy-2,1 If Mouse_Hit Then state=(Mouse_HitY-aty)/sizy svit1=0 EndIf Next Color RIC,GIC,BIC t=atx+sizx*.5 If d>0 Text t,aty+sizy*1+sizy*.5,name1$,1,1 If d>1 Text t,aty+sizy*2+sizy*.5,name2$,1,1 If d>2 Text t,aty+sizy*3+sizy*.5,name3$,1,1 If d>3 Text t,aty+sizy*4+sizy*.5,name4$,1,1 If d>4 Text t,aty+sizy*5+sizy*.5,name5$,1,1 EndIf Text 100,10,state+" "+(Mouse_HitY-aty)/sizy,1,1 Return state End Function В исходнике нет комментов, но построен он на тех же функциях, что описаны выше. Удачи! |
Re: Примеры элементов GUI
Можете оставлять комменты и варианты оптимизации, вобщем все что поможет пользователю. Критику кривости кода можете написать в личку, а сюда по делу. :)
И напомню что во втором посте есть этот урок аттачем, в более наглядной форме. |
Ответ: Примеры элементов GUI
Все не осилил, но определенно "в мемориз". То есть в журнал к Матвею.
|
Часовой пояс GMT +4, время: 07:03. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot