summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap.js2
-rw-r--r--src/game.js22
-rw-r--r--src/systems/collision.js49
-rw-r--r--src/systems/grid.js111
-rw-r--r--src/systems/gridSystem.js122
-rw-r--r--src/systems/keyboardInput.js4
-rw-r--r--src/systems/physics.js8
-rw-r--r--src/systems/render.js4
8 files changed, 184 insertions, 138 deletions
diff --git a/src/bootstrap.js b/src/bootstrap.js
index 7a7d809..24e9c4c 100644
--- a/src/bootstrap.js
+++ b/src/bootstrap.js
@@ -32,7 +32,7 @@ game.bootstrap = (() => {
{ src: ['src/systems/system.js'], id: 'system' },
{
src: [
- 'src/systems/render.js', 'src/systems/gridSystem.js', 'src/systems/physics.js', 'src/systems/keyboardInput.js'
+ 'src/systems/render.js', 'src/systems/grid.js', 'src/systems/physics.js', 'src/systems/keyboardInput.js', 'src/systems/collision.js',
],
id: 'systems' },
{ src: ['src/game.js'], id: 'game' },
diff --git a/src/game.js b/src/game.js
index 60d2a27..f649ba5 100644
--- a/src/game.js
+++ b/src/game.js
@@ -4,8 +4,11 @@ game.loop = (timeStamp) => {
lastTimeStamp = timeStamp;
+ const changedIds = new Set();
game.systemOrder.map((i) => {
- game.systems[i].update(elapsedTime, game.entities);
+ game.systems[i]
+ .update(elapsedTime, game.entities, changedIds)
+ .forEach((id) => changedIds.add(id));
});
for (let id in game.entities) {
@@ -14,23 +17,22 @@ game.loop = (timeStamp) => {
}
}
- if (game.nextLevel) {
- game.loadLevel(game.nextLevel);
- game.nextLevel = false;
- }
-
requestAnimationFrame(game.loop);
}
game.initialize = () => {
[game.entities, game.config] = game.loadLevel(game.levels[0]);
- game.systemOrder = ["render", "physics", "gridSystem", "keyboardInput"];
+ // Maintained by gridSystem as a side-effect
+ game.entitiesGrid = Array(game.config.yDim).fill(null).map(() => Array(game.config.xDim).fill(null).map(() => new Map()));
+
+ game.systemOrder = ["gridSystem", "collisionSystem", "physics", "keyboardInput", "render"];
game.systems = {
- render: game.system.Render(game.graphics),
- physics: game.system.Physics(),
- gridSystem: game.system.GridSystem({...game.config}),
+ physics: game.system.Physics(game.entitiesGrid),
+ gridSystem: game.system.Grid(game.entitiesGrid),
+ collisionSystem: game.system.Collision(game.entitiesGrid),
keyboardInput: game.system.KeyboardInput(),
+ render: game.system.Render(game.graphics),
};
lastTimeStamp = performance.now()
diff --git a/src/systems/collision.js b/src/systems/collision.js
new file mode 100644
index 0000000..7739bae
--- /dev/null
+++ b/src/systems/collision.js
@@ -0,0 +1,49 @@
+game.system.Collision = (entitiesGrid) => {
+ const update = (elapsedTime, entities, changedIds) => {
+ for (let entity of Object.keys(entities).map((id) => entities[id])) {
+ if (entity.hasComponent("controllable") && entity.hasComponent("gridPosition") && entity.hasComponent("momentum")) {
+ const momentum = unitize(entity.components.momentum);
+
+ let found;
+ const proposed = {x: entity.components.gridPosition.x + momentum.dx, y: entity.components.gridPosition.y + momentum.dy};
+ const entitiesToPush = [];
+ let wall = false;
+ do {
+ const proposedClampedInBounds = clamp(proposed, game.config.xDim-1, game.config.yDim-1);
+ if (!equivalence(proposed, proposedClampedInBounds)) {
+ break;
+ }
+
+ found = false;
+
+ const entitiesInCell = entitiesGrid[proposed.y][proposed.x];
+
+ for (let next of entitiesInCell.values()) {
+ if (next.hasComponent("stop")) {
+ console.log("WALL FOUND")
+ wall = next;
+ found = false;
+ break;
+ }
+ if (next.hasComponent("pushable")) {
+ entitiesToPush.push(next);
+ found = true;
+ }
+ }
+
+ proposed.x += momentum.dx;
+ proposed.y += momentum.dy;
+ } while(found);
+
+ if (wall) {
+ console.log("WALL")
+ entity.removeComponent("momentum");
+ } else {
+ entitiesToPush.map((e) => e.addComponent(game.components.Momentum({...momentum})));
+ }
+ }
+ }
+ return new Set();
+ };
+ return { update };
+};
diff --git a/src/systems/grid.js b/src/systems/grid.js
new file mode 100644
index 0000000..4082793
--- /dev/null
+++ b/src/systems/grid.js
@@ -0,0 +1,111 @@
+game.system.Grid = (entitiesGrid) => {
+ let gridWidth = game.canvas.width / game.config.xDim;
+ let gridHeight = game.canvas.height / game.config.yDim;
+
+ const gameCoordsToGrid = ({ x, y }) => {
+ return { x: Math.floor((x+gridWidth/2) / game.canvas.width * game.config.yDim), y: Math.floor((y+gridHeight/2) / game.canvas.height * game.config.yDim) };
+ };
+
+ const gridCoordsToGame = ({ x, y }) => {
+ return { x: x * gridWidth, y: y * gridHeight };
+ };
+
+ const rebuildGrid = (entities) => {
+ let changedIds = new Set();
+ entities.map(entity => {
+ const { x, y } = entity.components.gridPosition;
+ if (!entitiesGrid[y][x].has(entity.id)) {
+ changedIds.add(entity.id);
+ }
+ });
+ entitiesGrid.forEach((row) => row.forEach((entitiesInCell) => {
+ for (let id of entitiesInCell.keys()) {
+ if (changedIds.has(id)) {
+ entitiesInCell.delete(id);
+ }
+ }
+ }));
+ changedIds.forEach(id => {
+ const entity = entities[id];
+ const { x, y } = entity.components.gridPosition;
+ entitiesGrid[y][x].set(entity.id, entity);
+ });
+ }
+
+ const update = (_elapsedTime, entities, changedIds) => {
+ gridEntities = Object.keys(entities).filter((x) => entities[x].hasComponent("gridPosition")).map((x) => entities[x]);
+ const thisChangedIds = new Set();
+ gridEntities.map((entity) => {
+ if (entity.hasComponent("appearance")) {
+ entity.components.appearance.width = gridWidth;
+ entity.components.appearance.height = gridHeight;
+ }
+ if (entity.hasComponent("gridPosition")) {
+ const oldGridCoords = entity.components.gridPosition;
+ if (entity.hasComponent("position")) {
+ const gameCoords = gridCoordsToGame(entity.components.gridPosition);
+ if (Math.abs(entity.components.position.x - gameCoords.x) >= gridWidth/2 || Math.abs(entity.components.position.y - gameCoords.y) >= gridHeight/2) {
+ entity.components.gridPosition = gameCoordsToGrid(entity.components.position);
+ if (entity.hasComponent("momentum")) {
+ entity.removeComponent("momentum");
+ }
+ }
+ }
+ if (!entity.hasComponent("position") || !equivalence(entity.components.gridPosition, oldGridCoords)) {
+ entity.components.position = {
+ ...entity.components.position,
+ ...gridCoordsToGame(entity.components.gridPosition)
+ };
+ thisChangedIds.add(entity.id);
+ }
+ }
+ });
+ rebuildGrid(gridEntities);
+ return thisChangedIds;
+ };
+
+
+ return { gameCoordsToGrid, gridCoordsToGame, update, gridWidth, gridHeight };
+};
+
+//
+//
+//
+// const proposed = {...newGridCoords};
+// let wall = false;
+// let entitiesToPush = [];
+// if (entity.hasComponent("controllable")) {
+// let found = false;
+
+//
+// if (entity.hasComponent("controllable")) {
+// if (!wall) {
+// entity.components.gridPosition = {...entity.components.gridPosition, ...newGridCoords};
+// entitiesToPush.map((e) => e.addComponent(game.components.Momentum({...momentumVector})));
+// }
+// const particles = game.createBorderParticles({
+// colors: ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF"],
+// maxAmount: 100,
+// minAmount: 25,
+// minLife: 100,
+// maxLife: 300,
+// minRadius: 1,
+// maxRadius: 3,
+// maxSpeed: 0.15,
+// });
+// particles.addComponent(game.components.Position(gridCoordsToGame(oldGridCoords)));
+// particles.addComponent(game.components.Appearance({width: 50, height: 50}));
+// game.entities[particles.id] = particles;
+// } else {
+// entity.components.gridPosition = {...entity.components.gridPosition, ...newGridCoords};
+// }
+//
+//
+//
+//
+//
+// }
+// } else {
+// entity.addComponent(game.components.Position({...gridCoordsToGame(entity.components.gridPosition)}));
+// };
+// }); \ No newline at end of file
diff --git a/src/systems/gridSystem.js b/src/systems/gridSystem.js
deleted file mode 100644
index d9c8a6b..0000000
--- a/src/systems/gridSystem.js
+++ /dev/null
@@ -1,122 +0,0 @@
-game.system.GridSystem = ({ xDim, yDim }) => {
- const entitiesGrid = Array(yDim).fill(null).map(() => Array(xDim).fill(null).map(() => new Map()));
-
- let gridWidth = game.canvas.width / xDim;
- let gridHeight = game.canvas.height / yDim;
-
- const gameCoordsToGrid = ({ x, y }) => {
- return { x: Math.floor((x+gridWidth/2) / game.canvas.width * xDim), y: Math.floor((y+gridHeight/2) / game.canvas.height * yDim) };
- };
-
- const gridCoordsToGame = ({ x, y }) => {
- return { x: x * gridWidth, y: y * gridHeight };
- };
-
- const rebuildGrid = (entities) => {
- let changedIds = new Set();
- entities.map(entity => {
- const { x, y } = entity.components.gridPosition;
- if (!entitiesGrid[y][x].has(entity.id)) {
- changedIds.add(entity.id);
- }
- });
- entitiesGrid.forEach((row) => row.forEach((entitiesInCell) => {
- for (let id of entitiesInCell.keys()) {
- if (changedIds.has(id)) {
- entitiesInCell.delete(id);
- }
- }
- }));
- changedIds.forEach(id => {
- const entity = entities[id];
- const { x, y } = entity.components.gridPosition;
- entitiesGrid[y][x].set(entity.id, entity);
- });
- }
-
- const update = (_elapsedTime, entities) => {
- const gridEntities = Object.keys(entities).filter((x) => entities[x].hasComponent("gridPosition")).map((x) => entities[x]);
- rebuildGrid(gridEntities);
- gridEntities.map((entity) => {
- if (entity.hasComponent("appearance")) {
- entity.components.appearance.width = gridWidth;
- entity.components.appearance.height = gridHeight;
- }
- if (entity.hasComponent("position")) {
- let newGridCoords = gameCoordsToGrid(entity.components.position);
- const oldGridCoords = entity.components.gridPosition;
- if (!equivalence(newGridCoords, oldGridCoords)) {
- const momentumVector = unitize({
- dx: newGridCoords.x - oldGridCoords.x,
- dy: newGridCoords.y - oldGridCoords.y,
- });
-
- const proposed = {...newGridCoords};
- let wall = false;
- let entitiesToPush = [];
- if (entity.hasComponent("controllable")) {
- let found = false;
- do {
- found = false;
- const entitiesInCell = entitiesGrid[proposed.y][proposed.x];
- for (let entity of entitiesInCell.values()) {
- if (entity.hasComponent("pushable")) {
- found = true;
- entitiesToPush.push(entity);
- }
- if (entity.hasComponent("stop")) {
- wall = true;
- found = false;
- break;
- }
- }
- proposed.x += momentumVector.dx;
- proposed.y += momentumVector.dy;
- const proposedClampedInBounds = clamp(proposed, xDim-1, yDim-1);
- if (!equivalence(proposedClampedInBounds, proposed)) {
- found = false;
- }
- } while (found);
- }
-
- if (entity.hasComponent("controllable")) {
- if (!wall) {
- entity.components.gridPosition = {...entity.components.gridPosition, ...newGridCoords};
- entitiesToPush.map((e) => e.addComponent(game.components.Momentum({...momentumVector})));
- }
- const particles = game.createBorderParticles({
- colors: ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF"],
- maxAmount: 100,
- minAmount: 25,
- minLife: 100,
- maxLife: 300,
- minRadius: 1,
- maxRadius: 3,
- maxSpeed: 0.15,
- });
- particles.addComponent(game.components.Position(gridCoordsToGame(oldGridCoords)));
- particles.addComponent(game.components.Appearance({width: 50, height: 50}));
- game.entities[particles.id] = particles;
- } else {
- entity.components.gridPosition = {...entity.components.gridPosition, ...newGridCoords};
- }
-
-
- entity.components.position = {
- ...entity.components.position,
- ...gridCoordsToGame(entity.components.gridPosition)
- };
-
- if (entity.hasComponent("momentum")) {
- entity.components.momentum.dx = 0;
- entity.components.momentum.dy = 0;
- }
- }
- } else {
- entity.addComponent(game.components.Position({...gridCoordsToGame(entity.components.gridPosition)}));
- };
- });
- };
-
- return { entitiesGrid, gameCoordsToGrid, gridCoordsToGame, update, gridWidth, gridHeight };
-};
diff --git a/src/systems/keyboardInput.js b/src/systems/keyboardInput.js
index 24fd076..60a62a1 100644
--- a/src/systems/keyboardInput.js
+++ b/src/systems/keyboardInput.js
@@ -6,7 +6,7 @@ game.system.KeyboardInput = () => {
keys[event.key] = true;
}
};
- const update = (elapsedTime, entities) => {
+ const update = (elapsedTime, entities, changedIds) => {
for (let id in entities) {
const entity = entities[id];
if (entity.hasComponent('controllable')) {
@@ -24,6 +24,8 @@ game.system.KeyboardInput = () => {
}
}
Object.keys(keys).map((key) => delete keys[key]);
+
+ return new Set();
};
window.addEventListener("keydown", keyPress);
return { keys, update };
diff --git a/src/systems/physics.js b/src/systems/physics.js
index a49edca..d72b1a0 100644
--- a/src/systems/physics.js
+++ b/src/systems/physics.js
@@ -1,7 +1,7 @@
game.system.Physics = () => {
- const update = (elapsedTime) => {
- for (let id in game.entities) {
- const entity = game.entities[id];
+ const update = (elapsedTime, entities, changedIds) => {
+ for (let id in entities) {
+ const entity = entities[id];
if (entity.hasComponent("momentum") && entity.hasComponent("appearance")) {
const {dx, dy} = entity.components.momentum;
entity.components.position.x += dx * elapsedTime;
@@ -9,6 +9,8 @@ game.system.Physics = () => {
entity.components.position = clamp(entity.components.position, game.canvas.width - entity.components.appearance.width, game.canvas.height - entity.components.appearance.height);
}
}
+
+ return new Set();
}
return { update };
} \ No newline at end of file
diff --git a/src/systems/render.js b/src/systems/render.js
index 4ec67c7..adf3e86 100644
--- a/src/systems/render.js
+++ b/src/systems/render.js
@@ -1,5 +1,5 @@
game.system.Render = (graphics) => {
- const update = (elapsedTime, entities) => {
+ const update = (elapsedTime, entities, _changedIds) => {
graphics.clear();
const entitiesArray = Object.keys(entities).map(key => entities[key]);
@@ -14,6 +14,8 @@ game.system.Render = (graphics) => {
entity.sprite.draw(elapsedTime, {...entity.components.position, ...entity.components.appearance});
}
});
+
+ return new Set();
}
return { update };
}; \ No newline at end of file