rework level loading & restarting, and player death.
level loading is now based on events; the level loading code doesn't know anything about how things are loaded, it just tells things to load. player death is also now based on events; instead of directly restarting the level, it simply sends out an event that the level handling code listens for.
This commit is contained in:
parent
92fdab8fbd
commit
b51b776137
5 changed files with 108 additions and 28 deletions
25
js/enemy.mjs
25
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);
|
||||
}
|
||||
})
|
||||
|
|
48
js/event.mjs
Normal file
48
js/event.mjs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
32
js/level.mjs
32
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();
|
||||
});
|
||||
|
|
|
@ -17,6 +17,6 @@ function main () {
|
|||
requestAnimationFrame(main);
|
||||
}
|
||||
|
||||
level.load();
|
||||
level.load(1);
|
||||
|
||||
main();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue