diff --git a/src/Player.js b/src/Player.js
index d78b635..e6f1526 100644
--- a/src/Player.js
+++ b/src/Player.js
@@ -3,8 +3,9 @@ import skull from 'data-url:./assets/img/skull.png';
import { getPointer, Sprite, on } from 'kontra';
import { PlayerControls } from './PlayerControls';
import { fgc2 } from './constants';
-import { ARCADIAN_ADDED, CUT_ROPE, GOAL_COLLISION } from './gameEvents';
+import { ARCADIAN_HEAD_SELECTED, CUT_ROPE, GOAL_COLLISION } from './gameEvents';
import { Rope } from './Rope';
+import { getSelectedArcadian } from './store';
export class Player {
game;
@@ -26,6 +27,8 @@ export class Player {
const startY = levelData.p.y;
this.createRope({ startX, startY, ropeLength });
this.createSprite();
+ this.headImg = getSelectedArcadian().img;
+ this.createHeadSprite(this.headImg);
this.playerControls = new PlayerControls(this);
this.listenForGameEvents();
}
@@ -60,6 +63,7 @@ export class Player {
};
}
createHeadSprite(img) {
+ if (!img) return;
const scale = this.scale / 2;
let scaleX = scale;
if (this.isLeft) scaleX = scaleX * -1;
@@ -167,7 +171,7 @@ export class Player {
listenForGameEvents() {
on(GOAL_COLLISION, this.onGoalCollision);
- on(ARCADIAN_ADDED, this.onArcadianAdded);
+ on(ARCADIAN_HEAD_SELECTED, this.onArcadianAdded);
on(CUT_ROPE, this.onCutRope);
}
onGoalCollision = () => {
diff --git a/src/arcadianApi.js b/src/arcadianApi.js
index 7b86baf..f861ce8 100644
--- a/src/arcadianApi.js
+++ b/src/arcadianApi.js
@@ -1,4 +1,6 @@
-export const arcadianHeadImages = [];
+import { emit } from 'kontra';
+import { ARCADIAN_ADDED, ARCADIAN_HEAD_SELECTED } from './gameEvents';
+import { setArcadianData } from './store';
export async function queryArcadian(id) {
const partsUrl =
@@ -29,9 +31,9 @@ export async function queryArcadian(id) {
img.addEventListener(
'load',
() => {
- localStorage.setItem('Arcadian #' + id, xhr.response);
- arcadianHeadImages.push(img);
- resolve(img);
+ localStorage.setItem('Arcadian #' + id, img);
+ setArcadianData({ id, data, img });
+ resolve({ id, data, img });
},
false
);
@@ -41,3 +43,17 @@ export async function queryArcadian(id) {
xhr.send();
});
}
+
+export const fetchArcadianHeads = () => {
+ return new Promise((resolve) => {
+ const promises = [];
+ for (let i = 1; i < 6; i++) {
+ const promise = queryArcadian(i);
+ promises.push(promise);
+ }
+ Promise.allSettled(promises).then((res) => {
+ emit(ARCADIAN_HEAD_SELECTED, { img: res[0].value });
+ resolve(res);
+ });
+ });
+};
diff --git a/src/gameEvents.js b/src/gameEvents.js
index beb7c3e..4901b4a 100644
--- a/src/gameEvents.js
+++ b/src/gameEvents.js
@@ -5,3 +5,4 @@ export const HEART_PICKUP = 'hp';
export const CUT_ROPE = 'cr';
export const START_LEVEL = 'sl';
export const RESTART_LEVEL = 'r';
+export const ARCADIAN_HEAD_SELECTED = 'ahs';
diff --git a/src/index.html b/src/index.html
index fc2831b..19b698e 100644
--- a/src/index.html
+++ b/src/index.html
@@ -19,6 +19,7 @@
+
diff --git a/src/index.js b/src/index.js
index 41f4b13..5785f60 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,8 +3,6 @@ import { emit } from 'kontra';
import cssText from 'bundle-text:./styles.css';
import { Game } from './Game';
-import { ARCADIAN_ADDED } from './gameEvents';
-import { queryArcadian } from './arcadianApi';
import { initLoginLogout } from './near/nearLogin';
import { NearConnection } from './near/nearConnection';
import { initMenu } from './menu';
@@ -46,14 +44,4 @@ const loadNearApi = () => {
});
};
-const fetchArcadianHeads = () => {
- // TODO (johnedvard) get from localStorage so we don't call the api too much
- // get many headpices
- for (let i = 0; i < 60; i += 5)
- queryArcadian(i).then((img) => {
- if (img) {
- emit(ARCADIAN_ADDED, { img });
- }
- });
-};
init();
diff --git a/src/menu.js b/src/menu.js
index 8d5a84d..e05f69a 100644
--- a/src/menu.js
+++ b/src/menu.js
@@ -1,6 +1,11 @@
+import { emit, Sprite } from 'kontra';
+
import closeIcon from 'data-url:./assets/img/close icon.svg';
-import { emit } from 'kontra';
-import { START_LEVEL } from './gameEvents';
+import skull from 'data-url:./assets/img/skull.png';
+
+import { ARCADIAN_HEAD_SELECTED, START_LEVEL } from './gameEvents';
+import { arcadianHeadImages, fetchArcadianHeads } from './arcadianApi';
+import { setSelectedArcadian } from './store';
const overlayIds = ['main', 'bonus', 'levels'];
const levels = 20;
@@ -20,7 +25,34 @@ const initLevels = () => {
levelsGridEl.appendChild(levelEl);
}
};
-const initBonusContent = () => {};
+const initBonusContent = () => {
+ const bonusGridEl = document.getElementById('bonus-grid');
+ const skullImg = new Image();
+ skullImg.src = skull;
+ fetchArcadianHeads().then((res) => {
+ for (let i = 0; i < res.length; i++) {
+ const img = res[i].value.img;
+ const bonusEl = document.createElement('canvas');
+ bonusEl.setAttribute('height', img.height * 4);
+ bonusEl.setAttribute('width', img.width * 4);
+ bonusEl.classList.add('bonus-item');
+ bonusEl.setAttribute('arcadian', res[i].value.id);
+ const ctx = bonusEl.getContext('2d');
+ ctx.imageSmoothingEnabled = false;
+ ctx.scale(8, 8);
+ ctx.drawImage(skullImg, img.width / 4 - 4, img.height / 4 - 12);
+ ctx.scale(1 / 2, 1 / 2);
+ ctx.drawImage(img, 0, 0);
+ bonusGridEl.appendChild(bonusEl);
+ }
+ });
+ bonusGridEl.addEventListener('click', (e) => {
+ if (e.target.classList.contains('bonus-item')) {
+ setSelectedArcadian(e.target.getAttribute('arcadian'));
+ showOverlay('main');
+ }
+ });
+};
const addButtonListeners = () => {
const containerEl = document.getElementById('container');
diff --git a/src/store.js b/src/store.js
index 6a4e7d0..22f23fa 100644
--- a/src/store.js
+++ b/src/store.js
@@ -1,8 +1,28 @@
+import { emit } from 'kontra';
+import { ARCADIAN_HEAD_SELECTED } from './gameEvents';
+
export let gameWidth = 0;
export let gameHeight = 0;
+const arcadianData = {};
+let selectedArcadian = {};
+
export const setGameWidth = (width) => {
gameWidth = width;
};
+
export const setGameHeight = (height) => {
gameHeight = height;
};
+
+export const setArcadianData = ({ id, data, img }) => {
+ arcadianData[id] = { data, img };
+};
+
+export const setSelectedArcadian = (id) => {
+ selectedArcadian = arcadianData[id];
+ emit(ARCADIAN_HEAD_SELECTED, { img: selectedArcadian.img });
+};
+
+export const getSelectedArcadian = () => {
+ return selectedArcadian;
+};
diff --git a/src/styles.css b/src/styles.css
index 6884e86..2a3a21f 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -116,9 +116,24 @@ button:disabled {
display: grid;
justify-items: center;
}
-#levels-grid::-webkit-scrollbar {
+#levels-grid::-webkit-scrollbar,
+#bonus-grid::-webkit-scrollbar {
display: none;
}
+.bonus-item {
+ cursor: pointer;
+ background: none;
+ border-radius: 4px;
+}
+.bonus-item:hover {
+ box-shadow: inset 0px 0px 100px -50px var(--acc);
+}
+#bonus-grid {
+}
+#bonus-grid > canvas {
+ width: 200px;
+ height: 200px;
+}
.hide {
display: none !important; /* XXX Override any other display settings on the element */
}