2012-01-28 2 views
3

Я работаю над движком CoffeeScript для холста Html5. Я придумал «крутую» идею использовать mixins после того, как я проверил очень аккуратный CoffeeScript implementation. Я думал, может быть очень крутой идеей уменьшить различную иерархию объектов, которые обычно предоставляют игровые объекты, путем разработки набора компонентов на основе mixin, каждый из которых имеет очень специфическую функциональность. Затем при разработке реальной игры можно было создавать уникальные игровые объекты «на лету», в основном, начиная с одного компонента и смешивая его с кучей других компонентов. Это уменьшает иерархии и допускает частые изменения.Об использовании mixins в игровом движке CoffeeScript

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

Что мне делать? Это хороший способ? Мне все еще нравится, особенно из-за основанного на JS механизма прототипа, который позволяет таким простым способом комбинировать материал «на лету».

ответ

10

Вы говорите об entity component system. В JS написано пару; самым популярным является Crafty, который большой, но стоит посмотреть. Недавно я написал один в CoffeeScript (только для funsies, вероятно, никогда не выпустит его).

Несколько замечаний по поводу столкновений:

Так первое, что проблема может быть хуже, чем вы думаете: столкновения произойдет, если два метода имеет одинаковое имя; JS не отличает сигнатуры функций. Это также может быть не так уж плохо: почему бы вам просто не создать соглашение об именах, где каждое поведение (значение метода) названо после того компонента, к которому он принадлежит, например burnable_burn?

Чтобы сделать шаг назад, mixins - это не единственный способ построить это - поведение (т. Е. Вещи, которые может выполнять компонент) не обязательно должно быть методами. Мотивирующий вопрос, который я задаю, - как вы вызываете поведение? Например, вы можете:

if entity.hasComponent "burnable" #hasComponent provided by your framework 
    entity.burn() 

Но это звучит не так. это создает странную связь между тем, что происходит в вашей игре, и тем, что у вас есть, и неудобно проверять, реализуют ли ваши объекты соответствующий компонент. Вместо этого, я хотел бы поведение, чтобы быть слушателями на событие:

entity.send("applySeriousHeat") #triggers whatever behaviors are there 

И тогда ваш компонент делать все, что нужно сделать. Поэтому, когда вы добавляете компонент в объект, он регистрирует слушателей на события. Может быть, это выглядит (просто зарисовка):

register: (entity) -> #called when you add a component to an entity 
    entity.listen "applySeriousHeat", -> #thing I do when this event is sent to me 
    #do burnination here 

Чтобы довести эту точку домой, если вы сделаете это, вы не заботитесь о столкновении, потому что ваши поведения не имеют имен. Фактически, вы хотите «столкновения»; вы хотите, чтобы более одного компонента реагировали на одно и то же событие. Может, он горит и тает одновременно?

На практике я использовал обе установки вместе. Я сделал смешение entity.addComponent в функциях компонента, так как иногда удобно просто вызвать поведение как метод. Но в основном компоненты объявляют слушатели, которые называют эти методы, которые помогли с развязкой и уменьшили неловкость использования имен с областью, поскольку я не называю их непосредственно в большинстве случаев.

+0

Удивительно, спасибо за тщательный ответ! – preslavrachev

+0

NP :) Не забудьте установить флажок, если он ответил на ваш вопрос. –

+1

Да, я даю вам кредиты, потому что ваш ответ был действительно тщательным, и я ценю это. На данный момент я считаю, что я буду придерживаться модели GetComponent (""), подобной Crafty. Спасибо, что предложили эту приятную структуру для меня. – preslavrachev

Смежные вопросы