Behavior.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. const Behavior = {};
  2. Behavior.attach = function attachBehavior (behavior, sprite, opts, game) {
  3. const behaviors = require('../behaviors');
  4. if (typeof sprite === "undefined") {
  5. // throw new Error('Warning: attempting to attach behavior to undefined sprite ' + behavior)
  6. console.log('Warning: Attempting to attach behavior to undefined sprite ' + behavior);
  7. return false;
  8. }
  9. if (typeof behaviors[behavior] === "undefined") {
  10. // throw new Error('Warning: attempting to attach behavior to undefined sprite ' + behavior)
  11. console.log('Warning: Attempting to attach undefined behavior to sprite: ' + behavior);
  12. return false;
  13. }
  14. opts = opts || {};
  15. /*
  16. if (Behavior.mode !== 'server') {
  17. if (behavior === 'aiFollow') {
  18. return;
  19. }
  20. }
  21. */
  22. sprite.behaviors = sprite.behaviors || {};
  23. sprite.behaviors[behavior] = behaviors[behavior];
  24. sprite.behaviors[behavior].opts = opts;
  25. sprite.behaviors[behavior].tags = sprite.behaviors[behavior].tags || [];
  26. sprite.behaviors[behavior].config = sprite.behaviors[behavior].config || { stack: 1 };
  27. if (typeof sprite.behaviors[behavior] === "undefined") {
  28. throw new Error('Behavior could not be required: ' + behavior);
  29. }
  30. if (opts.controlKey) {
  31. sprite.G.mappedInputs = sprite.G.mappedInputs || {};
  32. sprite.G.mappedInputs[opts.controlKey] = sprite.G.mappedInputs[opts.controlKey] || [];
  33. sprite.G.mappedInputs[opts.controlKey].push(behavior);
  34. }
  35. if (typeof sprite.behaviors[behavior].create === "function") {
  36. try {
  37. if (!sprite.scene) {
  38. console.log('no scene variable found...', behavior, sprite)
  39. }
  40. sprite.behaviors[behavior].create(sprite, opts, sprite.scene, sprite.behaviors[behavior].config);
  41. } catch (err) {
  42. console.log('error running ' + behavior + '.create()', err);
  43. }
  44. }
  45. };
  46. Behavior.detach = function detachBehavior (behavior, sprite, opts) {
  47. if (typeof sprite === "undefined") {
  48. return;
  49. }
  50. sprite.behaviors = sprite.behaviors || {};
  51. if (typeof sprite.behaviors[behavior] === "object") {
  52. // if a 'remove' method has been provided, run it now to clean up behavior
  53. if (typeof sprite.behaviors[behavior].remove === "function") {
  54. // 'remove' methods will usually delete no longer needed resources,
  55. // or reset the state of something now that the behavior is removed
  56. sprite.behaviors[behavior].remove(sprite, game);
  57. }
  58. sprite.G.mappedInputs = {};
  59. delete sprite.behaviors[behavior];
  60. }
  61. };
  62. Behavior.process = function processBehavior (thing, game, gameUpdate) {
  63. const behaviors = require('../behaviors');
  64. // process all Things
  65. if (typeof thing === "object") {
  66. if (typeof thing.behaviors === "object") {
  67. var behaviorKeys = Object.keys(thing.behaviors);
  68. // Remark: Sort the order the behaviors are applied based on their optional config.stack value
  69. // The lowest config.stack value will execute first
  70. // The highest config.stack value will execute last
  71. behaviorKeys = behaviorKeys.sort(function(a, b){
  72. if (behaviors[a].config.stack > behaviors[b].config.stack) {
  73. return 1;
  74. }
  75. return -1;
  76. });
  77. behaviorKeys.forEach(function (b) {
  78. if (typeof thing.behaviors[b] === "object") {
  79. if (typeof thing.behaviors[b].update === "function") {
  80. try {
  81. thing.behaviors[b].update.call(this, thing, thing.scene, thing.behaviors[b].config, gameUpdate);
  82. // Remark: This is the best place to clamp max velocity of all physics bodies
  83. // This must be done after all possible thrust is applied ( after all behaviors run )
  84. // TODO: We could probably implement this as a series of "after" behaviors,
  85. // or add cardinality to the order of behaviors
  86. if (thing.G.maxVelocity) {
  87. behaviors.hasMaxVelocity.update(thing);
  88. }
  89. } catch (err) {
  90. console.log(thing.name, ': error in processing update call for:' + b, err);
  91. }
  92. }
  93. }
  94. });
  95. }
  96. }
  97. }
  98. Behavior.findByTag = function findByTag (str) {
  99. const behaviors = require('../behaviors');
  100. let results = [];
  101. for (let b in behaviors) {
  102. if (behaviors[b].tags) {
  103. if (behaviors[b].tags.indexOf(str) !== -1) {
  104. results.push(b);
  105. }
  106. }
  107. }
  108. return results;
  109. };
  110. module.exports = Behavior;