Введение в скриптинг GUI: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
(Еще немного перевода)
(Translation finished)
Line 100: Line 100:
addEventHandler("onClientGUIClick", btnLogin, clientSubmitLogin, false)
addEventHandler("onClientGUIClick", btnLogin, clientSubmitLogin, false)
</syntaxhighlight>
</syntaxhighlight>
The event handler must be added here because it makes sure variable btnLogin contains the actual button. You cannot attach an event to an non-existant element. You should have noticed that we need the "clientSubmitLogin" function, as stated in the line above.
Обработчик должен быть добавлен здесь, чтобы быть уверенным, что переменная btnLogin содержит существующую кнопку. Нельзя привязать событие к несуществующему элементу. Вы, должно быть, заметили, что нам потребуется функция "clientSubmitLogin", вызываемая в предыдущей строке.
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function clientSubmitLogin(button)
function clientSubmitLogin(button)
Line 112: Line 112:
end
end
</syntaxhighlight>
</syntaxhighlight>
The variable "button" is passed by the event handler, and it's a string with the name of the button (either "left" or "right"). Here we also hit a new concept, which is custom events. Custom events can be triggered by script from the same side (server to server, or client to client), or from the other side (server to client, or vice versa). Here we use the [[triggerServerEvent]] function to trigger a custom event on the server, "SubmitLogin".
Переменная "button" передается обработчиком события и содержит строку с именем этой кнопки (к примеру "left" или "right"). Здесь мы познакомились с новой концепцией пользовательских событий. Пользовательские события могут генерироваться как на одной стороне, так и на разных (с сервера на клиент и наоборот). Мы используем функцию [[triggerServerEvent]], чтобы сгенерировать событие "SubmitLogin" на сервере.


At this point we have all the code needed on the client side. On the server side, recall that we are spawning the player as soon as they join, as shown below:  
Теперь у нас есть весь необходимый клиентский код. На сервере, как вы помните, мы спавним игрока как только он подключается к серверу:  
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function joinHandler()
function joinHandler()
Line 127: Line 127:
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
</syntaxhighlight>
</syntaxhighlight>
However, since we are going to spawn the player when the button is clicked, we must replace the "onPlayerJoin" event with the custom event triggered by the client script. Replace the above code with the following:
Так как теперь мы должны спавнить игрока после нажатия на кнопку, нам нужно заменить событие "onPlayerJoin" пользовательским событием, генерируемым клиентом. Замените приведенный выше код следующим образом:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function joinHandler(username, password)
function joinHandler(username, password)
Line 144: Line 144:
addEventHandler("SubmitLogin", getRootElement(), joinHandler)
addEventHandler("SubmitLogin", getRootElement(), joinHandler)
</syntaxhighlight>
</syntaxhighlight>
Note that the second arguement of [[addEvent]] function (the one with value "true") specifies whether the event can be triggered by the other side, therefore we need to turn it on since the client is triggering it. Also note the variable "client", it's an internal variable used by MTA to identify the player who triggered the event.  
Обратите внимание на второй параметр функции [[addEvent]] (имеющий значение "true"), он указывает, что событие может быть сгенерировано другой стороной. так же заметьте, что "client" - внутренняя переменная, используемая MTA для идентификации игрока, сгенерировавшего событие.  


Finally, do not forget to include the new gui.lua file in the meta.xml of the main resource, and label it as a client script:
И, наконец, не забудьте добавить файл gui.lua в meta.xml основного ресурса и пометть его как клиентский:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<script src="client/gui.lua" type="client" />
<script src="client/gui.lua" type="client" />
</syntaxhighlight>
</syntaxhighlight>


As to this point, we have a basic login window that spawns the player when the "login" button is clicked. You can also use the username and password submitted by the [[triggerServerEvent]] function to verify the player's identify before spawning him.
Теперь у нас есть минимальное окно авторизации, спавнящее игрока при нажатии кнопки "login". Вы также можете использовать логин и пароль, передаваемые функцией [[triggerServerEvent]] для идентификации пользователя.


