3

我正在尝试在 StarCraft 2 Editor 中创建一个event based editor类似的算法,它可以支持:

  • 创建用户界面
  • 播放声音
  • 处理键盘/鼠标输入
  • 显示消息
  • 按钮(或一些引用的 UI 对象)被按下等。

与星际争霸 2 编辑器中的内容几乎相同(当然也不是 3D 内容)


到目前为止,我正在考虑使用JSON,添加对象中的每个事件,然后循环它们并使用该addEventListener()方法创建一个事件。

JSON 事件对象(当然它将由用户在编辑器中创建,无需编程):

var Events={
    //your event's names here
    onReady:{ //on page ready to manipulate
        displayMessage:{//just a simple popup
            text:"Hello user!",
            title:"Welcome!",
            type:"normal",
            },
        createButton:{ //creates a buton on the screen
            text:"Click me!",
            id:"myButton"
        }
    },
    onClick:{
        id:"myButton" ,//the id of the button we just created
        actions:{ //the actions applied after we click the button
            displayMessage:{//just a simple popup
                text:"You pressed me!",
                title:"Button",
                type:"error",//show the message as an error
            }
        }
    }
}

我发现了一些软件GameMakerConstruct 2GameDevelopevent based editor如果你想了解我在说什么(如果你还不知道星际争霸 2 编辑器)

我的问题是: 我可以用来实现这一目标的最佳算法是什么?

4

3 回答 3

5

听起来像是jQuery UI的工作。

当用户在您的编辑器中创建自定义区域时,它的所有属性都存储在一个对象中(您可以将其保存为 JSON),然后在加载地图时将其作为参数应用于 div(使用html-attributes

function create_areas(areas){
    var map = $('#map_area');
    for(var i=0;i<areas.length;i++){
        map.append($('<div>', area[i].params));
    }
}

而 params 看起来像这样:

params = {
    width: 100,
    height: 200,
    ....
    mousedown: function(){ play_music('hello'); },
    keydown: function(e){ alert('you pressed ' + e.keyCode; }
}

像可拖动可调整大小这样的 jQuery UI 工具也应该可以简化您的编辑器的构建。

于 2013-07-02T18:21:46.833 回答
3

我会在主干的事件系统之后对此进行更多建模:

events: {
  'click selector': handler,
  'mouseover selector': handler2,
  ...
}

处理程序可以是任何 javascript 函数,这将允许您创建一堆预定义的函数,例如displayMessage.

然后您可以使用自己的处理程序,这将允许您的用户在需要时指定配置。

例子:

var events = {
   'click element': displayMessage({
        text:"Hello user!",
        title:"Welcome!",
        type:"normal",
    }),
   'mouseover pizza': createButton({...}) 
}

function displayMessage(options) {
   var options = options;

   return function() {
      //display message logic
   }
}

然后你可以compose在其他助手中提供一个函数(也许是查找承诺?)将你的函数组合在一起:

var events = {
   'click element': compose(
        displayMessage({
            text:"Hello user!",
            title:"Welcome!",
            type:"normal",
        }),
        createButton({})
    ),
   'mouseover pizza': createButton({...}) 
}

这能行吗?

警告:如果 events 是一个包含对象的数组可能会更好。这样,您可以在某些选择器上拥有多个单击处理程序而不会发生冲突。

于 2013-07-03T20:04:10.170 回答
3

在我看来,您确实需要做出多种选择。我会,虽然我更喜欢 JSON 作为数据结构,但我不会将自己限制在实际编程语言的这个子集上。反之亦然。

你有事件、处理程序和选项。选项,或者更好的选项列表是用户输入的数据,处理程序是实际操作,事件是设置某些操作的触发器。

如果您仔细阅读本文,您会注意到这是对大多数 jQuery 脚本或事件驱动软件的基本结构的准确描述。只有 jQuery 中的用户选项(因为它是一个 DOM 框架)通常是单个 DOM 元素的上下文。所以,我们到了这里,我建议简单地借用这背后的理论并利用 Promise生成代码,这是一种非常清晰和伟大的方式!

所以我对任何事件链的调用都是这样的。

...when(chainObject['event'])
.then(function(event) {
      //call handler
      handlers[chainObject[selectedHandler]].call(event.context, chainObject['options']); 
      //apply next element(s) in chain, this is the current promise
      appendNextElement(chainObject['followingHandlers'], this);
})...

请注意如何apply让您轻松更改环境,进而根据用户和事件所做的任何处理程序的行为。Promises 使错误处理变得非常容易!

这当然只适用于链中的一个节点。那么数据结构应该是什么样子才能让你生成这种代码呢?

结构中的一个节点如下所示:

   {
      event: 'click',
      selectedHandler: 'sohwText',
      options: {
          'text': 'helloWorld'
      },
      followingChain: {...OTHER HANDLERS....}
   }

需要注意的重要一点是,就像一个良好的结构化函数程序一样,您正在查看一棵树而不是简单的事件列表。所以每个实际的 DOM 元素都包含其中的许多

var eventTree = {
   '.someButton': [..Handlers of this button...],'
   '.someOtherButton': [..Handlers of the other button...],
}

我们开始了。你有一个上下文(按钮)、一个事件、用户输入和一个处理程序。

生成的应用程序不仅应该可以工作,而且可以为任何有经验的 JavaScript 程序员扩展或修改样式。

于 2013-07-08T22:59:07.193 回答