summaryrefslogtreecommitdiff
path: root/Homework/cs5410/bbiy/src
diff options
context:
space:
mode:
Diffstat (limited to 'Homework/cs5410/bbiy/src')
-rw-r--r--Homework/cs5410/bbiy/src/bootstrap.js117
-rw-r--r--Homework/cs5410/bbiy/src/components/alive.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/appearence.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/burn.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/burnable.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/component.js8
-rw-r--r--Homework/cs5410/bbiy/src/components/controllable.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/gridPosition.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/loadPriority.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/momentum.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/name.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/noun.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/particles.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/position.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/pushable.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/sink.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/sinkable.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/sprite.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/stop.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/verb.js1
-rw-r--r--Homework/cs5410/bbiy/src/components/win.js1
-rw-r--r--Homework/cs5410/bbiy/src/entities/bigblue.js13
-rw-r--r--Homework/cs5410/bbiy/src/entities/borderParticles.js41
-rw-r--r--Homework/cs5410/bbiy/src/entities/entity.js23
-rw-r--r--Homework/cs5410/bbiy/src/entities/flag.js12
-rw-r--r--Homework/cs5410/bbiy/src/entities/floor.js8
-rw-r--r--Homework/cs5410/bbiy/src/entities/grass.js8
-rw-r--r--Homework/cs5410/bbiy/src/entities/hedge.js9
-rw-r--r--Homework/cs5410/bbiy/src/entities/lava.js9
-rw-r--r--Homework/cs5410/bbiy/src/entities/rock.js14
-rw-r--r--Homework/cs5410/bbiy/src/entities/wall.js13
-rw-r--r--Homework/cs5410/bbiy/src/entities/water.js9
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordBigBlue.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordFlag.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordIs.js11
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordKill.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordLava.js11
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordPush.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordRock.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordSink.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordStop.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordWall.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordWater.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordWin.js10
-rw-r--r--Homework/cs5410/bbiy/src/entities/wordYou.js10
-rw-r--r--Homework/cs5410/bbiy/src/game.js72
-rw-r--r--Homework/cs5410/bbiy/src/render/graphics.js47
-rw-r--r--Homework/cs5410/bbiy/src/render/sprites.js156
-rw-r--r--Homework/cs5410/bbiy/src/require.js5
-rw-r--r--Homework/cs5410/bbiy/src/systems/collision.js93
-rw-r--r--Homework/cs5410/bbiy/src/systems/grid.js71
-rw-r--r--Homework/cs5410/bbiy/src/systems/keyboardInput.js46
-rw-r--r--Homework/cs5410/bbiy/src/systems/logic.js149
-rw-r--r--Homework/cs5410/bbiy/src/systems/menu.js114
-rw-r--r--Homework/cs5410/bbiy/src/systems/particle.js57
-rw-r--r--Homework/cs5410/bbiy/src/systems/physics.js16
-rw-r--r--Homework/cs5410/bbiy/src/systems/render.js26
-rw-r--r--Homework/cs5410/bbiy/src/systems/system.js1
-rw-r--r--Homework/cs5410/bbiy/src/systems/undo.js32
-rw-r--r--Homework/cs5410/bbiy/src/utils/clamp.js6
-rw-r--r--Homework/cs5410/bbiy/src/utils/loadLevel.js87
-rw-r--r--Homework/cs5410/bbiy/src/utils/objectEquivalence.js14
-rw-r--r--Homework/cs5410/bbiy/src/utils/randInRange.js4
-rw-r--r--Homework/cs5410/bbiy/src/utils/unitizeVector.js11
64 files changed, 1442 insertions, 0 deletions
diff --git a/Homework/cs5410/bbiy/src/bootstrap.js b/Homework/cs5410/bbiy/src/bootstrap.js
new file mode 100644
index 0000000..09e7ec5
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/bootstrap.js
@@ -0,0 +1,117 @@
+game.bootstrap = (() => {
+ const image_extensions = ["png", "jpeg", "jpg"];
+ const audio_extensions = ["mp3"];
+ const scripts = [
+ {
+ src: [
+ 'src/utils/objectEquivalence.js', 'src/utils/unitizeVector.js', 'src/utils/clamp.js', 'src/utils/loadLevel.js',
+ 'src/utils/randInRange.js'
+ ],
+ id: 'utils'
+ },
+ { src: ['src/render/graphics.js'], id: 'graphics' },
+ { src: ['src/render/sprites.js'], id: 'sprites' },
+ { src: ['src/components/component.js'], id: 'component' },
+ {
+ src: [
+ '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', 'src/components/particles.js', 'src/components/noun.js',
+ 'src/components/name.js', 'src/components/verb.js', 'src/components/burn.js',
+ 'src/components/burnable.js', 'src/components/sink.js', 'src/components/sinkable.js',
+ 'src/components/win.js',
+ ],
+ id: 'components'
+ },
+ { src: ['src/entities/entity.js'], id: 'entity' },
+ {
+ src: [
+ 'src/entities/bigblue.js', 'src/entities/flag.js', 'src/entities/floor.js', 'src/entities/grass.js', 'src/entities/hedge.js',
+ 'src/entities/lava.js', 'src/entities/rock.js', 'src/entities/wall.js', 'src/entities/wordBigBlue.js',
+ 'src/entities/wordFlag.js', 'src/entities/wordIs.js', 'src/entities/wordKill.js', 'src/entities/wordLava.js',
+ 'src/entities/wordPush.js', 'src/entities/wordRock.js', 'src/entities/wordSink.js', 'src/entities/wordStop.js',
+ 'src/entities/wordWall.js', 'src/entities/wordWater.js', 'src/entities/wordWin.js', 'src/entities/wordYou.js',
+ 'src/entities/borderParticles.js', 'src/entities/water.js'
+ ],
+ id: 'entities'
+ },
+ { 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/undo.js', 'src/systems/particle.js', 'src/systems/menu.js', 'src/systems/logic.js',
+ ],
+ id: 'systems' },
+ { src: ['src/game.js'], id: 'game' },
+ ];
+ const assets = {};
+ [
+ "bigblue", "flag", "floor", "grass", "hedge", "lava", "rock",
+ "wall", "wordBigBlue", "wordFlag", "wordIs", "wordKill", "wordLava",
+ "wordPush", "wordRock", "wordSink", "wordStop", "wordWall", "wordWater",
+ "wordWin", "wordYou", "water"
+ ].map((x) => assets[x] = `assets/image/${x}.png`);
+ [
+ "music", "death", "move", "win"
+ ].map((x) => assets[x] = `assets/sound/${x}.mp3`);
+
+ const loadScripts = function(onDone) {
+ if (scripts.length) {
+ let script = scripts.shift();
+ require(script.src, () => {
+ loadScripts(onDone);
+ });
+ } else {
+ onDone();
+ }
+ }
+
+ const loadAsset = (source) => {
+ let fileExtension = source.substr(source.lastIndexOf('.') + 1);
+ return fetch(source)
+ .then((r) => r.blob())
+ .then((r) => {
+ let asset;
+ if (image_extensions.includes(fileExtension)) {
+ asset = new Image();
+ } else if (audio_extensions.includes(fileExtension)) {
+ asset = new Audio();
+ }
+ asset.src = URL.createObjectURL(r);
+ const ready = () => URL.revokeObjectURL(asset.src);
+ if (asset instanceof Image) {
+ asset.onload = ready;
+ } else if (asset instanceof Audio) {
+ asset.oncanplaythrough = ready;
+ }
+ return asset;
+ })
+ }
+
+ const loadAssets = function() {
+ game.assets = {};
+ const promises = [];
+ for (let key in assets) {
+ promises.push(loadAsset(assets[key], (asset) => {
+ game.assets[key] = asset;
+ }, (error) => {
+ console.log(error)
+ }));
+ }
+ return Promise.all(Object.keys(assets).map((key) => {
+ return loadAsset(assets[key]).then((asset) => game.assets[key] = asset);
+ }));
+ }
+
+ const loadLevels = function() {
+ game.levels = [];
+ fetch('/levels')
+ .then((r) => r.json())
+ .then((r) => game.levels = r);
+ }
+
+ Promise.all([loadAssets(), loadLevels()]).then(() => {
+ loadScripts(() => game.initialize());
+ })
+})();
diff --git a/Homework/cs5410/bbiy/src/components/alive.js b/Homework/cs5410/bbiy/src/components/alive.js
new file mode 100644
index 0000000..08b0890
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/alive.js
@@ -0,0 +1 @@
+game.components.Alive = () => game.Component('alive'); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/appearence.js b/Homework/cs5410/bbiy/src/components/appearence.js
new file mode 100644
index 0000000..8c2130a
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/appearence.js
@@ -0,0 +1 @@
+game.components.Appearance = ({rot, width, height}) => game.Component('appearance', {rot, width, height}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/burn.js b/Homework/cs5410/bbiy/src/components/burn.js
new file mode 100644
index 0000000..f138e9d
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/burn.js
@@ -0,0 +1 @@
+game.components.Burn = () => game.Component('burn', {}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/burnable.js b/Homework/cs5410/bbiy/src/components/burnable.js
new file mode 100644
index 0000000..d5767e7
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/burnable.js
@@ -0,0 +1 @@
+game.components.Burnable = () => game.Component('burnable', {}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/component.js b/Homework/cs5410/bbiy/src/components/component.js
new file mode 100644
index 0000000..9b55a1f
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/component.js
@@ -0,0 +1,8 @@
+game.components = {};
+
+game.Component = (name, spec) => {
+ return {
+ name,
+ ...spec
+ };
+};
diff --git a/Homework/cs5410/bbiy/src/components/controllable.js b/Homework/cs5410/bbiy/src/components/controllable.js
new file mode 100644
index 0000000..84b05ee
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/controllable.js
@@ -0,0 +1 @@
+game.components.Controllable = ({ controls }) => game.Component('controllable', { controls }); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/gridPosition.js b/Homework/cs5410/bbiy/src/components/gridPosition.js
new file mode 100644
index 0000000..ede4b23
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/gridPosition.js
@@ -0,0 +1 @@
+game.components.GridPosition = ({x, y}) => game.Component('gridPosition', {x, y}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/loadPriority.js b/Homework/cs5410/bbiy/src/components/loadPriority.js
new file mode 100644
index 0000000..35c3887
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/loadPriority.js
@@ -0,0 +1 @@
+game.components.LoadPriority = ({priority}) => game.Component('loadPriority', {priority}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/momentum.js b/Homework/cs5410/bbiy/src/components/momentum.js
new file mode 100644
index 0000000..b974aa7
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/momentum.js
@@ -0,0 +1 @@
+game.components.Momentum = ({dx, dy}) => game.Component('momentum', {dx, dy}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/name.js b/Homework/cs5410/bbiy/src/components/name.js
new file mode 100644
index 0000000..d3bf14a
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/name.js
@@ -0,0 +1 @@
+game.components.Name = ({selector}) => game.Component('name', {selector});
diff --git a/Homework/cs5410/bbiy/src/components/noun.js b/Homework/cs5410/bbiy/src/components/noun.js
new file mode 100644
index 0000000..4b01e06
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/noun.js
@@ -0,0 +1 @@
+game.components.Noun = ({select}) => game.Component('noun', {select});
diff --git a/Homework/cs5410/bbiy/src/components/particles.js b/Homework/cs5410/bbiy/src/components/particles.js
new file mode 100644
index 0000000..8120ff1
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/particles.js
@@ -0,0 +1 @@
+game.components.Particles = (spec) => game.Component('particles', {spec});
diff --git a/Homework/cs5410/bbiy/src/components/position.js b/Homework/cs5410/bbiy/src/components/position.js
new file mode 100644
index 0000000..072a1a6
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/position.js
@@ -0,0 +1 @@
+game.components.Position = ({x, y}) => game.Component('position', {x, y}) \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/pushable.js b/Homework/cs5410/bbiy/src/components/pushable.js
new file mode 100644
index 0000000..85087ea
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/pushable.js
@@ -0,0 +1 @@
+game.components.Pushable = () => game.Component('pushable');
diff --git a/Homework/cs5410/bbiy/src/components/sink.js b/Homework/cs5410/bbiy/src/components/sink.js
new file mode 100644
index 0000000..3a4d9dc
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/sink.js
@@ -0,0 +1 @@
+game.components.Sink = () => game.Component('sink', {}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/sinkable.js b/Homework/cs5410/bbiy/src/components/sinkable.js
new file mode 100644
index 0000000..1fcb132
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/sinkable.js
@@ -0,0 +1 @@
+game.components.Sinkable = () => game.Component('sinkable', {}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/sprite.js b/Homework/cs5410/bbiy/src/components/sprite.js
new file mode 100644
index 0000000..f45975d
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/sprite.js
@@ -0,0 +1 @@
+game.components.Sprite = ({spriteName}) => game.Component('sprite', {spriteName}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/components/stop.js b/Homework/cs5410/bbiy/src/components/stop.js
new file mode 100644
index 0000000..17d4c38
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/stop.js
@@ -0,0 +1 @@
+game.components.Stop = () => game.Component("stop");
diff --git a/Homework/cs5410/bbiy/src/components/verb.js b/Homework/cs5410/bbiy/src/components/verb.js
new file mode 100644
index 0000000..393e48c
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/verb.js
@@ -0,0 +1 @@
+game.components.Verb = ({action}) => game.Component('verb', {action});
diff --git a/Homework/cs5410/bbiy/src/components/win.js b/Homework/cs5410/bbiy/src/components/win.js
new file mode 100644
index 0000000..ea905fc
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/components/win.js
@@ -0,0 +1 @@
+game.components.Win = () => game.Component('win', {}); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/entities/bigblue.js b/Homework/cs5410/bbiy/src/entities/bigblue.js
new file mode 100644
index 0000000..45fbc90
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/bigblue.js
@@ -0,0 +1,13 @@
+game.createBigBlue = () => {
+ const bigBlue = game.Entity();
+ bigBlue.addComponent(game.components.LoadPriority({priority: 1}));
+ bigBlue.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ bigBlue.addComponent(game.components.Alive());
+ bigBlue.addComponent(game.components.Sprite({spriteName: "bigBlue"}));
+
+// bigBlue.addComponent(game.components.Controllable({controls: ['left', 'right', 'up', 'down']}));
+ bigBlue.addComponent(game.components.Name({selector: "bigblue"}));
+ bigBlue.addComponent(game.components.Burnable());
+ bigBlue.addComponent(game.components.Sinkable());
+ return bigBlue;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/borderParticles.js b/Homework/cs5410/bbiy/src/entities/borderParticles.js
new file mode 100644
index 0000000..e1a7e98
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/borderParticles.js
@@ -0,0 +1,41 @@
+game.createBorderParticles = (spawnerSpec) => {
+ const particleSpawner = game.Entity();
+ const spawnFunction = (particleSpec) => {
+ switch (Math.floor(Math.random() * 4)) {
+ case 0:
+ particleSpec.y = 0;
+ particleSpec.dy = -Math.abs(particleSpec.dy);
+ break;
+ case 1:
+ particleSpec.x = 1;
+ particleSpec.dx = Math.abs(particleSpec.dx);
+ break;
+ case 2:
+ particleSpec.y = 1;
+ particleSpec.dy = Math.abs(particleSpec.dy);
+ break;
+ case 3:
+ particleSpec.x = 0;
+ particleSpec.dx = -Math.abs(particleSpec.dx);
+ break;
+ }
+ return particleSpec;
+ };
+ particleSpawner.addComponent(game.components.Particles({
+ spec: {
+ spawnFunction,
+ colors: ["#666666", "#777777", "#888888", "#999999"],
+ maxSpeed: 0.20,
+ minRadius: 1,
+ maxRadius: 3,
+ minLife: 100,
+ maxLife: 300,
+ minAmount: 20,
+ maxAmount: 50,
+ ...spawnerSpec,
+ }
+ }));
+ particleSpawner.addComponent(game.components.LoadPriority({priority: 1}));
+ particleSpawner.addComponent(game.components.Alive());
+ return particleSpawner;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/entity.js b/Homework/cs5410/bbiy/src/entities/entity.js
new file mode 100644
index 0000000..3da032c
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/entity.js
@@ -0,0 +1,23 @@
+game.nextId = 0;
+
+game.Entity = (id=game.nextId++) => {
+ const components = {};
+
+ const addComponent = (component) => {
+ components[component.name] = component;
+ };
+ const hasComponent = (componentName) => components[componentName] !== undefined;
+ const removeComponent = (componentName) => {
+ if (hasComponent(componentName)) {
+ delete components[componentName];
+ }
+ };
+
+ return {
+ id,
+ components,
+ addComponent,
+ removeComponent,
+ hasComponent
+ };
+} \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/entities/flag.js b/Homework/cs5410/bbiy/src/entities/flag.js
new file mode 100644
index 0000000..e8c662a
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/flag.js
@@ -0,0 +1,12 @@
+game.createFlag = () => {
+ const flag = game.Entity();
+ flag.addComponent(game.components.LoadPriority({priority: 5}));
+ flag.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ flag.addComponent(game.components.Alive());
+ flag.addComponent(game.components.Sprite({spriteName: "flag"}))
+ flag.addComponent(game.components.Name({selector: "flag"}));
+
+ flag.addComponent(game.components.Burnable());
+ flag.addComponent(game.components.Sinkable());
+ return flag;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/floor.js b/Homework/cs5410/bbiy/src/entities/floor.js
new file mode 100644
index 0000000..95cbcf2
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/floor.js
@@ -0,0 +1,8 @@
+game.createFloor = () => {
+ const floor = game.Entity();
+ floor.addComponent(game.components.LoadPriority({priority: 6}));
+ floor.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ floor.addComponent(game.components.Alive());
+ floor.addComponent(game.components.Sprite({spriteName: "floor"}))
+ return floor;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/grass.js b/Homework/cs5410/bbiy/src/entities/grass.js
new file mode 100644
index 0000000..7f26712
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/grass.js
@@ -0,0 +1,8 @@
+game.createGrass = () => {
+ const grass = game.Entity();
+ grass.addComponent(game.components.LoadPriority({priority: 6}));
+ grass.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ grass.addComponent(game.components.Alive());
+ grass.addComponent(game.components.Sprite({spriteName: "grass"}))
+ return grass;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/hedge.js b/Homework/cs5410/bbiy/src/entities/hedge.js
new file mode 100644
index 0000000..90d069b
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/hedge.js
@@ -0,0 +1,9 @@
+game.createHedge = () => {
+ const hedge = game.Entity();
+ hedge.addComponent(game.components.LoadPriority({priority: 6}));
+ hedge.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ hedge.addComponent(game.components.Stop({stop: true}));
+ hedge.addComponent(game.components.Alive());
+ hedge.addComponent(game.components.Sprite({spriteName: "hedge"}))
+ return hedge;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/lava.js b/Homework/cs5410/bbiy/src/entities/lava.js
new file mode 100644
index 0000000..e529812
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/lava.js
@@ -0,0 +1,9 @@
+game.createLava = () => {
+ const lava = game.Entity();
+ lava.addComponent(game.components.LoadPriority({priority: 6}));
+ lava.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ lava.addComponent(game.components.Alive());
+ lava.addComponent(game.components.Sprite({spriteName: "lava"}))
+ lava.addComponent(game.components.Name({selector: "lava"}));
+ return lava;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/rock.js b/Homework/cs5410/bbiy/src/entities/rock.js
new file mode 100644
index 0000000..a87710a
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/rock.js
@@ -0,0 +1,14 @@
+game.createRock = () => {
+ const rock = game.Entity();
+ rock.addComponent(game.components.LoadPriority({priority: 2}));
+ rock.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ rock.addComponent(game.components.Alive());
+ rock.addComponent(game.components.Sprite({spriteName: "rock"}));;
+
+
+// rock.addComponent(game.components.Pushable());
+ rock.addComponent(game.components.Name({selector: "rock"}));
+ rock.addComponent(game.components.Sinkable());
+
+ return rock;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wall.js b/Homework/cs5410/bbiy/src/entities/wall.js
new file mode 100644
index 0000000..e7549ca
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wall.js
@@ -0,0 +1,13 @@
+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());
+ wall.addComponent(game.components.Name({selector: "wall"}));
+ wall.addComponent(game.components.Alive());
+ wall.addComponent(game.components.Sprite({spriteName: "wall"}));
+
+ wall.addComponent(game.components.Burnable());
+ wall.addComponent(game.components.Sinkable());
+ return wall;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/water.js b/Homework/cs5410/bbiy/src/entities/water.js
new file mode 100644
index 0000000..11522b1
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/water.js
@@ -0,0 +1,9 @@
+game.createWater = () => {
+ const water = game.Entity();
+ water.addComponent(game.components.LoadPriority({priority: 5}));
+ water.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ water.addComponent(game.components.Alive());
+ water.addComponent(game.components.Sprite({spriteName: "water"}))
+ water.addComponent(game.components.Name({selector: "water"}))
+ return water;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordBigBlue.js b/Homework/cs5410/bbiy/src/entities/wordBigBlue.js
new file mode 100644
index 0000000..15aaa0e
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordBigBlue.js
@@ -0,0 +1,10 @@
+game.createWordBigBlue = () => {
+ const wordBigBlue = game.Entity();
+ wordBigBlue.addComponent(game.components.LoadPriority({priority: 3}));
+ wordBigBlue.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordBigBlue.addComponent(game.components.Pushable({pushable: true}));
+ wordBigBlue.addComponent(game.components.Alive());
+ wordBigBlue.addComponent(game.components.Sprite({spriteName: "wordBigBlue"}));
+ wordBigBlue.addComponent(game.components.Noun({select: "bigblue"}));
+ return wordBigBlue;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordFlag.js b/Homework/cs5410/bbiy/src/entities/wordFlag.js
new file mode 100644
index 0000000..79617ea
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordFlag.js
@@ -0,0 +1,10 @@
+game.createWordFlag = () => {
+ const wordFlag = game.Entity();
+ wordFlag.addComponent(game.components.LoadPriority({priority: 3}));
+ wordFlag.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordFlag.addComponent(game.components.Pushable({pushable: true}));
+ wordFlag.addComponent(game.components.Alive());
+ wordFlag.addComponent(game.components.Sprite({spriteName: "wordFlag"}));
+ wordFlag.addComponent(game.components.Noun({select: "flag"}));
+ return wordFlag;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordIs.js b/Homework/cs5410/bbiy/src/entities/wordIs.js
new file mode 100644
index 0000000..041f10c
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordIs.js
@@ -0,0 +1,11 @@
+game.createWordIs = () => {
+ const wordIs = game.Entity();
+ wordIs.addComponent(game.components.LoadPriority({priority: 3}));
+ wordIs.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ // wordIs.addComponent(game.components.Stop({stop: true}));
+ wordIs.addComponent(game.components.Pushable());
+ wordIs.addComponent(game.components.Alive());
+ wordIs.addComponent(game.components.Sprite({spriteName: "wordIs"}));
+ wordIs.addComponent(game.components.Verb({action: "Is"}));
+ return wordIs;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordKill.js b/Homework/cs5410/bbiy/src/entities/wordKill.js
new file mode 100644
index 0000000..6906e9c
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordKill.js
@@ -0,0 +1,10 @@
+game.createWordKill = () => {
+ const wordKill = game.Entity();
+ wordKill.addComponent(game.components.LoadPriority({priority: 3}));
+ wordKill.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordKill.addComponent(game.components.Pushable({pushable: true}));
+ wordKill.addComponent(game.components.Alive());
+ wordKill.addComponent(game.components.Sprite({spriteName: "wordKill"}))
+ wordKill.addComponent(game.components.Verb({action: "burn"}));
+ return wordKill;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordLava.js b/Homework/cs5410/bbiy/src/entities/wordLava.js
new file mode 100644
index 0000000..cf31286
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordLava.js
@@ -0,0 +1,11 @@
+game.createWordLava = () => {
+ const wordLava = game.Entity();
+ wordLava.addComponent(game.components.LoadPriority({priority: 3}));
+ wordLava.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordLava.addComponent(game.components.Pushable({pushable: true}));
+ wordLava.addComponent(game.components.Alive());
+
+ wordLava.addComponent(game.components.Sprite({spriteName: "wordLava"}))
+ wordLava.addComponent(game.components.Noun({select: "lava"}));
+ return wordLava;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordPush.js b/Homework/cs5410/bbiy/src/entities/wordPush.js
new file mode 100644
index 0000000..5594e46
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordPush.js
@@ -0,0 +1,10 @@
+game.createWordPush = () => {
+ const wordPush = game.Entity();
+ wordPush.addComponent(game.components.LoadPriority({priority: 3}));
+ wordPush.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordPush.addComponent(game.components.Pushable({pushable: true}));
+ wordPush.addComponent(game.components.Alive());
+ wordPush.addComponent(game.components.Sprite({spriteName: "wordPush"}));
+ wordPush.addComponent(game.components.Verb({action: "push"}));
+ return wordPush;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordRock.js b/Homework/cs5410/bbiy/src/entities/wordRock.js
new file mode 100644
index 0000000..648f6ba
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordRock.js
@@ -0,0 +1,10 @@
+game.createWordRock = () => {
+ const wordRock = game.Entity();
+ wordRock.addComponent(game.components.LoadPriority({priority: 3}));
+ wordRock.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordRock.addComponent(game.components.Pushable({pushable: true}));
+ wordRock.addComponent(game.components.Alive());
+ wordRock.addComponent(game.components.Sprite({spriteName: "wordRock"}));
+ wordRock.addComponent(game.components.Noun({select: "rock"}));
+ return wordRock;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordSink.js b/Homework/cs5410/bbiy/src/entities/wordSink.js
new file mode 100644
index 0000000..369f922
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordSink.js
@@ -0,0 +1,10 @@
+game.createWordSink = () => {
+ const wordSink = game.Entity();
+ wordSink.addComponent(game.components.LoadPriority({priority: 3}));
+ wordSink.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordSink.addComponent(game.components.Pushable({pushable: true}));
+ wordSink.addComponent(game.components.Alive());
+ wordSink.addComponent(game.components.Sprite({spriteName: "wordSink"}));
+ wordSink.addComponent(game.components.Verb({action: "sink"}));
+ return wordSink;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordStop.js b/Homework/cs5410/bbiy/src/entities/wordStop.js
new file mode 100644
index 0000000..e2ad45c
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordStop.js
@@ -0,0 +1,10 @@
+game.createWordStop = () => {
+ const wordStop = game.Entity();
+ wordStop.addComponent(game.components.LoadPriority({priority: 3}));
+ wordStop.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordStop.addComponent(game.components.Pushable({pushable: true}));
+ wordStop.addComponent(game.components.Alive());
+ wordStop.addComponent(game.components.Sprite({spriteName: "wordStop"}));
+ wordStop.addComponent(game.components.Verb({action: "stop"}));
+ return wordStop;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordWall.js b/Homework/cs5410/bbiy/src/entities/wordWall.js
new file mode 100644
index 0000000..277ab69
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordWall.js
@@ -0,0 +1,10 @@
+game.createWordWall = () => {
+ const wordWall = game.Entity();
+ wordWall.addComponent(game.components.LoadPriority({priority: 3}));
+ wordWall.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordWall.addComponent(game.components.Pushable({pushable: true}));
+ wordWall.addComponent(game.components.Alive());
+ wordWall.addComponent(game.components.Noun({select: "wall"}));
+ wordWall.addComponent(game.components.Sprite({spriteName: "wordWall"}));
+ return wordWall;
+};
diff --git a/Homework/cs5410/bbiy/src/entities/wordWater.js b/Homework/cs5410/bbiy/src/entities/wordWater.js
new file mode 100644
index 0000000..eb0c1be
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordWater.js
@@ -0,0 +1,10 @@
+game.createWordWater = () => {
+ const wordWater = game.Entity();
+ wordWater.addComponent(game.components.LoadPriority({priority: 3}));
+ wordWater.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordWater.addComponent(game.components.Pushable({pushable: true}));
+ wordWater.addComponent(game.components.Alive());
+ wordWater.addComponent(game.components.Sprite({spriteName: "wordWater"}));
+ wordWater.addComponent(game.components.Noun({select: "water"}));
+ return wordWater;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordWin.js b/Homework/cs5410/bbiy/src/entities/wordWin.js
new file mode 100644
index 0000000..e8948ee
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordWin.js
@@ -0,0 +1,10 @@
+game.createWordWin = () => {
+ const wordWin = game.Entity();
+ wordWin.addComponent(game.components.LoadPriority({priority: 3}));
+ wordWin.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordWin.addComponent(game.components.Pushable({pushable: true}));
+ wordWin.addComponent(game.components.Alive());
+ wordWin.addComponent(game.components.Sprite({spriteName: "wordWin"}));
+ wordWin.addComponent(game.components.Verb({action: "win"}));
+ return wordWin;
+}
diff --git a/Homework/cs5410/bbiy/src/entities/wordYou.js b/Homework/cs5410/bbiy/src/entities/wordYou.js
new file mode 100644
index 0000000..1bf698f
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/entities/wordYou.js
@@ -0,0 +1,10 @@
+game.createWordYou = () => {
+ const wordYou = game.Entity();
+ wordYou.addComponent(game.components.LoadPriority({priority: 3}));
+ wordYou.addComponent(game.components.Appearance({rot: 0, width: 100, height: 100}));
+ wordYou.addComponent(game.components.Pushable({pushable: true}));
+ wordYou.addComponent(game.components.Alive());
+ wordYou.addComponent(game.components.Sprite({spriteName: "wordYou"}));
+ wordYou.addComponent(game.components.Verb({action: "you"}));
+ return wordYou;
+};
diff --git a/Homework/cs5410/bbiy/src/game.js b/Homework/cs5410/bbiy/src/game.js
new file mode 100644
index 0000000..5a7e391
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/game.js
@@ -0,0 +1,72 @@
+game.loop = (timeStamp) => {
+ if (!game.running) {
+ return;
+ }
+
+ let elapsedTime = timeStamp - game.lastTimeStamp;
+ game.lastTimeStamp = timeStamp;
+
+ const changedIds = new Set();
+ game.systemOrder.map((i) => {
+ game.systems[i]
+ .update(elapsedTime, game.entities, changedIds)
+ .forEach((id) => changedIds.add(id));
+ });
+
+ for (let id in game.entities) {
+ if (game.entities[id].hasComponent("particles") && !game.entities[id].hasComponent("alive")) {
+ delete game.entities[id];
+ }
+ }
+
+ requestAnimationFrame(game.loop);
+};
+
+game.toggleRunning = () => {
+ game.running = !game.running;
+};
+
+game.startLoop = () => {
+ game.running = true;
+ game.lastTimeStamp = performance.now();
+ game.assets.music.play();
+ if (game.assets.music.paused) {
+ alert("Failed to start background music; please allow autoplay in your browser settings.");
+ }
+ requestAnimationFrame(game.loop);
+};
+
+game.loadSystems = () => {
+ game.systemOrder = ["grid", "collision", "physics", "keyboardInput", "particle", "logic", "undo", "render"];
+ game.systems = { };
+ game.systems.physics = game.system.Physics(),
+ game.systems.grid = game.system.Grid(game.entitiesGrid);
+ game.systems.collision = game.system.Collision(game.entitiesGrid);
+ game.systems.render = game.system.Render(game.graphics);
+ game.systems.particle = game.system.Particle(game.canvas.context);
+ game.systems.keyboardInput = game.system.KeyboardInput();
+ game.systems.logic = game.system.Logic(game.entitiesGrid);
+ game.systems.undo = game.system.Undo(game.entitiesGrid, game.systems.logic, game.systems.grid);
+ game.systems.menu = game.system.Menu();
+};
+
+game.loadLevelIndex = (level) => {
+ game.win = false;
+
+ game.level = level;
+ [game.entities, game.config] = game.loadLevel(game.levels[game.level]);
+
+ // Maintained by grid system as a side-effect
+ game.entitiesGrid = Array(game.config.yDim).fill(null).map(() => Array(game.config.xDim).fill(null).map(() => new Map()));
+ game.loadSystems();
+};
+
+game.initialize = () => {
+ game.assets.music.addEventListener('ended', function() {
+ this.currentTime = 0;
+ this.play();
+ }, false);
+
+ game.loadLevelIndex(0);
+ game.startLoop();
+};
diff --git a/Homework/cs5410/bbiy/src/render/graphics.js b/Homework/cs5410/bbiy/src/render/graphics.js
new file mode 100644
index 0000000..aa4195e
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/render/graphics.js
@@ -0,0 +1,47 @@
+// Pretty much a copy of my centipede code
+game.graphics = (
+ (context) => {
+ context.imageSmoothingEnabled = false;
+ const clear = () => {
+ context.clearRect(0, 0, game.canvas.width, game.canvas.height);
+ };
+
+ const Sprite = ({image, spriteX, spriteY, spriteWidth, spriteHeight, timePerFrame, cols, rows, numFrames, color, drawFunction}) => {
+ timePerFrame = timePerFrame ?? 100;
+ numFrames = numFrames ?? 1;
+ cols = cols ?? numFrames;
+ rows = rows ?? 1;
+ spriteX = spriteX ?? 0;
+ spriteY = spriteY ?? 0;
+
+ let currentFrame = 0;
+ let lastTime = performance.now();
+
+ let draw;
+ if (!drawFunction) {
+ draw = (_elapsedTime, {x, y, rot, width, height}) => {
+ if (numFrames > 1) {
+ if (performance.now()-lastTime > timePerFrame) {
+ lastTime = performance.now();
+ currentFrame = (currentFrame + 1) % numFrames;
+ }
+ }
+ context.save();
+ context.translate(x+width/2, y+height/2);
+ context.rotate(rot * Math.PI / 180);
+ context.translate(-x-width/2, -y-height/2);
+ const row = currentFrame % rows;
+ const col = Math.floor(currentFrame / rows);
+ context.drawImage(image, spriteX+col*spriteWidth, spriteY+row*spriteHeight, spriteWidth, spriteHeight, x, y, width, height);
+
+ context.restore();
+ };
+ } else {
+ draw = (elapsedTime, drawSpec) => drawFunction(elapsedTime, drawSpec, context);
+ }
+ return { draw };
+ }
+
+ return { clear, Sprite };
+ }
+)(game.canvas.context);
diff --git a/Homework/cs5410/bbiy/src/render/sprites.js b/Homework/cs5410/bbiy/src/render/sprites.js
new file mode 100644
index 0000000..d8ae126
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/render/sprites.js
@@ -0,0 +1,156 @@
+game.sprites = {
+ bigBlue: game.graphics.Sprite({
+ image: game.assets.bigblue,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ flag: game.graphics.Sprite({
+ image: game.assets.flag,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ floor: game.graphics.Sprite({
+ image: game.assets.floor,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ hedge: game.graphics.Sprite({
+ image: game.assets.hedge,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 250,
+ }),
+ grass: game.graphics.Sprite({
+ image: game.assets.grass,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ lava: game.graphics.Sprite({
+ image: game.assets.lava,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ rock: game.graphics.Sprite({
+ image: game.assets.rock,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wall: game.graphics.Sprite({
+ image: game.assets.wall,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ water: game.graphics.Sprite({
+ image: game.assets.water,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordBigBlue: game.graphics.Sprite({
+ image: game.assets.wordBigBlue,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordFlag: game.graphics.Sprite({
+ image: game.assets.wordFlag,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordIs: game.graphics.Sprite({
+ image: game.assets.wordIs,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordKill: game.graphics.Sprite({
+ image: game.assets.wordKill,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordLava: game.graphics.Sprite({
+ image: game.assets.wordLava,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordPush: game.graphics.Sprite({
+ image: game.assets.wordPush,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordRock: game.graphics.Sprite({
+ image: game.assets.wordRock,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordSink: game.graphics.Sprite({
+ image: game.assets.wordSink,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordStop: game.graphics.Sprite({
+ image: game.assets.wordStop,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordWall: game.graphics.Sprite({
+ image: game.assets.wordWall,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordWater: game.graphics.Sprite({
+ image: game.assets.wordWater,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordWin: game.graphics.Sprite({
+ image: game.assets.wordWin,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+ wordYou: game.graphics.Sprite({
+ image: game.assets.wordYou,
+ spriteHeight: 24,
+ spriteWidth: 24,
+ numFrames: 3,
+ timePerFrame: 100,
+ }),
+};
diff --git a/Homework/cs5410/bbiy/src/require.js b/Homework/cs5410/bbiy/src/require.js
new file mode 100644
index 0000000..a4203f0
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/require.js
@@ -0,0 +1,5 @@
+/** vim: et:ts=4:sw=4:sts=4
+ * @license RequireJS 2.3.6 Copyright jQuery Foundation and other contributors.
+ * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
+ */
+var requirejs,require,define;!function(global,setTimeout){var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.6",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){var i;if(e)for(i=0;i<e.length&&(!e[i]||!t(e[i],i,e));i+=1);}function eachReverse(e,t){var i;if(e)for(i=e.length-1;-1<i&&(!e[i]||!t(e[i],i,e));i-=1);}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(i,e,r,n){return e&&eachProp(e,function(e,t){!r&&hasProp(i,t)||(!n||"object"!=typeof e||!e||isArray(e)||isFunction(e)||e instanceof RegExp?i[t]=e:(i[t]||(i[t]={}),mixin(i[t],e,r,n)))}),i}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttps://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}if(void 0===define){if(void 0!==requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}void 0===require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),(n=getOwn(contexts,a))||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick=void 0!==setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(t){req[t]=function(){var e=contexts[defContextName];return e.require[t].apply(e,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],baseElement=document.getElementsByTagName("base")[0],baseElement&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(t,i,r){var e,n=t&&t.config||{};if(isBrowser)return(e=req.createNode(n,i,r)).setAttribute("data-requirecontext",t.contextName),e.setAttribute("data-requiremodule",i),!e.attachEvent||e.attachEvent.toString&&e.attachEvent.toString().indexOf("[native code")<0||isOpera?(e.addEventListener("load",t.onScriptLoad,!1),e.addEventListener("error",t.onScriptError,!1)):(useInteractive=!0,e.attachEvent("onreadystatechange",t.onScriptLoad)),e.src=r,n.onNodeCreated&&n.onNodeCreated(e,n,i,r),currentlyAddingScript=e,baseElement?head.insertBefore(e,baseElement):head.appendChild(e),currentlyAddingScript=null,e;if(isWebWorker)try{setTimeout(function(){},0),importScripts(r),t.completeLoad(i)}catch(e){t.onError(makeError("importscripts","importScripts failed for "+i+" at "+r,e,[i]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||-1!==mainScript.indexOf("!")||(mainScript=(src=mainScript.split("/")).pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,i,t){var r,n;"string"!=typeof e&&(t=i,i=e,e=null),isArray(i)||(t=i,i=null),!i&&isFunction(t)&&(i=[],t.length&&(t.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,t){i.push(t)}),i=(1===t.length?["require"]:["require","exports","module"]).concat(i))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript())&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")]),n?(n.defQueue.push([e,i,t]),n.defQueueMap[e]=!0):globalDefQueue.push([e,i,t])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}function newContext(u){var i,e,l,c,d,g={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},p={},f={},r={},h=[],m={},n={},v={},x=1,b=1;function q(e,t,i){var r,n,o,a,s,u,c,d,p,f,l=t&&t.split("/"),h=g.map,m=h&&h["*"];if(e&&(u=(e=e.split("/")).length-1,g.nodeIdCompat&&jsSuffixRegExp.test(e[u])&&(e[u]=e[u].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&l&&(e=l.slice(0,l.length-1).concat(e)),function(e){var t,i;for(t=0;t<e.length;t++)if("."===(i=e[t]))e.splice(t,1),t-=1;else if(".."===i){if(0===t||1===t&&".."===e[2]||".."===e[t-1])continue;0<t&&(e.splice(t-1,2),t-=2)}}(e),e=e.join("/")),i&&h&&(l||m)){e:for(o=(n=e.split("/")).length;0<o;o-=1){if(s=n.slice(0,o).join("/"),l)for(a=l.length;0<a;a-=1)if((r=getOwn(h,l.slice(0,a).join("/")))&&(r=getOwn(r,s))){c=r,d=o;break e}!p&&m&&getOwn(m,s)&&(p=getOwn(m,s),f=o)}!c&&p&&(c=p,d=f),c&&(n.splice(0,d,c),e=n.join("/"))}return getOwn(g.pkgs,e)||e}function E(t){isBrowser&&each(scripts(),function(e){if(e.getAttribute("data-requiremodule")===t&&e.getAttribute("data-requirecontext")===l.contextName)return e.parentNode.removeChild(e),!0})}function w(e){var t=getOwn(g.paths,e);if(t&&isArray(t)&&1<t.length)return t.shift(),l.require.undef(e),l.makeRequire(null,{skipMap:!0})([e]),!0}function y(e){var t,i=e?e.indexOf("!"):-1;return-1<i&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function S(e,t,i,r){var n,o,a,s,u=null,c=t?t.name:null,d=e,p=!0,f="";return e||(p=!1,e="_@r"+(x+=1)),u=(s=y(e))[0],e=s[1],u&&(u=q(u,c,r),o=getOwn(m,u)),e&&(u?f=i?e:o&&o.normalize?o.normalize(e,function(e){return q(e,c,r)}):-1===e.indexOf("!")?q(e,c,r):e:(u=(s=y(f=q(e,c,r)))[0],f=s[1],i=!0,n=l.nameToUrl(f))),{prefix:u,name:f,parentMap:t,unnormalized:!!(a=!u||o||i?"":"_unnormalized"+(b+=1)),url:n,originalName:d,isDefine:p,id:(u?u+"!"+f:f)+a}}function k(e){var t=e.id,i=getOwn(p,t);return i||(i=p[t]=new l.Module(e)),i}function M(e,t,i){var r=e.id,n=getOwn(p,r);!hasProp(m,r)||n&&!n.defineEmitComplete?(n=k(e)).error&&"error"===t?i(n.error):n.on(t,i):"defined"===t&&i(m[r])}function O(i,e){var t=i.requireModules,r=!1;e?e(i):(each(t,function(e){var t=getOwn(p,e);t&&(t.error=i,t.events.error&&(r=!0,t.emit("error",i)))}),r||req.onError(i))}function j(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(l.defQueueMap[t]=!0),h.push(e)}),globalDefQueue=[])}function P(e){delete p[e],delete f[e]}function R(){var e,r,t=1e3*g.waitSeconds,n=t&&l.startTime+t<(new Date).getTime(),o=[],a=[],s=!1,u=!0;if(!i){if(i=!0,eachProp(f,function(e){var t=e.map,i=t.id;if(e.enabled&&(t.isDefine||a.push(e),!e.error))if(!e.inited&&n)w(i)?s=r=!0:(o.push(i),E(i));else if(!e.inited&&e.fetched&&t.isDefine&&(s=!0,!t.prefix))return u=!1}),n&&o.length)return(e=makeError("timeout","Load timeout for modules: "+o,null,o)).contextName=l.contextName,O(e);u&&each(a,function(e){!function n(o,a,s){var e=o.map.id;o.error?o.emit("error",o.error):(a[e]=!0,each(o.depMaps,function(e,t){var i=e.id,r=getOwn(p,i);!r||o.depMatched[t]||s[i]||(getOwn(a,i)?(o.defineDep(t,m[i]),o.check()):n(r,a,s))}),s[e]=!0)}(e,{},{})}),n&&!r||!s||!isBrowser&&!isWebWorker||d||(d=setTimeout(function(){d=0,R()},50)),i=!1}}function a(e){hasProp(m,e[0])||k(S(e[0],null,!0)).init(e[1],e[2])}function o(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function s(e){var t=e.currentTarget||e.srcElement;return o(t,l.onScriptLoad,"load","onreadystatechange"),o(t,l.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function T(){var e;for(j();h.length;){if(null===(e=h.shift())[0])return O(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));a(e)}l.defQueueMap={}}return c={require:function(e){return e.require?e.require:e.require=l.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?m[e.map.id]=e.exports:e.exports=m[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(g.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},(e=function(e){this.events=getOwn(r,e.id)||{},this.map=e,this.shim=getOwn(g.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0}).prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,l.startTime=(new Date).getTime();var e=this.map;if(!this.shim)return e.prefix?this.callPlugin():this.load();l.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()}))}},load:function(){var e=this.map.url;n[e]||(n[e]=!0,l.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var t,e,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=l.execCb(i,o,r,n)}catch(e){t=e}else n=l.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&((e=this.module)?n=e.exports:this.usingExports&&(n=this.exports)),t)return t.requireMap=this.map,t.requireModules=this.map.isDefine?[this.map.id]:null,t.requireType=this.map.isDefine?"define":"require",O(this.error=t)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(m[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(l,this.map,a)}P(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(l.defQueueMap,i)||this.fetch()}},callPlugin:function(){var u=this.map,c=u.id,e=S(u.prefix);this.depMaps.push(e),M(e,"defined",bind(this,function(e){var o,t,i,r=getOwn(v,this.map.id),n=this.map.name,a=this.map.parentMap?this.map.parentMap.name:null,s=l.makeRequire(u.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(e.normalize&&(n=e.normalize(n,function(e){return q(e,a,!0)})||""),M(t=S(u.prefix+"!"+n,this.map.parentMap,!0),"defined",bind(this,function(e){this.map.normalizedMap=t,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),void((i=getOwn(p,t.id))&&(this.depMaps.push(t),this.events.error&&i.on("error",bind(this,function(e){this.emit("error",e)})),i.enable()))):r?(this.map.url=l.nameToUrl(r),void this.load()):((o=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})})).error=bind(this,function(e){this.inited=!0,(this.error=e).requireModules=[c],eachProp(p,function(e){0===e.map.id.indexOf(c+"_unnormalized")&&P(e.map.id)}),O(e)}),o.fromText=bind(this,function(e,t){var i=u.name,r=S(i),n=useInteractive;t&&(e=t),n&&(useInteractive=!1),k(r),hasProp(g.config,c)&&(g.config[i]=g.config[c]);try{req.exec(e)}catch(e){return O(makeError("fromtexteval","fromText eval for "+c+" failed: "+e,e,[c]))}n&&(useInteractive=!0),this.depMaps.push(r),l.completeLoad(i),s([i],o)}),void e.load(u.name,s,o,g))})),l.enable(e,this),this.pluginMaps[e.id]=e},enable:function(){(f[this.map.id]=this).enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=S(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(c,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,M(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?M(e,"error",bind(this,this.errback)):this.events.error&&M(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=p[i],hasProp(c,i)||!r||r.enabled||l.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(p,e.id);t&&!t.enabled&&l.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},(l={config:g,contextName:u,registry:p,defined:m,urlFetched:n,defQueue:h,defQueueMap:{},Module:e,makeModuleMap:S,nextTick:req.nextTick,onError:O,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var i=e.urlArgs;e.urlArgs=function(e,t){return(-1===t.indexOf("?")?"?":"&")+i}}var r=g.shim,n={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){n[t]?(g[t]||(g[t]={}),mixin(g[t],e,!0,!0)):g[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(v[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=l.makeShimExports(e)),r[t]=e}),g.shim=r),e.packages&&each(e.packages,function(e){var t;t=(e="string"==typeof e?{name:e}:e).name,e.location&&(g.paths[t]=e.location),g.pkgs[t]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(p,function(e,t){e.inited||e.map.unnormalized||(e.map=S(t,null,!0))}),(e.deps||e.callback)&&l.require(e.deps||[],e.callback)},makeShimExports:function(t){return function(){var e;return t.init&&(e=t.init.apply(global,arguments)),e||t.exports&&getGlobal(t.exports)}},makeRequire:function(o,a){function s(e,t,i){var r,n;return a.enableBuildCallback&&t&&isFunction(t)&&(t.__requireJsBuild=!0),"string"==typeof e?isFunction(t)?O(makeError("requireargs","Invalid require call"),i):o&&hasProp(c,e)?c[e](p[o.id]):req.get?req.get(l,e,o,s):(r=S(e,o,!1,!0).id,hasProp(m,r)?m[r]:O(makeError("notloaded",'Module name "'+r+'" has not been loaded yet for context: '+u+(o?"":". Use require([])")))):(T(),l.nextTick(function(){T(),(n=k(S(null,o))).skipMap=a.skipMap,n.init(e,t,i,{enabled:!0}),R()}),s)}return a=a||{},mixin(s,{isBrowser:isBrowser,toUrl:function(e){var t,i=e.lastIndexOf("."),r=e.split("/")[0];return-1!==i&&(!("."===r||".."===r)||1<i)&&(t=e.substring(i,e.length),e=e.substring(0,i)),l.nameToUrl(q(e,o&&o.id,!0),t,!0)},defined:function(e){return hasProp(m,S(e,o,!1,!0).id)},specified:function(e){return e=S(e,o,!1,!0).id,hasProp(m,e)||hasProp(p,e)}}),o||(s.undef=function(i){j();var e=S(i,o,!0),t=getOwn(p,i);t.undefed=!0,E(i),delete m[i],delete n[e.url],delete r[i],eachReverse(h,function(e,t){e[0]===i&&h.splice(t,1)}),delete l.defQueueMap[i],t&&(t.events.defined&&(r[i]=t.events),P(i))}),s},enable:function(e){getOwn(p,e.id)&&k(e).enable()},completeLoad:function(e){var t,i,r,n=getOwn(g.shim,e)||{},o=n.exports;for(j();h.length;){if(null===(i=h.shift())[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);a(i)}if(l.defQueueMap={},r=getOwn(p,e),!t&&!hasProp(m,e)&&r&&!r.inited){if(!(!g.enforceDefine||o&&getGlobal(o)))return w(e)?void 0:O(makeError("nodefine","No define call for "+e,null,[e]));a([e,n.deps||[],n.exportsFn])}R()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c=getOwn(g.pkgs,e);if(c&&(e=c),u=getOwn(v,e))return l.nameToUrl(u,t,i);if(req.jsExtRegExp.test(e))a=e+(t||"");else{for(r=g.paths,o=(n=e.split("/")).length;0<o;o-=1)if(s=getOwn(r,n.slice(0,o).join("/"))){isArray(s)&&(s=s[0]),n.splice(0,o,s);break}a=n.join("/"),a=("/"===(a+=t||(/^data\:|^blob\:|\?/.test(a)||i?"":".js")).charAt(0)||a.match(/^[\w\+\.\-]+:/)?"":g.baseUrl)+a}return g.urlArgs&&!/^blob\:/.test(a)?a+g.urlArgs(e,a):a},load:function(e,t){req.load(l,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=s(e);l.completeLoad(t.id)}},onScriptError:function(e){var i=s(e);if(!w(i.id)){var r=[];return eachProp(p,function(e,t){0!==t.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===i.id)return r.push(t),!0})}),O(makeError("scripterror",'Script error for "'+i.id+(r.length?'", needed by: '+r.join(", "):'"'),e,[i.id]))}}}).require=l.makeRequire(),l}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState||eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript}}(this,"undefined"==typeof setTimeout?void 0:setTimeout); \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/systems/collision.js b/Homework/cs5410/bbiy/src/systems/collision.js
new file mode 100644
index 0000000..0732c74
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/collision.js
@@ -0,0 +1,93 @@
+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("position") && entity.hasComponent("gridPosition") && (entity.hasComponent("burnable") || entity.hasComponent("sinkable")) && entity.hasComponent("alive")) {
+ for (let collided of entitiesGrid[entity.components.gridPosition.y][entity.components.gridPosition.x].values()) {
+ if (!equivalence(entity, collided) && collided.hasComponent("alive")){
+ if (entity.hasComponent("burnable") && collided.hasComponent("burn")) {
+ const burnedParticleSpawner = game.createBorderParticles({colors: ["#f58d42", "#d6600b", "#c7a312", "#f2b844"]});
+ burnedParticleSpawner.addComponent(game.components.Position(collided.components.position));
+ burnedParticleSpawner.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim}));
+ game.entities[burnedParticleSpawner.id] = burnedParticleSpawner;
+ entity.removeComponent("alive");
+ game.assets.death.play();
+ break;
+ } else if (entity.hasComponent("sinkable") && collided.hasComponent("sink")) {
+ const sunkParticleSpawner = game.createBorderParticles({colors: ["#16f7c9", "#0d6e5a", "#2fa18a", "#48cfb4", "#58877d", "#178054", "#2cdb92"]});
+ sunkParticleSpawner.addComponent(game.components.Position(collided.components.position));
+ sunkParticleSpawner.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim}));
+ game.entities[sunkParticleSpawner.id] = sunkParticleSpawner;
+ entity.removeComponent("alive");
+ collided.removeComponent("alive");
+ game.assets.death.play();
+ break;
+ }
+ }
+ }
+ }
+ if (entity.hasComponent("controllable") && entity.hasComponent("gridPosition")) {
+ for (let collided of entitiesGrid[entity.components.gridPosition.y][entity.components.gridPosition.x].values()) {
+ if (collided.hasComponent("win")) {
+ game.assets.win.play();
+ game.win = true;
+ game.systems.menu.bringUpMenu();
+ game.systems.menu.setState("levelSelect");
+ }
+ }
+
+ if (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("alive")) {
+ if (next.hasComponent("stop")) {
+ 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) {
+ entity.removeComponent("momentum");
+ } else {
+ game.assets.move.play();
+ entitiesToPush.map((e) => {
+ const pushedParticleSpawner = game.createBorderParticles({maxSpeed: 0.1, minAmount: 10, maxAmount: 15});
+ pushedParticleSpawner.addComponent(game.components.Position(e.components.position));
+ pushedParticleSpawner.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim}));
+ game.entities[pushedParticleSpawner.id] = pushedParticleSpawner;
+
+ e.addComponent(game.components.Momentum({...momentum}));
+ });
+ }
+ }
+ }
+ }
+ return thisChangedIds;
+ };
+ return { update };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/grid.js b/Homework/cs5410/bbiy/src/systems/grid.js
new file mode 100644
index 0000000..6d4cf84
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/grid.js
@@ -0,0 +1,71 @@
+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 => {
+ // TODO: Figure out why we HAVE to use game.entities rather than entities
+ // Hint: it breaks when changing a level in the menu
+ const entity = game.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 };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/keyboardInput.js b/Homework/cs5410/bbiy/src/systems/keyboardInput.js
new file mode 100644
index 0000000..1b399ca
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/keyboardInput.js
@@ -0,0 +1,46 @@
+game.system.KeyboardInput = () => {
+ "use strict";
+ const keys = {};
+ const keyPress = (event) => {
+ if (!event.repeat) {
+ keys[event.key] = true;
+ }
+ };
+ const removeKey = (event) => {
+ delete keys[event.key];
+ };
+ const update = (elapsedTime, entities, changedIds) => {
+ for (let id in entities) {
+ const entity = entities[id];
+ if (entity.hasComponent('controllable') && entity.hasComponent('alive')) {
+ const controls = entity.components.controllable.controls;
+ if (!changedIds.has(entity.id)) {
+ if (controls.includes('left') && keys[game.controls.left]) {
+ entity.addComponent(game.components.Momentum({ dx: -1, dy: 0 }));
+ } else if (controls.includes('right') && keys[game.controls.right]) {
+ entity.addComponent(game.components.Momentum({ dx: 1, dy: 0 }));
+ } else if (controls.includes('up') && keys[game.controls.up]) {
+ entity.addComponent(game.components.Momentum({ dx: 0, dy: -1 }));
+ } else if (controls.includes('down') && keys[game.controls.down]) {
+ entity.addComponent(game.components.Momentum({ dx: 0, dy: 1 }));
+ }
+ }
+ }
+ }
+ if (keys[game.controls.undo]) {
+ game.systems.undo.undo(entities);
+ }
+ if (keys[game.controls.reset]) {
+ game.loadLevelIndex(game.level);
+ }
+ if (keys["Escape"]) {
+ game.systems.menu.bringUpMenu();
+ }
+ Object.keys(keys).map((key) => delete keys[key]);
+
+ return new Set();
+ };
+ window.addEventListener("keydown", keyPress);
+ window.addEventListener("keyup", removeKey);
+ return { keys, update };
+}
diff --git a/Homework/cs5410/bbiy/src/systems/logic.js b/Homework/cs5410/bbiy/src/systems/logic.js
new file mode 100644
index 0000000..e8854c1
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/logic.js
@@ -0,0 +1,149 @@
+game.system.Logic = (entitiesGrid) => {
+ "use strict";
+ let currentVerbRules = [];
+ let previousVerbState = {
+ controllable: new Set(),
+ win: new Set(),
+ };
+ const isWord = (entity) => entity.hasComponent("gridPosition") && (entity.hasComponent("verb") || entity.hasComponent("noun"));
+
+ const getFirstWordEntity = (gridPosition) => {
+ if (!equivalence(gridPosition, clamp(gridPosition, game.config.xDim, game.config.yDim))) {
+ return null;
+ }
+ for (let entity of entitiesGrid[gridPosition.y][gridPosition.x].values()) {
+ if (isWord(entity)) {
+ return entity;
+ }
+ }
+ return null;
+ };
+
+ const verbActionsToComponent = {
+ "stop": game.components.Stop(),
+ "push": game.components.Pushable(),
+ "you": game.components.Controllable({controls: ['left', 'right', 'up', 'down']}),
+ "burn": game.components.Burn(),
+ "sink": game.components.Sink(),
+ "win": game.components.Win(),
+ };
+
+ const nounsToEntityCreators = {
+ "rock": game.createRock,
+ "wall": game.createWall,
+ "bigblue": game.createBigBlue,
+ "flag": game.createFlag,
+ "lava": game.createLava,
+ "water": game.createWater,
+ };
+
+ const doOnRule = (rule, entities, direction) => {
+ const [applyee, application] = [entities[rule[0]], entities[rule[1]]];
+ const changedEntityIds = [];
+ if (applyee.hasComponent("noun")) {
+ const entityName = applyee.components.noun.select;
+ if (application.hasComponent("verb")) {
+ const verb = application.components.verb.action;
+ if (direction == "apply") {
+ currentVerbRules.push(rule);
+ }
+ for (let id in entities) {
+ const entity = entities[id];
+ if (entity.hasComponent("alive") && entity.hasComponent("name") && entity.components.name.selector == entityName) {
+ changedEntityIds.push(id);
+ const component = verbActionsToComponent[verb];
+ if (component) {
+ if (direction == "apply") {
+ if (verb == "you") {
+ if (!previousVerbState.controllable.has(id)) {
+ const newYouParticleSpawner = game.createBorderParticles({colors: ["#ffc0cb", "#ffb6c1", "#ffc1cc", "#ffbcd9", "#ff1493"], minAmount: 80, maxAmount: 150, maxSpeed: 0.5});
+ newYouParticleSpawner.addComponent(game.components.Position(entity.components.position));
+ newYouParticleSpawner.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim}));
+ game.entities[newYouParticleSpawner.id] = newYouParticleSpawner;
+ }
+ }
+ if (verb == "win") {
+ if (!previousVerbState.win.has(id)) {
+ game.assets.win.play();
+ }
+ }
+ entity.addComponent(component);
+ } else if (direction == "deapply") {
+ if (entity.hasComponent("controllable")) {
+ previousVerbState.controllable.add(id);
+ }
+ if (entity.hasComponent("win")) {
+ previousVerbState.win.add(id);
+ }
+ entity.removeComponent(component.name);
+ }
+ }
+ }
+ }
+ if (direction == "apply") {
+ if (changedEntityIds.some((id) => previousVerbState.controllable.has(id))) {
+ previousVerbState.controllable = new Set();
+ }
+ }
+ }
+ if (application.hasComponent("noun")) {
+ const applicationEntityName = application.components.noun.select;
+ for (let id in entities) {
+ const entity = entities[id];
+ if (entity.hasComponent("name") && entity.components.name.selector == entityName) {
+ const e = nounsToEntityCreators[applicationEntityName]();
+ ["name", "sprite", "burnable", "sinkable"].map((name) => {
+ if (e.hasComponent(name)) {
+ entity.components[name] = e.components[name];
+ }
+ });
+ }
+ }
+ }
+ };
+ return changedEntityIds;
+ };
+
+ const parseRules = (entities) => {
+ currentVerbRules.map((rule) => doOnRule(rule, entities, "deapply"));
+ currentVerbRules = [];
+ const isWordGridPositions = [];
+ const changedEntityIds = new Set();
+ entitiesGrid.forEach((row) => row.forEach((entitiesInCell) => {
+ for (let entity of entitiesInCell.values()) {
+ if (isWord(entity) && entity.hasComponent("verb") && entity.components.verb.action == "Is") {
+ isWordGridPositions.push(entity.components.gridPosition);
+ }
+ }
+ }));
+ let newRules = [];
+ isWordGridPositions.forEach((gridPosition) => {
+ const east = getFirstWordEntity({y: gridPosition.y, x: gridPosition.x - 1});
+ const west = getFirstWordEntity({y: gridPosition.y, x: gridPosition.x + 1});
+ const north = getFirstWordEntity({x: gridPosition.x, y: gridPosition.y - 1});
+ const south = getFirstWordEntity({x: gridPosition.x, y: gridPosition.y + 1});
+
+ if (east && west) {
+ newRules.push([east.id, west.id]);
+ }
+ if (north && south) {
+ newRules.push([north.id, south.id]);
+ }
+ });
+ newRules = newRules.sort((a, b) => (entities[b[1]].hasComponent("noun") ? 1 : -1) - (entities[a[1]].hasComponent("noun") ? 1 : -1));
+ newRules.map((rule) => doOnRule(rule, entities, "apply").map((id) => changedEntityIds.add(id)));
+ return changedEntityIds;
+ };
+
+ const update = (_elapsedTime, entities, changedIds) => {
+ for (let id of changedIds) {
+ const changed = entities[id];
+ if (changed.hasComponent("verb") || changed.hasComponent("noun")) {
+ return parseRules(entities);
+ }
+ }
+ return new Set();
+ };
+
+ return { update, parseRules };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/menu.js b/Homework/cs5410/bbiy/src/systems/menu.js
new file mode 100644
index 0000000..abd6748
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/menu.js
@@ -0,0 +1,114 @@
+game.system.Menu = () => {
+ let state;
+
+ const menuElement = document.getElementById("menu");
+
+ const escapeEventListener = (e) => {
+ if (e.key == "Escape") {
+ setState('main');
+ }
+ };
+
+ const setState = (newState) => {
+ state = newState;
+ draw();
+ };
+
+ const bringUpMenu = () => {
+ game.running = false;
+ game.assets.music.pause();
+ window.addEventListener("keydown", escapeEventListener);
+ setState("main");
+ };
+
+ const hide = () => {
+ menuElement.style.display = "none";
+ game.startLoop();
+ };
+
+ const listenFor = (action, elementId) => {
+ const element = document.getElementById(elementId);
+ element.innerHTML = "Listening...";
+ const handleKey = (event) => {
+ window.removeEventListener("keydown", handleKey);
+ if (event.key == "Escape") {
+ element.innerHTML = menu.controls[action];
+ return;
+ }
+ game.controls[action] = event.key;
+ localStorage.setItem("controls", JSON.stringify(game.controls));
+ element.innerHTML = event.key;
+ };
+ window.addEventListener("keydown", handleKey);
+ };
+
+ const setLevel = (index) => {
+ game.loadLevelIndex(index);
+ hide();
+ };
+
+ const draw = () => {
+ menuElement.style.display = "block";
+ menuElement.innerHTML = `<h1><span style='color: blue'>Big Blue</span> Is <span style='color: green'>You</h1>`;
+ if (state == "main") {
+ menuElement.innerHTML += `
+ <div class='menu-button' onclick='game.systems.menu.setState("controls")'>Change Controls</div>
+ <div class='menu-button' onclick='game.systems.menu.setState("credits")'>Credits</div>
+ <div class='menu-button' onclick='game.systems.menu.setState("levelSelect")'>Select Level</div>
+ `;
+ }
+ else if (state == "controls") {
+ menuElement.innerHTML += `
+ <div>
+ <p>
+ Move left: <button id="moveLeft" onfocus='game.systems.menu.listenFor("left", "moveLeft")'>${game.controls.left}</button>
+ <br>
+ Move right: <button id="moveRight" onfocus='game.systems.menu.listenFor("right", "moveRight")'>${game.controls.right}</button>
+ <br>
+ Move up: <button id="moveUp" onfocus='game.systems.menu.listenFor("up", "moveUp")'>${game.controls.up}</button>
+ <br>
+ Move down: <button id="moveDown" onfocus='game.systems.menu.listenFor("down", "moveDown")'>${game.controls.down}</button>
+ <br>
+ Undo: <button id="undo" onfocus='game.systems.menu.listenFor("undo", "undo")'>${game.controls.undo}</button>
+ <br>
+ Reset: <button id="reset" onfocus='game.systems.menu.listenFor("reset", "reset")'>${game.controls.reset}</button>
+ </p>
+ </div>
+ `;
+ } else if (state == "credits") {
+ menuElement.innerHTML += `
+ <div>
+ <p>
+ Sprites from Baba Is You, as hosted <a href="https://www.spriters-resource.com/pc_computer/babaisyou/sheet/115231/">here</a>, and a few custom ones.
+ <br>
+ Background is from <a href="https://i.pinimg.com/originals/b2/2a/a2/b22aa22b2f3f55b6468361158d52e2e7.gif">PinImg</a>.
+ <br>
+ Music is <a href="https://www.youtube.com/watch?v=yQjAF3frudY">Fluffing A Duck</a> by Kevin MacLeod.
+ <br>
+ Other sound effects generated on <a href="https://www.sfxr.me/">SFXR</a>.
+ <br>
+ Developed by Logan Hunt, Ethan Payne
+ </p>
+ </div>
+ `;
+ } else if (state == "levelSelect") {
+ menuElement.innerHTML += `
+ <div>
+ <p> Select a level to play: </p>
+ ${
+ game.levels.map((level, index) => {
+ return `<div class='menu-button' onclick='game.systems.menu.setLevel(${index});'>${level.levelName}</div>`;
+ }).join("")
+ }
+ `;
+ }
+ if (!game.win) {
+ menuElement.innerHTML += "<div class='menu-button' onclick='game.systems.menu.hide()'>Resume Game</div>";
+ }
+ if (state !== "main") {
+ menuElement.innerHTML += "<div class='menu-button' onclick='game.systems.menu.setState(\"main\")'>Back</div>";
+ }
+ };
+
+ return { bringUpMenu, setState, listenFor, hide, setLevel, state };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/particle.js b/Homework/cs5410/bbiy/src/systems/particle.js
new file mode 100644
index 0000000..56d8c47
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/particle.js
@@ -0,0 +1,57 @@
+game.system.Particle = () => {
+ "use strict";
+ const particleSpawners = {};
+
+ const particleSpawner = ({colors, maxAmount, minAmount, minLife, maxLife, minRadius, maxRadius, maxSpeed, spawnFunction}) => {
+ return Array(randomInRange(minAmount, maxAmount)).fill(0).map(() => {
+ let particleSpec = {
+ x: Math.random(),
+ y: Math.random(),
+ dx: Math.random() * maxSpeed - maxSpeed / 2,
+ dy: Math.random() * maxSpeed - maxSpeed / 2,
+ radius: randomInRange(minRadius, maxRadius),
+ color: colors[randomInRange(0, colors.length-1)],
+ lifetime: randomInRange(minLife, maxLife),
+ elapsed: 0,
+ };
+ if (spawnFunction) {
+ particleSpec = {...particleSpec, ...spawnFunction(particleSpec)};
+ }
+ return particleSpec;
+ });
+ };
+
+ const update = (elapsedTime, entities, _changedIds) => {
+ for (let id in entities) {
+ const entity = entities[id];
+ if (entity.hasComponent("particles")) {
+ if (!particleSpawners[entity.id]) {
+ particleSpawners[entity.id] = particleSpawner(entity.components.particles.spec.spec);
+ entities[id].particleSprite = game.graphics.Sprite({
+ drawFunction: (elapsedTime, {x, y, width, height}, context) => {
+ let particleSpawner = particleSpawners[entity.id];
+ particleSpawner.map((particleSpec) => particleSpec.elapsed += elapsedTime);
+ particleSpawners[id] = particleSpawner.filter((particleSpec) => particleSpec.lifetime > particleSpec.elapsed);
+ particleSpawner = particleSpawners[id];
+ if (particleSpawner.length === 0) {
+ entities[id].removeComponent("alive");
+ }
+ particleSpawner.map((particleSpec) => {
+ const position = {x: (particleSpec.x * width) + x + particleSpec.dx * particleSpec.elapsed, y: (particleSpec.y * height) + y + particleSpec.dy * particleSpec.elapsed};
+ const fill = context.fillStyle;
+ context.fillStyle = particleSpec.color;
+ context.beginPath();
+ context.arc(position.x, position.y, particleSpec.radius, 0, 2 * Math.PI);
+ context.fill();
+ context.fillStyle = fill;
+ });
+ }
+ });
+ }
+ }
+ }
+ return new Set();
+ };
+
+ return { update };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/physics.js b/Homework/cs5410/bbiy/src/systems/physics.js
new file mode 100644
index 0000000..18c3cb3
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/physics.js
@@ -0,0 +1,16 @@
+game.system.Physics = () => {
+ 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;
+ entity.components.position.y += dy * elapsedTime;
+ 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 };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/render.js b/Homework/cs5410/bbiy/src/systems/render.js
new file mode 100644
index 0000000..e0db7e3
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/render.js
@@ -0,0 +1,26 @@
+game.system.Render = (graphics) => {
+ const update = (elapsedTime, entities, _changedIds) => {
+ graphics.clear();
+
+ const entitiesArray = Object.keys(entities).map(key => entities[key]);
+ const sortedEntities = entitiesArray.sort((a, b) => {
+ const aprior = a.hasComponent("loadPriority") ? a.components.loadPriority.priority : 0;
+ const bprior = b.hasComponent("loadPriority") ? b.components.loadPriority.priority : 0;
+ return bprior - aprior;
+ });
+
+ sortedEntities.forEach((entity) => {
+ if (entity.hasComponent("position") && entity.hasComponent("appearance") && entity.hasComponent("alive")) {
+ const drawSpec = {...entity.components.position, ...entity.components.appearance};
+ if (entity.hasComponent("sprite")) {
+ game.sprites[entity.components.sprite.spriteName].draw(elapsedTime, drawSpec);
+ } else if (entity.hasComponent("particles") && entity.particleSprite) {
+ entity.particleSprite.draw(elapsedTime, drawSpec);
+ }
+ }
+ });
+
+ return new Set();
+ };
+ return { update };
+};
diff --git a/Homework/cs5410/bbiy/src/systems/system.js b/Homework/cs5410/bbiy/src/systems/system.js
new file mode 100644
index 0000000..f331401
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/system.js
@@ -0,0 +1 @@
+game.system = {}; \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/systems/undo.js b/Homework/cs5410/bbiy/src/systems/undo.js
new file mode 100644
index 0000000..086d6b4
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/systems/undo.js
@@ -0,0 +1,32 @@
+game.system.Undo = (entitiesGrid, logicSystem, gridSystem) => {
+ const states = [];
+
+ const update = (elapsedTime, entities, changedIds) => {
+ if (changedIds.size) {
+ 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) => {
+ let state = states.slice(0, -1).pop();
+ if (states.length > 1) {
+ states.pop();
+ }
+ for (let id in state) {
+ for (let componentName in state[id]) {
+ entities[id].addComponent({name: componentName, ...state[id][componentName]});
+ }
+ }
+ gridSystem.update(0, entities, new Set());
+ logicSystem.parseRules(entities);
+ };
+
+ return { update, undo };
+};
diff --git a/Homework/cs5410/bbiy/src/utils/clamp.js b/Homework/cs5410/bbiy/src/utils/clamp.js
new file mode 100644
index 0000000..b0da861
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/utils/clamp.js
@@ -0,0 +1,6 @@
+const clamp = (vector, maxX, maxY) => {
+ const newVector = {...vector};
+ newVector.x = Math.max(0, Math.min(maxX, vector.x));
+ newVector.y = Math.max(0, Math.min(maxY, vector.y));
+ return newVector;
+};
diff --git a/Homework/cs5410/bbiy/src/utils/loadLevel.js b/Homework/cs5410/bbiy/src/utils/loadLevel.js
new file mode 100644
index 0000000..3bd86d9
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/utils/loadLevel.js
@@ -0,0 +1,87 @@
+game.loadLevel = (level) => {
+ const entities = {};
+ const config = {...level.gridSize};
+ for (let y = 0; y < level.gridSize.yDim; y++) {
+ for (let x = 0; x < level.gridSize.xDim; x++) {
+ const cell = level.level[y][x];
+ cell.forEach((letter) => {
+ let entity;
+ switch (letter) {
+ case 'b':
+ entity = game.createBigBlue();
+ break;
+ case 'h':
+ entity = game.createHedge();
+ break;
+ case 'r':
+ entity = game.createRock();
+ break;
+ case 'f':
+ entity = game.createFlag();
+ break;
+ case 'g':
+ entity = game.createGrass();
+ break;
+ case 'l':
+ entity = game.createFloor();
+ break;
+ case 'w':
+ entity = game.createWall();
+ break;
+ case 'a':
+ entity = game.createWater();
+ break;
+ case 'A':
+ entity = game.createWordWater();
+ break;
+ case 'N':
+ entity = game.createWordSink();
+ break;
+ case 'V':
+ entity = game.createWordLava();
+ break;
+ case 'v':
+ entity = game.createLava();
+ break;
+ case 'K':
+ entity = game.createWordKill();
+ break;
+ case 'W':
+ entity = game.createWordWall();
+ break;
+ case 'I':
+ entity = game.createWordIs();
+ break;
+ case 'S':
+ entity = game.createWordStop();
+ break;
+ case 'R':
+ entity = game.createWordRock();
+ break;
+ case 'P':
+ entity = game.createWordPush();
+ break;
+ case 'B':
+ entity = game.createWordBigBlue();
+ break;
+ case 'Y':
+ entity = game.createWordYou();
+ break;
+ case 'F':
+ entity = game.createWordFlag();
+ break;
+ case 'X':
+ entity = game.createWordWin();
+ break;
+ default:
+ break;
+ }
+ if (entity) {
+ entity.addComponent(game.components.GridPosition({x, y}));
+ entities[entity.id] = entity;
+ }
+ });
+ }
+ }
+ return [entities, config];
+}; \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/utils/objectEquivalence.js b/Homework/cs5410/bbiy/src/utils/objectEquivalence.js
new file mode 100644
index 0000000..e33dd76
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/utils/objectEquivalence.js
@@ -0,0 +1,14 @@
+const equivalence = (obj1, obj2) => {
+ if (obj1 === null) {
+ return obj1 === null;
+ }
+ return Object.keys(obj1).every(key => {
+ if (obj2[key] === undefined) {
+ return false;
+ }
+ if (typeof obj1[key] === 'object') {
+ return equivalence(obj1[key], obj2[key]);
+ }
+ return obj1[key] === obj2[key];
+ });
+};
diff --git a/Homework/cs5410/bbiy/src/utils/randInRange.js b/Homework/cs5410/bbiy/src/utils/randInRange.js
new file mode 100644
index 0000000..528221a
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/utils/randInRange.js
@@ -0,0 +1,4 @@
+const randomInRange = (min, max) => {
+ // min <= random number <= max
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+} \ No newline at end of file
diff --git a/Homework/cs5410/bbiy/src/utils/unitizeVector.js b/Homework/cs5410/bbiy/src/utils/unitizeVector.js
new file mode 100644
index 0000000..6297ca8
--- /dev/null
+++ b/Homework/cs5410/bbiy/src/utils/unitizeVector.js
@@ -0,0 +1,11 @@
+const unitize = (vector) => {
+ // Not *technically* a unit vector, but has x,y components of |magnitude| = 1
+ Object.keys(vector).forEach((key) => {
+ if (typeof vector[key] === 'object') {
+ vector[key] = vector[key].unitize();
+ } else if (typeof vector[key] === 'number') {
+ vector[key] = (vector[key] === 0 ? 0 : vector[key] / Math.abs(vector[key]));
+ }
+ });
+ return vector;
+} \ No newline at end of file