000112. Делаем графическое меню

Делаем графическое меню|Всем привет! Этот урок я делаю по заказу многих пользователей нашего сайта. Сегодня будем учиться рисовать меню.|wmysterio|wmysterio||||Как вариант, можно было сделать с помощью панелей, но наша задача сегодня состоит в следующем: написать скрипт драки, где игроку нужно выбрать себе бойца. Иконки участников я возьму со стандартного TXD-архива - обычные карты, что были при игре в покер.

Прежде всего определим размер текстур. Они составили 128 пикселей.

Как уже звучало в уроке по рисованию ранее, размер экрана в GTA SA - 640х448. Сделаем арифметические расчёты, что бы определить к-во картинок, которые поместятся на экран: 640/128 = 5. Такое количество бойцов меня не устроило, так как желательным результатом для меня - 7 персонажей. Следовательно нам нужно рисовать текстуры с меньшем размером. Я подсчитал, что размер должен быть - 64, мы получим 10 бойцов в экране. Так как этого многовато, то с 640 - ( 7*64 ) = 192 пикселей можно равномерно отдалить картинки друг от друга. С размерами определились.

Следующим шагом будет выбор места и условий запуска меню. Я выбрал автошколу в Сан Фиерро. Вот блок условий в нашем скрипте:

{$CLEO}
0000:

var
$PLAYER_ACTOR: actor
$PLAYER_CHAR: player
end

:BOXEN
thread 'BOXEN'
wait 0

while true
 03A1: show_sphere_at -2039.1498 -106.7122 34.191 radius 1.5
 if AND
 0AB0: key_pressed 71 // G
 00EC: actor $PLAYER_ACTOR 0 near_point -2039.1498 -106.7122 radius 2.0 2.0
 then
 if AND
 8A0C: not player $PLAYER_CHAR on_jetpack
 $ONMISSION == 0
 then
 gosub @BOXEN_INIT
 wait 1000
 end 
 end 
wait 0
end

:BOXEN_INIT
wait 0

Следующий шаг - загрузка текстур, объявление переменных:

0390: load_txd_dictionary 'LD_POKE'
038F: load_texture "cd13s" as 1
038F: load_texture "cd13h" as 2
038F: load_texture "cd13d" as 3
038F: load_texture "cd13c" as 4
038F: load_texture "cd11s" as 5
038F: load_texture "cd11h" as 6
038F: load_texture "cd11d" as 7 // 128 > 64
30@ = 0
0826: enable_hud 0
0581: enable_radar 0
$PLAYER_CHAR.CanMove = false
$PLAYER_ACTOR.SetImmunities(1, 1, 1, 1, 1)
wait 1000
0@ = 0 // switch
1@ = 64 // texture 1
2@ = 64 // texture 2
3@ = 64 // texture 3
4@ = 64 // texture 4
5@ = 64 // texture 5
6@ = 64 // texture 6
7@ = 64 // texture 7
8@ = #WMYDRUG // model enemy
9@ = 0.0
10@s = 'BJ_PUSH'

Объясню, какая переменная для чего нужна:

30@ = 0 - переменная, которая будет условием цикла. Я использую переменную а не true, так как при срабатывании разных условий, мы можем сделать ещё некоторые проверки после цикла и изменить ветвь алгоритма. 0@ = 0 // switch - Эта переменная будет использовать в таблице переходов. Собственно она будет делать наше меню, так как в зависимости от неё будет изменятся прозрачность нашей текстуры. Так как наше меню будет состоять из 7 участников, то к-во пунктов меню тоже будет равна цифре 7, а значения, которые будет принимать - 0, 1, 2, 3, 4, 5 и 6. 1@ ... 7@ - указываем значение прозрачности для загруженных нами текстур на значение 64. Таким образом прозрачность пункта меню, который не выбран будет равен этому значению. 8@ = #WMYDRUG // model enemy - переменная будет менять модель актёра, который будет нашим противником 10@s = 'BJ_PUSH' - строковая переменная носит имя нашего противника и так же меняется в зависимости от выбранного пункта меню. 9@ = 0.0 - переменная отвечает за переключатель меню. Что бы пользователь без проблем мог двигаться по меню, нужно удержать отклик на величину 0.25. Когда переменная будет иметь значения 0.0 1.0 2.0 3.0 4.0 5.0 6.0, то переменная 0@ будет иметь такое же значение, что и 9@, только в целой форме.

Создадим цикл, где укажем условия выхода и условия изменения 0@:

