我正在开发游戏交互菜单,它是一个HTML菜单,根据玩家目前的工作情况显示操作。
我的问题:我通过window.addEventListener检索有关玩家工作的信息。它是从我的游戏Lua文件发送到JavaScript。我可以确认这是有效的。但是,在JavaScript部分存在问题。
在item.updateJob下的addEventListener中存储/检索/更新作业,作为名为playerJob的变量。这也将使用相同的名称更新全局变量。正如您在代码中看到的那样,init()函数正在window.addEventListener之前运行。 init()必须使用更新的全局变量playerJob来显示正确的菜单,但它不会。在控制台中调试它时,它告诉我它是“未定义的”。我试图把window.addEventListener放在init()函数的上面§(函数...代码,但是没有做任何事情。
如何确保正在运行window.addEventListener并在init()函数执行任何操作之前设置playerJob变量?我尝试在顶部放置一个全局变量并执行此操作:playerJob =“police”,然后它工作正常。谁知道我怎么能这样做?
var playerJob;
$( function() {
// Adds all of the correct button actions
console.log("Before int: ", playerJob)
init();
// Gets the interactionmenu div container
var interactionContainer = $( "#interactionmenu" );
// Listens for NUI messages from Lua
window.addEventListener( 'message', function( event ) {
var item = event.data;
// Show the menu
if ( item.showmenu ) {
ResetMenu()
interactionContainer.show();
}
if ( item.hidemenu ) {
interactionContainer.hide();
}
// This will update the players job, and does work!
if ( item.updateJob ) {
playerJob = item.job;
setJob(playerJob);
console.log("playerJob set to: ", playerJob)
}
} );
} )
// Hides all div elements that contain a data-parent, in
// other words, hide all buttons in submenus.
function ResetMenu() {
$( "div" ).each( function( i, obj ) {
var element = $( this );
if ( element.attr( "data-parent" ) ) {
element.hide();
} else {
element.show();
}
} );
}
// Configures every button click to use its data-action, or data-sub
// to open a submenu.
function init() {
// Loops through every button that has the class of "menuoption"
$( ".menuoption" ).each( function( i, obj ) {
// If the button has a data-action, then we set it up so when it is
// pressed, we send the data to the lua side.
if ( $( this ).attr( "data-action" ) ) {
$( this ).click( function() {
var data = $( this ).data( "action" );
sendData( "ButtonClick", data );
} )
}
// If the button has a data-sub, then we set it up so when it is
// pressed, we show the submenu buttons, and hide all of the others.
if ( $( this ).attr( "data-sub" ) ) {
$( this ).click( function() {
var menu = $( this ).data( "sub" );
var element = $( "#" + menu );
element.show();
$( this ).parent().hide();
} )
}
// Here I'd like to know the playerJob, and want via item.updateJob in the addEventListener
// However it returns undefined, no matter if I place the init() above or below
// My question is: how can I make sure the item.updatePlayer job in the addEventListener updates
// the variable globally and makes sure that it does that before this function is being run?
console.log("right before data-require: ", playerJob) // returns undefined X amount of times.
if ( ( $( this ).attr ( "data-require" ) == "police" && playerJob != "police") ) {
$( this ).hide();
}
else if ( ( $( this ).attr ( "data-require" ) == "mecano" && playerJob != "mecano") ) {
$( this ).hide();
}
else if ( ( $( this ).attr ( "data-require" ) == "ambulance" && playerJob != "ambulance") ) {
$( this ).hide();
}
} );
}
// Send data to lua for processing.
function sendData( name, data ) {
$.post( "http://wk_interactionmenu/" + name, JSON.stringify( data ), function( datab ) {
if ( datab != "ok" ) {
console.log( datab );
}
} );
}
答案 0 :(得分:0)
如果我理解正确的问题,您只需要在{0}收到init
事件后才能运行message
,因此playerJob
已设置。
我认为你不理解的是addEventListener
电话不是在运行听众,它只是设置它。问题是message
事件直到稍后才会发生。这就是您在查看undefined
时获得playerJob
的原因。
但是您不希望init
多次运行,因此不希望它从事件处理程序运行。
您可以在同一位置设置一个标记var didInit = false;
,而不是当前对init()
的调用。然后,在事件处理程序中,在设置playerJob
后,检查didInit
的状态。如果还不是,请将其设置为true并运行init
功能。
以下是您的onLoad($(function(){...
)功能的替代品,该功能可以完成这项工作:
$( function() {
// Did we initialize yet?
var didInit = false;
// Gets the interactionmenu div container
var interactionContainer = $( "#interactionmenu" );
// Listens for NUI messages from Lua
window.addEventListener( 'message', function( event ) {
var item = event.data;
// Show the menu
if ( item.showmenu ) {
ResetMenu()
interactionContainer.show();
}
if ( item.hidemenu ) {
interactionContainer.hide();
}
// This will update the players job, and does work!
if ( item.updateJob ) {
playerJob = item.job;
setJob(playerJob);
console.log("playerJob set to: ", playerJob)
// Initialize if we didn't yet
if (!didInit) {
didInit = true;
init();
}
}
} );
} )
玩家的工作是否有变化?如果是这样,你可能想要运行再次隐藏按钮的初始化代码的一部分,并且你想要改变它以显示以前隐藏的任何现在相关的按钮。
如果是这样的话,可能值得将init
分成两部分 - 一部分你可以在一开始就运行(正如你的原始代码所做的那样)并不依赖在playerJob
上,另一个可以在playerJob
更改(包括第一次设置)时运行,并更新用户界面。然后,您可以运行此(没有任何条件或didInit
标志)作为事件处理程序的一部分。