diff --git a/js/enemy.mjs b/js/enemy.mjs index 6b88744..ad30e3e 100644 --- a/js/enemy.mjs +++ b/js/enemy.mjs @@ -1,6 +1,9 @@ import * as entity from "./entity.mjs"; import { register_tick } from "./tick.mjs"; import * as behaviours from "./behaviours/main.mjs"; +import * as Entity from "./entity.mjs"; + +import * as Event from "./event.mjs"; @@ -47,6 +50,26 @@ export function add (enemy) { enemies.push(enemy); } -export function remove_all () { +function remove_all () { enemies.splice(0, enemies.length); } + +Event.listen("level/unload", _ => { + remove_all(); +}); + +Event.listen("level/load/enemy", enemies => { + for (const data of enemies) { + const {pos, size} = data; + const enemy = create(pos[0], pos[1], size[0], size[1]); + + set_behaviour(enemy, data.behaviour); + + const meta = Entity.get_meta(enemy); + for (const [key, value] of data.meta) { + meta.set(key, value); + } + + add(enemy); + } +}) diff --git a/js/event.mjs b/js/event.mjs new file mode 100644 index 0000000..20b44bf --- /dev/null +++ b/js/event.mjs @@ -0,0 +1,48 @@ +const registered_listeners = new Map(); + +export function trigger (event_name, data) { + for (const callback of listeners(event_name)) { + callback(data); + } +} + +export function listen (event_name, callback) { + listeners(event_name).push(callback); + // to find an event later, for deletion or other things. + return [event_name, listeners(event_name).length - 1]; +} + +// makes a callback function stop being used to listen to an event, and returns that callback function. +export function ignore (listener_id) { + const [event_name, index] = listener_id; + return listeners(event_name).splice(index, 1)[0]; +} + +function listeners (event_name) { + if (!registered_listeners.has(event_name)) + registered_listeners.set(event_name, []); + + return registered_listeners.get(event_name); +} + + + +export function attach_listener (target, event_name, callback) { + return listen(event_name, data => { + if (data.target === target) { + callback(data); + } + }); +} + +export function create_alias (event_name, alias) { + // note that aliases are one-directional; `event_name` isn't triggered when `alias` is. + return listen(event_name, data => trigger(alias, data)); +} + +export function create_group (group_name, members) { + // TODO: return list of event id:s so groups can be `ignore`:d. + for (const event_name of members) { + create_alias(event_name, group_name); + } +} diff --git a/js/level.mjs b/js/level.mjs index 5be8845..37350bf 100644 --- a/js/level.mjs +++ b/js/level.mjs @@ -1,33 +1,27 @@ import * as Entity from "./entity.mjs"; -import * as Enemy from "./enemy.mjs"; -import * as Player from "./player.mjs"; import * as Levels from "./levels/main.mjs"; +import * as Event from "./event.mjs"; -const current = Levels.get_level(1); -export function load (data) { - Enemy.remove_all(); - Player.set_pos(0, 0); +let last_loaded; - const {enemies} = current; +export function load (name) { + last_loaded = name; - for (const data of enemies) { - const {pos, size} = data; - const enemy = Enemy.create(pos[0], pos[1], size[0], size[1]); + Event.trigger("level/unload"); - Enemy.set_behaviour(enemy, data.behaviour); + const level = Levels.get_level(name); - const meta = Entity.get_meta(enemy); - for (const [key, value] of data.meta) { - meta.set(key, value); - } - - Enemy.add(enemy); - } + Event.trigger("level/load/player", level.player); + Event.trigger("level/load/enemy", level.enemies); } export function restart () { - load(); + load(last_loaded); } + +Event.listen("level/restart", data => { + restart(); +}); diff --git a/js/main.mjs b/js/main.mjs index 3c92ec3..352c6c4 100644 --- a/js/main.mjs +++ b/js/main.mjs @@ -17,6 +17,6 @@ function main () { requestAnimationFrame(main); } -level.load(); +level.load(1); main(); diff --git a/js/player.mjs b/js/player.mjs index 4f5449b..ba2cddb 100644 --- a/js/player.mjs +++ b/js/player.mjs @@ -4,7 +4,9 @@ import * as Entity from "./entity.mjs"; import * as Input from "./input.mjs"; import { register_tick } from "./tick.mjs"; import * as Enemy from "./enemy.mjs"; -// import * as level from "./level.mjs"; + +import * as Event from "./event.mjs"; +import { underride } from "./underride.mjs"; @@ -24,12 +26,8 @@ function tick_player (deltatime) { const enemies = Enemy.get_all(); for (const e of enemies) { if (Entity.touches(player, e)) { - // here it should just tell other code that the player touched enemy; - // the player code shouldn't know what to do in that situation. - // in the meantime we simply refresh the page. it's hacky and won't last for long, - // but for now it works. - // level.restart(); - location.reload(); + Event.trigger("level/restart"); + return; } } } @@ -39,3 +37,20 @@ export function set_pos (x, y) { } register_tick(tick_player); + +Event.listen("level/unload", _ => { + Entity.set_visible(player, false); +}); + +Event.listen("level/load/player", (data = {}) => { + data = underride(data, { + pos: { + x: 0, + y: 0, + }, + }); + + Entity.set_pos(player, data.pos.x, data.pos.y); + + Entity.set_visible(player, true); +});