while 30@ == 0
 if OR // EXIT
 0AB0: key_pressed 71 // G
 $PLAYER_ACTOR.Dead
 0741: actor $PLAYER_ACTOR busted
 09FA: is_menu_closed
 then
 30@ = -1
 end

 if
 9@ == 0.0
 then
 0@ = 0
 end 
 if
 9@ == 1.0
 then
 0@ = 1
 end
 if
 9@ == 2.0
 then
 0@ = 2
 end
 if
 9@ == 3.0
 then
 0@ = 3
 end
 if
 9@ == 4.0
 then
 0@ = 4
 end
 if
 9@ == 5.0
 then
 0@ = 5
 end
 if
 9@ == 6.0
 then
 0@ = 6
 end 


// // // Цикл продолжается // // //

wait 0
end

Нужно так же учесть, что если игрок выведет переменные "0@" и "9@" за нужный диапазон, то текстуры пропадут с экран, так как их нужно рисовать в цикле при точных условиях. Нужно написать условия, которые не дают выйти значениям за нужные рамки. В моём случае это такой код:

if
9@ > 6.75
then
9@ = 0.0
end
 
if
9@ < -0.75
then
9@ = 6.0
end

Осталось нам написать управление переменной "9@". Я сделал, что при нажатии левой или правой стрелки значение уменьшалось или увеличивалось соответственно:

 { NAVIGATE }
 if
 0AB0: key_pressed 37 // LEFT
 then
 9@ -= 0.25
 end
 if
 0AB0: key_pressed 39 // RIGNT
 then
 9@ += 0.25
 end

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

 { SWITCH BOXER }
 0871: init_jump_table 0@ total_jumps 7 default_jump 0 @BOXING_SELECT jumps 0 @BOXING_S_0 1 @BOXING_S_1 2 @BOXING_S_2 3 @BOXING_S_3 4 @BOXING_S_4 5 @BOXING_S_5 6 @BOXING_S_6
 
 :BOXING_S_0
 8@ = #WMYDRUG // model enemy
 1@ = 255 // texture 1
 2@ = 64 // texture 2
 3@ = 64 // texture 3
 4@ = 64 // texture 4
 5@ = 64 // texture 5
 6@ = 64 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_001'
 jump @BOXING_SELECT
 
 :BOXING_S_1
 8@ = #BMYDRUG // model enemy
 1@ = 64 // texture 1
 2@ = 255 // texture 2
 3@ = 64 // texture 3
 4@ = 64 // texture 4
 5@ = 64 // texture 5
 6@ = 64 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_002'
 jump @BOXING_SELECT
 
 :BOXING_S_2
 8@ = #HMYDRUG // model enemy
 1@ = 64 // texture 1
 2@ = 64 // texture 2
 3@ = 255 // texture 3
 4@ = 64 // texture 4
 5@ = 64 // texture 5
 6@ = 64 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_003'
 jump @BOXING_SELECT
 
 :BOXING_S_3
 8@ = #WMYCLOT // model enemy
 1@ = 64 // texture 1
 2@ = 64 // texture 2
 3@ = 64 // texture 3
 4@ = 255 // texture 4
 5@ = 64 // texture 5
 6@ = 64 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_004' 
 jump @BOXING_SELECT
 
 :BOXING_S_4
 8@ = #WMYST // model enemy
 1@ = 64 // texture 1
 2@ = 64 // texture 2
 3@ = 64 // texture 3
 4@ = 64 // texture 4
 5@ = 255 // texture 5
 6@ = 64 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_005' 
 jump @BOXING_SELECT
 
 :BOXING_S_5
 8@ = #HFORI // model enemy
 1@ = 64 // texture 1
 2@ = 64 // texture 2
 3@ = 64 // texture 3
 4@ = 64 // texture 4
 5@ = 64 // texture 5
 6@ = 255 // texture 6
 7@ = 64 // texture 7 
 10@s = 'BOX_006'
 jump @BOXING_SELECT
 
 :BOXING_S_6
 8@ = #HMOST // model enemy
 1@ = 64 // texture 1
 2@ = 64 // texture 2
 3@ = 64 // texture 3
 4@ = 64 // texture 4
 5@ = 64 // texture 5
 6@ = 64 // texture 6
 7@ = 255 // texture 7 
 10@s = 'BOX_007'
 jump @BOXING_SELECT