[[en:Introduction_to_Scripting_GUI]]
[[it:Introduzione_allo_scripting_della_GUI]]
[[it:Introduzione_allo_scripting_della_GUI]]

Revision as of 11:10, 14 April 2009

Одна из важных особенностей MTA:DM - возможность создания собственного GUI (графический пользовательский интерфейс). Графический интерфейс состоит из окон, кнопок, текстовых полей... Проще говоря, из всех стандартных компонент графических интерфейсов. Они могут использоваться пока пользователь в игре, и использоваться для ввода/вывода вместо команд.

Admin Console GUI

Руководство по созданию интерфейса авторизации

В этом руководстве мы сделаем простое окно авторизаци с двумя полями ввода и кнопкой. Окно появляется, когда игрок подключается к игре, и после того, как нажата кнопка, игрок респаунится. Это руководство - продолжение предыдущего (Введение в скриптинг). Теперь мы познакомимся с написанием клиентских скриптов.

Отрисовка окна

GUI работает на стороне клиента. Хорошим решением будет поместить все клиентские скрипты в отдельный каталог. Перейдите в каталог /Ваш сервер MTA/mods/deathmatch/resources/myserver/ и создайте подкаталог "client". В нём создайте текстовый файл и назовите его "gui.lua". В этом файле мы напишем функцию, отображающую окно:

function CreateLoginWindow()
	local X = 0.375
	local Y = 0.375
	local Width = 0.25
	local Height = 0.25
	wdwLogin = guiCreateWindow(X, Y, Width, Height, "Please Log In", true)
end

Вы можете кликнуть по имени функции, чтобы прочитать её описание. Заметьте, что координаты окна задаются в процентах от размеров экрана. Это значит, что левая граница экрана по ширине принимается за 0, а правая за 1, соответственно, "X" равное 0.5 обозначает середину экрана. Аналогично и для позиции по высоте, ширины и высоты окна (если "width" равно 0.5, окно будет в половину ширины экрана). Теперь мы добавим текстовые меткм (с надписями "username:" и "password:"), поля ввода и кнопку. Замените функцию её полной версией:

function CreateLoginWindow()
	local X = 0.375
	local Y = 0.375
	local Width = 0.25
	local Height = 0.25
	wdwLogin = guiCreateWindow(X, Y, Width, Height, "Please Log In", true)
	
	X = 0.0825
	Y = 0.2
	Width = 0.25
	Height = 0.25
	guiCreateLabel(X, Y, Width, Height, "Username", true, wdwLogin)
	Y = 0.5
	guiCreateLabel(X, Y, Width, Height, "Password", true, wdwLogin)
	
	X = 0.415
	Y = 0.2
	Width = 0.5
	Height = 0.15
	edtUser = guiCreateEdit(X, Y, Width, Height, "", true, wdwLogin)
	Y = 0.5
	edtPass = guiCreateEdit(X, Y, Width, Height, "", true, wdwLogin)
	guiEditSetMaxLength(edtUser, 50)
	guiEditSetMaxLength(edtPass, 50)
	
	X = 0.415
	Y = 0.7
	Width = 0.25
	Height = 0.2
	btnLogin = guiCreateButton(X, Y, Width, Height, "Log In", true, wdwLogin)
	
	guiSetVisible(wdwLogin, false)
end

Обратите внимание на то, что каждый компонент интерфейса является дочерним по отношению к окну, это достигается указанием родительского элемента (wdwLogin, в данном случае) при создании элемента:

guiCreateLabel(X, Y, Width, Height, "Password", true, wdwLogin)

Это очень удобно, т.к. в дальнейшем, при отображении окна, можно обращаться только к родительскому элементу. К примеру:

guiSetVisible(wdwLogin, false) --прячет всё окно целиком так, что мы можем показать его игроку в любой момент. 

Использование написаной нами функции

Функция CreateLoginWindow написана, но она не будет работать, пока мы её не вызовем. Рекомендуется создавать все окна при запуске ресурса на клиенте, прятать их, и показывать игроку позднее, когда они понадобятся. Для этого напишем обработчик события "onClientResourceStart", в котором будем создавать окно:

addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		CreateLoginWindow()
	end
)	

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

addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		CreateLoginWindow()

                outputChatBox("Welcome to My MTA DM Server, please log in.  ")

	        if (wdwLogin ~= nil) then
		         guiSetVisible(wdwLogin, true)
	        end 

	        showCursor(true)
	        guiSetInputEnabled(true)
	end
)	

Заметьте, что мы выполняем проверку перед показом окна, так, в случае, если окно не создано, не возникнет ошибки. Функция showCursor включает управление мышью, а guiSetInputEnabled позволяет быть уверенным, что использование при вводе некоторых клавиш, таких как "A", "S", "D", "W", "T", не приведёт к движению персонажа, или вводу текста в чате. На следующем шаге мы заставим кнопку работать так, как задумывалось.

Обработчик нажатия кнопки

Когда пользователь кликает по любому элементу интерфейса, генерируется событие "onClientGUIClick" для этого элемента. К примеру, если вы кликните по кнопке, можно добавить обработчик для этого события:

addEventHandler("onClientGUIClick", theButtonElement, theHandlerFunction, false)

В нашем скрипте требуется только обработчик привязанный к кнопке. При клике по ней, клиент должен сообщить серверу, что нужно респаунить игрока. Найдите обработчик события "onClientResourceStart" из предыдущей части и добавьте следующую строку сразу ПОСЛЕ вызова CreateLoginWindow() :

addEventHandler("onClientGUIClick", btnLogin, clientSubmitLogin, false)

Обработчик должен быть добавлен здесь, чтобы быть уверенным, что переменная btnLogin содержит существующую кнопку. Нельзя привязать событие к несуществующему элементу. Вы, должно быть, заметили, что нам потребуется функция "clientSubmitLogin", вызываемая в предыдущей строке.

function clientSubmitLogin(button)
	if button == "left" then
		
		triggerServerEvent("SubmitLogin", getRootElement(), guiGetText(edtUser), guiGetText(edtPass))
		guiSetInputEnabled(false)
		guiSetVisible(wdwLogin, false)
		showCursor(false)
	end
end

Переменная "button" передается обработчиком события и содержит строку с именем этой кнопки (к примеру "left" или "right"). Здесь мы познакомились с новой концепцией пользовательских событий. Пользовательские события могут генерироваться как на одной стороне, так и на разных (с сервера на клиент и наоборот). Мы используем функцию triggerServerEvent, чтобы сгенерировать событие "SubmitLogin" на сервере.

Теперь у нас есть весь необходимый клиентский код. На сервере, как вы помните, мы спавним игрока как только он подключается к серверу:

function joinHandler()
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
	spawnPlayer(source, x, y, z)
	fadeCamera(source, true)
	outputChatBox("Welcome to My Server", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

Так как теперь мы должны спавнить игрока после нажатия на кнопку, нам нужно заменить событие "onPlayerJoin" пользовательским событием, генерируемым клиентом. Замените приведенный выше код следующим образом:

function joinHandler(username, password)
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
        if (client) then
	      spawnPlayer(client, x, y, z)
	      fadeCamera(client, true)
	      outputChatBox("Welcome to My Server", client)
        end
end

addEvent("SubmitLogin", true)
addEventHandler("SubmitLogin", getRootElement(), joinHandler)

Обратите внимание на второй параметр функции addEvent (имеющий значение "true"), он указывает, что событие может быть сгенерировано другой стороной. так же заметьте, что "client" - внутренняя переменная, используемая MTA для идентификации игрока, сгенерировавшего событие.

И, наконец, не забудьте добавить файл gui.lua в meta.xml основного ресурса и пометть его как клиентский:

<script src="client/gui.lua" type="client" />

Теперь у нас есть минимальное окно авторизации, спавнящее игрока при нажатии кнопки "login". Вы также можете использовать логин и пароль, передаваемые функцией triggerServerEvent для идентификации пользователя.