diff --git a/js/behaviours/main.mjs b/js/behaviours/main.mjs new file mode 100644 index 0000000..2768637 --- /dev/null +++ b/js/behaviours/main.mjs @@ -0,0 +1,25 @@ +import * as entity from "../entity.mjs"; + + + +export const behaviours = new Map(); + +export function exists (name) { + return behaviours.has(name); +} +export function get_tick (name) { + return behaviours.get(name).tick; +} +export function init (enemy, name, params) { + entity.get_meta(enemy).set("behaviour", name); + + const behaviour = behaviours.get(name); + if (behaviour.hasOwnProperty("init")) { + behaviour.init(enemy, params); + } +} + + + +import sine_x from "./sine_x.mjs"; +behaviours.set("sine_x", sine_x); diff --git a/js/behaviours/sine_x.mjs b/js/behaviours/sine_x.mjs new file mode 100644 index 0000000..4aac719 --- /dev/null +++ b/js/behaviours/sine_x.mjs @@ -0,0 +1,34 @@ +import * as entity from "../entity.mjs"; +import { underride } from "../underride.mjs"; + + + +export default { + tick: (enemy, deltatime) => { + const {y} = entity.get_pos(enemy); + + const meta = entity.get_meta(enemy); + const age = meta.get("age"); + + // `movement_speed` is in hertz and `Math.sin` input is in radians. + const age_factor = meta.get("movement_speed") * Math.PI * 2; + const x = meta.get("center_x") + Math.sin(age * age_factor) * meta.get("movement_scale"); + + entity.set_pos(enemy, x, y); + }, + init: (enemy, params = {}) => { + params = underride(params, { + movement_scale: 100, + movement_speed: 1/4, + }); + + const {x} = entity.get_pos(enemy); + + const meta = entity.get_meta(enemy); + + meta.set("center_x", x); + + meta.set("movement_scale", params.movement_scale); + meta.set("movement_speed", params.movement_speed); + }, +}; diff --git a/js/enemy.mjs b/js/enemy.mjs index d9122e6..7b46b0a 100644 --- a/js/enemy.mjs +++ b/js/enemy.mjs @@ -1,14 +1,11 @@ -import { assert } from "./test.mjs"; - import * as entity from "./entity.mjs"; import { register_tick } from "./tick.mjs"; +import * as behaviours from "./behaviours/main.mjs"; const enemies = []; -const behaviours = new Map(); - function tick_enemy (enemy, deltatime) { const meta = entity.get_meta(enemy); const age = meta.get("age") + deltatime; @@ -16,8 +13,9 @@ function tick_enemy (enemy, deltatime) { if (meta.has("behaviour")) { const b = meta.get("behaviour"); - if (behaviours.has(b)) { - behaviours.get(b)(enemy, deltatime) + if (behaviours.exists(b)) { + const callback = behaviours.get_tick(b); + callback(enemy, deltatime); } } } @@ -32,8 +30,8 @@ export function get_all () { return enemies; } -function create () { - const enemy = entity.create(100, 100, 40, 40); +function create (...args) { + const enemy = entity.create(...args); const meta = entity.get_meta(enemy); meta.set("age", 0); @@ -41,15 +39,10 @@ function create () { return enemy; } -const e = create(); +function set_behaviour (enemy, behaviour, params) { + behaviours.init(enemy, behaviour, params); +} + +const e = create(300, 100, 40, 40); +set_behaviour(e, "sine_x"); enemies.push(e); -entity.get_meta(e).set("behaviour", "sine_x"); - -behaviours.set("sine_x", (enemy, deltatime) => { - const {x, y} = entity.get_pos(enemy); - - const meta = entity.get_meta(enemy); - const age = meta.get("age"); - - entity.set_pos(enemy, 100 + Math.sin(age) * 80, y); -}); diff --git a/js/underride.mjs b/js/underride.mjs new file mode 100644 index 0000000..8e68028 --- /dev/null +++ b/js/underride.mjs @@ -0,0 +1,30 @@ +import { assert } from "./test.mjs"; + + + +function shallow_mutable_copy (source, target) { + for (const [key, value] of Object.entries(source)) { + target[key] = value; + } +} + +export function underride (object, template) { + const result = {}; + shallow_mutable_copy(template, result); + shallow_mutable_copy(object, result); + return result; +} + + + +assert("underriding works.", _ => { + const object = underride({ + gay: true, + trans: true, + }, { + trans: false, + invisible: false, + }); + + return object.gay && object.trans && (object.invisible === false); +});