Модели персонажей я подбирал от фонаря: что помнил то и писал. Вы же можете подставить свои. Рисуем наше меню:

 :BOXING_SELECT 
 03F0: enable_text_draw 1
 038E: draw_box_position 311.8006 188.2005 size 542.60 102.60 RGBA 0 0 0 128 
 038E: draw_box_position 312.0 223.2 size 529.196 22.8 RGBA 0 0 0 128
 0340: set_text_draw_RGBA 180 180 180 255
 081C: draw_text_outline 1 RGBA 255 0 0 255 // Red Outkine
 0349: set_text_draw_font 2
 0343: set_text_draw_linewidth 640.0
 033E: set_draw_text_position 79.0 218.0 GXT 10@s // Push 
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 1 position 79.1995 174.8 size 64.0 64.0 RGBA 255 255 255 1@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 2 position 158.2 174.8 size 64.0 64.0 RGBA 255 255 255 2@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 3 position 235.8 174.8 size 64.0 64.0001 RGBA 255 255 255 3@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 4 position 312.799 174.6 size 64.0 64.0 RGBA 255 255 255 4@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 5 position 389.398 174.6 size 64.0 64.0 RGBA 255 255 255 5@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 6 position 466.997 174.6 size 64.0 64.0 RGBA 255 255 255 6@
 03E3: set_texture_to_be_drawn_antialiased 1
 038D: draw_texture 7 position 544.596 174.4 size 64.0 64.0 RGBA 255 255 255 7@

Таким образом я получил следующее меню:

При нажатии ВЛЕВО/ВПРАВО нужная карта будет подсвечиваться а ниже будет отображаться его имя. На этом рисование окончено. Теперь уже техническая часть. Напишем условие, которые выходит из меню:

 if
 0ab0: key_pressed 32 // Space
 then
 30@ = 1
 end

Как видите, ничего сложного нет, но следует помнить, что вариантов таких графических штучек может быть много и для каждого свой алгоритм. Я привёл самый распространённый вариант - горизонтальное меню. Допишем уже концовку для скрипта:

0391: release_txd_dictionary

if
30@ == 1
then
fade 0 1000
wait 1000
jump @BOXEN_RUN
end

0826: enable_hud 1
0581: enable_radar 1
$PLAYER_CHAR.CanMove = true
$PLAYER_ACTOR.SetImmunities(0, 0, 0, 0, 0)
return

:BOXEN_RUN
wait 0
0826: enable_hud 1
0581: enable_radar 1
$PLAYER_ACTOR.PutAt(-2066.6797, -107.5093, 35.3276)
$PLAYER_ACTOR.Angle = 90.0
camera.Restore_WithJumpCut
camera.SetBehindPlayer
model.Load(8@)
038B: load_requested_models

repeat
wait 0
until model.Available(8@)

29@ = actor.Create(23, 8@, -2078.1331, -107.5472, 34.3203)
actor.Angle(29@) = 270.0
actor.Health(29@) = 1000
model.Destroy(8@)
wait 1000
fade 1 1000
wait 1000
$PLAYER_CHAR.CanMove = true
$PLAYER_ACTOR.SetImmunities(0, 0, 0, 0, 0)
05E2: AS_actor 29@ kill_actor $PLAYER_ACTOR
30@ = 0

while 30@ == 0
 if
 $PLAYER_ACTOR.Dead
 then
 30@ = -1
 end
 if
 actor.Dead(29@)
 then
 30@ = 1
 end
wait 0
end

if
30@ == 1
then
01E3: show_text_1number_styled GXT 'WIN_BOX' number 20000 time 5000 style 1 // You Win
$PLAYER_CHAR.Money += 20000
end

return

Содержимое FXT-архива:

BOX_001 ѓ›o Њyx®ac¦њk BOX_002 …Ї KЄ¦ћњ® BOX_003 CЄЇ Poќc BOX_004 Poќ Њe®cњћ BOX_005 Pњ¤apљ Kyc¦ BOX_006 ѓЇњ¦pњќ –eљўeћeў BOX_007 ЃpЄ®k ѓpe—њ® WIN_BOX ЏЁ Јo—eљњћ!

Полный вариант вы можете скачать здесь. Там вы найдете и исходный код даного скрипта. Ничего сложного нет. Нужно только знать, что должна быть переменная-регулятор ( 9@ ) и переменная-switch ( 0@ ). Позиции уже могут быть абсолютно разные. Хочу добавить, что на разработку скрипта ушло 2.5 часа ( было даже видео, где я кодю ), так что быстро такие скрипты не разрабатываются. На этом урок окончен! С вами, как всегда, был wmysterio. Удачи в рисовании!

`\||delaem_graficheskoe_menju|1504464042

Last updated