diff --git a/index.html b/index.html index f0ec376..ee6d5d5 100644 --- a/index.html +++ b/index.html @@ -24,6 +24,7 @@ canvas: { width: document.getElementById('game-canvas').width, height: document.getElementById('game-canvas').height, + context: document.getElementById('game-canvas').getContext("2d"), } }; diff --git a/src/bootstrap.js b/src/bootstrap.js index ff4b4e4..64a79ac 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -14,6 +14,7 @@ game.bootstrap = (() => { 'src/components/position.js', 'src/components/momentum.js', 'src/components/gridPosition.js', 'src/components/appearence.js', 'src/components/controllable.js', 'src/components/pushable.js', 'src/components/loadPriority.js', 'src/components/stop.js', 'src/components/alive.js', + 'src/components/sprite.js' ], id: 'components' }, @@ -32,7 +33,8 @@ game.bootstrap = (() => { { src: ['src/systems/system.js'], id: 'system' }, { src: [ - 'src/systems/render.js', 'src/systems/grid.js', 'src/systems/physics.js', 'src/systems/keyboardInput.js', 'src/systems/collision.js', + 'src/systems/render.js', 'src/systems/grid.js', 'src/systems/physics.js', 'src/systems/keyboardInput.js', + 'src/systems/collision.js', 'src/systems/undo.js' ], id: 'systems' }, { src: ['src/game.js'], id: 'game' }, diff --git a/src/components/sprite.js b/src/components/sprite.js new file mode 100644 index 0000000..f45975d --- /dev/null +++ b/src/components/sprite.js @@ -0,0 +1 @@ +game.components.Sprite = ({spriteName}) => game.Component('sprite', {spriteName}); \ No newline at end of file diff --git a/src/components/stop.js b/src/components/stop.js index a269183..17d4c38 100644 --- a/src/components/stop.js +++ b/src/components/stop.js @@ -1 +1 @@ -game.components.Stop = ({stop}) => game.Component("stop", {stop}); +game.components.Stop = () => game.Component("stop"); diff --git a/src/entities/bigblue.js b/src/entities/bigblue.js index 02029a5..5b6af0f 100644 --- a/src/entities/bigblue.js +++ b/src/entities/bigblue.js @@ -3,7 +3,7 @@ game.createBigBlue = () => { bigBlue.addComponent(game.components.LoadPriority({priority: 1})); bigBlue.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); bigBlue.addComponent(game.components.Alive()); - bigBlue.sprite = game.sprites.bigBlue; + bigBlue.addComponent(game.components.Sprite({spriteName: "bigBlue"})) // TODO: Remove this bigBlue.addComponent(game.components.Controllable({controls: ['left', 'right', 'up', 'down']})); diff --git a/src/entities/borderParticles.js b/src/entities/borderParticles.js index a8d7036..34512bc 100644 --- a/src/entities/borderParticles.js +++ b/src/entities/borderParticles.js @@ -31,9 +31,7 @@ game.createBorderParticles = ({colors, maxAmount, minAmount, minLife, maxLife, m } return particle; }); - particles.addComponent(game.components.LoadPriority({priority: 1})); - particles.addComponent(game.components.Alive()); - particles.sprite = game.graphics.Sprite({ + game.sprites.borderParticle = game.graphics.Sprite({ drawFunction: (elapsedTime, {x, y, width, height}, context) => { particleSpecs.map((spec) => spec.elapsed += elapsedTime); particleSpecs = particleSpecs.filter((spec) => spec.lifetime > spec.elapsed); @@ -51,5 +49,8 @@ game.createBorderParticles = ({colors, maxAmount, minAmount, minLife, maxLife, m }); } }) + particles.addComponent(game.components.LoadPriority({priority: 1})); + particles.addComponent(game.components.Alive()); + particles.addComponent(game.components.Sprite({spriteName: "borderParticle"})) return particles; } \ No newline at end of file diff --git a/src/entities/flag.js b/src/entities/flag.js index 87daeb7..09cb7bd 100644 --- a/src/entities/flag.js +++ b/src/entities/flag.js @@ -3,6 +3,6 @@ game.createFlag = () => { flag.addComponent(game.components.LoadPriority({priority: 2})); flag.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); flag.addComponent(game.components.Alive()); - flag.sprite = game.sprites.flag; + flag.addComponent(game.components.Sprite({spriteName: "flag"})) return flag; } diff --git a/src/entities/floor.js b/src/entities/floor.js index d16392e..3f6b9f6 100644 --- a/src/entities/floor.js +++ b/src/entities/floor.js @@ -3,6 +3,6 @@ game.createFloor = () => { floor.addComponent(game.components.LoadPriority({priority: 5})); floor.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); floor.addComponent(game.components.Alive()); - floor.sprite = game.sprites.floor; + floor.addComponent(game.components.Sprite({spriteName: "floor"})) return floor; } diff --git a/src/entities/grass.js b/src/entities/grass.js index f731ef1..7f26712 100644 --- a/src/entities/grass.js +++ b/src/entities/grass.js @@ -3,6 +3,6 @@ game.createGrass = () => { grass.addComponent(game.components.LoadPriority({priority: 6})); grass.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); grass.addComponent(game.components.Alive()); - grass.sprite = game.sprites.grass; + grass.addComponent(game.components.Sprite({spriteName: "grass"})) return grass; } diff --git a/src/entities/hedge.js b/src/entities/hedge.js index 03ecb0f..90d069b 100644 --- a/src/entities/hedge.js +++ b/src/entities/hedge.js @@ -4,6 +4,6 @@ game.createHedge = () => { hedge.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); hedge.addComponent(game.components.Stop({stop: true})); hedge.addComponent(game.components.Alive()); - hedge.sprite = game.sprites.hedge; + hedge.addComponent(game.components.Sprite({spriteName: "hedge"})) return hedge; } diff --git a/src/entities/lava.js b/src/entities/lava.js index bd1ca04..e741f0d 100644 --- a/src/entities/lava.js +++ b/src/entities/lava.js @@ -1,10 +1,9 @@ game.createLava = () => { - // TODO: Split this into two entities: water and lava const lava = game.Entity(); lava.addComponent(game.components.LoadPriority({priority: 5})); lava.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); lava.addComponent(game.components.Alive()); - lava.sprite = game.sprites.lava; + lava.addComponent(game.components.Sprite({spriteName: "lava"})) return lava; } diff --git a/src/entities/rock.js b/src/entities/rock.js index 7602ab6..4d73f8d 100644 --- a/src/entities/rock.js +++ b/src/entities/rock.js @@ -3,7 +3,7 @@ game.createRock = () => { rock.addComponent(game.components.LoadPriority({priority: 2})); rock.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); rock.addComponent(game.components.Alive()); - rock.sprite = game.sprites.rock; + rock.addComponent(game.components.Sprite({spriteName: "rock"})) //TODO: Remove this rock.addComponent(game.components.Pushable()); diff --git a/src/entities/wall.js b/src/entities/wall.js index 84c9a91..af9aa1d 100644 --- a/src/entities/wall.js +++ b/src/entities/wall.js @@ -2,8 +2,8 @@ game.createWall = () => { const wall = game.Entity(); wall.addComponent(game.components.LoadPriority({priority: 3})); wall.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); - wall.addComponent(game.components.Stop({stop: true})); + wall.addComponent(game.components.Stop()); wall.addComponent(game.components.Alive()); - wall.sprite = game.sprites.wall; + wall.addComponent(game.components.Sprite({spriteName: "wall"})) return wall; } diff --git a/src/entities/water.js b/src/entities/water.js index abefd3f..7c160b0 100644 --- a/src/entities/water.js +++ b/src/entities/water.js @@ -3,12 +3,6 @@ game.createWater = () => { water.addComponent(game.components.LoadPriority({priority: 5})); water.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); water.addComponent(game.components.Alive()); - water.sprite = game.graphics.Sprite({ - image: game.assets.water, - spriteHeight: 24, - spriteWidth: 24, - numFrames: 3, - timePerFrame: 100, - }); + water.addComponent(game.components.Sprite({spriteName: "water"})) return water; } diff --git a/src/entities/wordBigBlue.js b/src/entities/wordBigBlue.js index 537c523..b6dd661 100644 --- a/src/entities/wordBigBlue.js +++ b/src/entities/wordBigBlue.js @@ -4,6 +4,6 @@ game.createWordBigBlue = () => { wordBigBlue.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordBigBlue.addComponent(game.components.Pushable({pushable: true})); wordBigBlue.addComponent(game.components.Alive()); - wordBigBlue.sprite = game.sprites.wordBigBlue; + wordBigBlue.addComponent(game.components.Sprite({spriteName: "wordBigBlue"})) return wordBigBlue; } diff --git a/src/entities/wordFlag.js b/src/entities/wordFlag.js index dd95845..bc2d782 100644 --- a/src/entities/wordFlag.js +++ b/src/entities/wordFlag.js @@ -4,6 +4,6 @@ game.createWordFlag = () => { wordFlag.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordFlag.addComponent(game.components.Pushable({pushable: true})); wordFlag.addComponent(game.components.Alive()); - wordFlag.sprite = game.sprites.wordFlag; + wordFlag.addComponent(game.components.Sprite({spriteName: "wordFlag"})) return wordFlag; } diff --git a/src/entities/wordIs.js b/src/entities/wordIs.js index ca00856..15bcbea 100644 --- a/src/entities/wordIs.js +++ b/src/entities/wordIs.js @@ -5,6 +5,6 @@ game.createWordIs = () => { // wordIs.addComponent(game.components.Stop({stop: true})); wordIs.addComponent(game.components.Pushable()); wordIs.addComponent(game.components.Alive()); - wordIs.sprite = game.sprites.wordIs; + wordIs.addComponent(game.components.Sprite({spriteName: "wordIs"})) return wordIs; } diff --git a/src/entities/wordKill.js b/src/entities/wordKill.js index 283ce90..8ea04d9 100644 --- a/src/entities/wordKill.js +++ b/src/entities/wordKill.js @@ -4,6 +4,6 @@ game.createWordKill = () => { wordKill.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordKill.addComponent(game.components.Pushable({pushable: true})); wordKill.addComponent(game.components.Alive()); - wordKill.sprite = game.sprites.wordKill; + wordKill.addComponent(game.components.Sprite({spriteName: "wordKill"})) return wordKill; } diff --git a/src/entities/wordLava.js b/src/entities/wordLava.js index dc50bf3..bb7a005 100644 --- a/src/entities/wordLava.js +++ b/src/entities/wordLava.js @@ -5,6 +5,6 @@ game.createWordLava = () => { wordLava.addComponent(game.components.Pushable({pushable: true})); wordLava.addComponent(game.components.Alive()); - wordLava.sprite = game.sprites.wordLava; + wordLava.addComponent(game.components.Sprite({spriteName: "wordLava"})) return wordLava; } diff --git a/src/entities/wordPush.js b/src/entities/wordPush.js index 20a4b8e..09478f6 100644 --- a/src/entities/wordPush.js +++ b/src/entities/wordPush.js @@ -4,6 +4,6 @@ game.createWordPush = () => { wordPush.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordPush.addComponent(game.components.Pushable({pushable: true})); wordPush.addComponent(game.components.Alive()); - wordPush.sprite = game.sprites.wordPush; + wordPush.addComponent(game.components.Sprite({spriteName: "wordPush"})) return wordPush; } diff --git a/src/entities/wordRock.js b/src/entities/wordRock.js index 96d8982..0897e35 100644 --- a/src/entities/wordRock.js +++ b/src/entities/wordRock.js @@ -4,6 +4,6 @@ game.createWordRock = () => { wordRock.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordRock.addComponent(game.components.Pushable({pushable: true})); wordRock.addComponent(game.components.Alive()); - wordRock.sprite = game.sprites.wordRock; + wordRock.addComponent(game.components.Sprite({spriteName: "wordRock"})) return wordRock; } diff --git a/src/entities/wordSink.js b/src/entities/wordSink.js index 2da3e07..decd480 100644 --- a/src/entities/wordSink.js +++ b/src/entities/wordSink.js @@ -4,6 +4,6 @@ game.createWordSink = () => { wordSink.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordSink.addComponent(game.components.Pushable({pushable: true})); wordSink.addComponent(game.components.Alive()); - wordSink.sprite = game.sprites.wordSink; + wordSink.addComponent(game.components.Sprite({spriteName: "wordSink"})) return wordSink; } diff --git a/src/entities/wordStop.js b/src/entities/wordStop.js index 0f6f97a..6eb79ea 100644 --- a/src/entities/wordStop.js +++ b/src/entities/wordStop.js @@ -4,6 +4,6 @@ game.createWordStop = () => { wordStop.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordStop.addComponent(game.components.Pushable({pushable: true})); wordStop.addComponent(game.components.Alive()); - wordStop.sprite = game.sprites.wordStop; + wordStop.addComponent(game.components.Sprite({spriteName: "wordStop"})) return wordStop; } diff --git a/src/entities/wordWall.js b/src/entities/wordWall.js index 4dac235..ea7068f 100644 --- a/src/entities/wordWall.js +++ b/src/entities/wordWall.js @@ -4,6 +4,6 @@ game.createWordWall = () => { wordWall.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordWall.addComponent(game.components.Pushable({pushable: true})); wordWall.addComponent(game.components.Alive()); - wordWall.sprite = game.sprites.wordWall; + wordWall.addComponent(game.components.Sprite({spriteName: "wordWall"})) return wordWall; } diff --git a/src/entities/wordWater.js b/src/entities/wordWater.js index e6272d1..c6404bf 100644 --- a/src/entities/wordWater.js +++ b/src/entities/wordWater.js @@ -4,6 +4,6 @@ game.createWordWater = () => { wordWater.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordWater.addComponent(game.components.Pushable({pushable: true})); wordWater.addComponent(game.components.Alive()); - wordWater.sprite = game.sprites.wordWater; + wordWater.addComponent(game.components.Sprite({spriteName: "wordWater"})) return wordWater; } diff --git a/src/entities/wordWin.js b/src/entities/wordWin.js index a3830b9..ed837d0 100644 --- a/src/entities/wordWin.js +++ b/src/entities/wordWin.js @@ -4,6 +4,6 @@ game.createWordWin = () => { wordWin.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordWin.addComponent(game.components.Pushable({pushable: true})); wordWin.addComponent(game.components.Alive()); - wordWin.sprite = game.sprites.wordWin; + wordWin.addComponent(game.components.Sprite({spriteName: "wordWin"})) return wordWin; } diff --git a/src/entities/wordYou.js b/src/entities/wordYou.js index 49a0044..89a3723 100644 --- a/src/entities/wordYou.js +++ b/src/entities/wordYou.js @@ -4,6 +4,6 @@ game.createWordYou = () => { wordYou.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100})); wordYou.addComponent(game.components.Pushable({pushable: true})); wordYou.addComponent(game.components.Alive()); - wordYou.sprite = game.sprites.wordYou; + wordYou.addComponent(game.components.Sprite({spriteName: "wordYou"})) return wordYou; } diff --git a/src/game.js b/src/game.js index 50db687..753d028 100644 --- a/src/game.js +++ b/src/game.js @@ -26,14 +26,14 @@ game.initialize = () => { // 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 = { - 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), - }; + game.systemOrder = ["gridSystem", "collisionSystem", "physics", "keyboardInput", "undo", "render"]; + game.systems = { }; + game.systems.physics = game.system.Physics(), + game.systems.gridSystem = game.system.Grid(game.entitiesGrid); + game.systems.collisionSystem = game.system.Collision(game.entitiesGrid); + game.systems.render = game.system.Render(game.graphics); + game.systems.undo = game.system.Undo(game.entitiesGrid); + game.systems.keyboardInput = game.system.KeyboardInput(game.systems.undo); lastTimeStamp = performance.now() requestAnimationFrame(game.loop); diff --git a/src/render/graphics.js b/src/render/graphics.js index 8a4cb1c..06d0b2c 100644 --- a/src/render/graphics.js +++ b/src/render/graphics.js @@ -52,4 +52,4 @@ game.graphics = ( return { clear, Sprite }; } -)(document.getElementById("game-canvas").getContext("2d")); +)(game.canvas.context); diff --git a/src/systems/collision.js b/src/systems/collision.js index 152dcd6..08a1d91 100644 --- a/src/systems/collision.js +++ b/src/systems/collision.js @@ -1,5 +1,6 @@ game.system.Collision = (entitiesGrid) => { const update = (elapsedTime, entities, changedIds) => { + const thisChangedIds = new Set(); 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); @@ -38,25 +39,25 @@ game.system.Collision = (entitiesGrid) => { entity.removeComponent("momentum"); } else { entitiesToPush.map((e) => { - const particles = game.createBorderParticles({ - colors: ["#16f7c9", "#0d6e5a", "#2fa18a", "#48cfb4", "#58877d", "#178054", "#2cdb92"], - maxSpeed: 0.20, - minRadius: 1, - maxRadius: 3, - minLife: 100, - maxLife: 300, - minAmount: 20, - maxAmount: 50, - }); - particles.addComponent(game.components.Position(e.components.position)); - particles.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim})); - game.entities[particles.id] = particles; +// const particles = game.createBorderParticles({ +// colors: ["#16f7c9", "#0d6e5a", "#2fa18a", "#48cfb4", "#58877d", "#178054", "#2cdb92"], +// maxSpeed: 0.20, +// minRadius: 1, +// maxRadius: 3, +// minLife: 100, +// maxLife: 300, +// minAmount: 20, +// maxAmount: 50, +// }); +// particles.addComponent(game.components.Position(e.components.position)); +// particles.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim})); +// game.entities[particles.id] = particles; e.addComponent(game.components.Momentum({...momentum})) }); } } } - return new Set(); + return thisChangedIds; }; return { update }; }; diff --git a/src/systems/keyboardInput.js b/src/systems/keyboardInput.js index 60a62a1..5ce6737 100644 --- a/src/systems/keyboardInput.js +++ b/src/systems/keyboardInput.js @@ -1,4 +1,4 @@ -game.system.KeyboardInput = () => { +game.system.KeyboardInput = (undoSystem) => { "use strict"; const keys = {}; const keyPress = (event) => { @@ -20,9 +20,11 @@ game.system.KeyboardInput = () => { } else if (controls.includes('down') && keys['ArrowDown']) { entity.addComponent(game.components.Momentum({ dx: 0, dy: 1 })); } - } } + if (keys['z']) { + undoSystem.undo(entities); + } Object.keys(keys).map((key) => delete keys[key]); return new Set(); diff --git a/src/systems/render.js b/src/systems/render.js index adf3e86..d3bacb8 100644 --- a/src/systems/render.js +++ b/src/systems/render.js @@ -10,8 +10,8 @@ game.system.Render = (graphics) => { }); sortedEntities.forEach((entity) => { - if (entity.sprite && entity.hasComponent("position") && entity.hasComponent("appearance")) { - entity.sprite.draw(elapsedTime, {...entity.components.position, ...entity.components.appearance}); + if (entity.hasComponent("position") && entity.hasComponent("appearance") && entity.hasComponent("sprite")) { + game.sprites[entity.components.sprite.spriteName].draw(elapsedTime, {...entity.components.position, ...entity.components.appearance}); } }); diff --git a/src/systems/undo.js b/src/systems/undo.js new file mode 100644 index 0000000..fa36c93 --- /dev/null +++ b/src/systems/undo.js @@ -0,0 +1,32 @@ +game.system.Undo = (entitiesGrid) => { + const states = []; + + const update = (elapsedTime, entities, changedIds) => { + if (changedIds.size) { + lastUndid = false; + const state = {}; + for (let id in entities) { + if (entities[id].hasComponent("gridPosition")) { + state[id] = JSON.parse(JSON.stringify(entities[id].components)); + } + } + states.push(state); + } + return new Set(); + } + + const undo = (entities) => { + states.map((state) => console.log(state[65].gridPosition)); + let state = states.slice(0, -1).pop(); + for (let id in state) { + for (let componentName in state[id]) { + entities[id].addComponent({name: componentName, ...state[id][componentName]}); + } + } + if (states.length > 1) { + states.pop(); + } + } + + return { update, undo }; +} \ No newline at end of file