Added collision system, added changedId's which doesn't do anything rn
This commit is contained in:
parent
69596ba244
commit
558e91a442
2
src/bootstrap.js
vendored
2
src/bootstrap.js
vendored
@ -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' },
|
||||
|
22
src/game.js
22
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()
|
||||
|
49
src/systems/collision.js
Normal file
49
src/systems/collision.js
Normal file
@ -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 };
|
||||
};
|
111
src/systems/grid.js
Normal file
111
src/systems/grid.js
Normal file
@ -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)}));
|
||||
// };
|
||||
// });
|
@ -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 };
|
||||
};
|
@ -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 };
|
||||
|
@ -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 };
|
||||
}
|
@ -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 };
|
||||
};
|
Loading…
Reference in New Issue
Block a user