Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 90 additions & 9 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
<script src="js/joystick-levitation.js"></script>
<script src="js/raycaster-listen.js"></script>
<script src="js/spawn-in-circle.component.js"></script>
<script src="js/overlay.component.js"></script>
<script src="js/teleport-controller.js"></script>
<script src="js/hud.js"></script>
<script src="js/bookkeeping.js"></script>
<script src="js/speech-recognition.js"></script>
<script src="js/grabbing.js"></script>
Expand Down Expand Up @@ -214,17 +216,96 @@
</a-entity>
</a-entity>

<div id="wordchooser" class="hidden">
<button type="button" class="button"></button>
<button type="button" class="button"></button>
<button type="button" class="button"></button>
</div>
<template id="right-hand-template">
<a-entity>
<a-gltf-model class="tracked-right-hand" rotation="0 0 -90" src="#right-hand-model"></a-gltf-model>
</a-entity>
</template>

</a-assets>

<a-entity position="0 10 -3" scale="10 10 10">
<a-entity
id="word-to-guess"
geometry="primitive: plane; height: 0.02; width: 0.1"
position="0 0 -1"
scale="10 10 1"
text="value: ; font: sourcecodepro;"
material="color: blue; opacity: 0.0; side: double">
</a-entity>
<a-entity
id="game-state"
geometry="primitive: plane; height: 0.02; width: 0.1"
position="1 0 -1"
scale="10 10 1"
text="value: waiting for players to join . . .; font: sourcecodepro;"
material="color: yellow; opacity: 0.5; side: double">
</a-entity>
<a-entity
id="room-code"
geometry="primitive: plane; height: 0.02; width: 0.1"
position="1 -0.2 -1"
scale="10 10 1"
text="value: ; font: sourcecodepro;"
material="color: blue; opacity: 0.5; side: double">
</a-entity>

<a-entity id="wordchooser" position=".7 -0.4 -1">
<a-entity
geometry="primitive: plane; height: 0.02; width: 0.02"
position="0 0 0"
scale="10 10 1"
text="value: ; wrapCount: 10; align: center; font: sourcecodepro;"
material="color: orange; opacity: 0.0; side: double">
</a-entity>
<a-entity
geometry="primitive: plane; height: 0.02; width: 0.02"
position="0.3 0 0"
scale="10 10 1"
text="value: ; wrapCount: 10; align: center; font: sourcecodepro;"
material="color: orange; opacity: 0.0; side: double">
</a-entity>
<a-entity
geometry="primitive: plane; height: 0.02; width: 0.02"
position="0.6 0 0"
scale="10 10 1"
text="value: ; wrapCount: 10; align: center; font: sourcecodepro;"
material="color: orange; opacity: 0.0; side: double">
</a-entity>
</a-entity>
</a-entity>

<a-entity id="camera-rig"
tracked-vr-hands
joystick-levitation
spawn-in-circle="radius:3"
networked="template:#camera-rig-template;"
>
<a-entity id="local-avatar" camera position="0 1.6 0" look-controls wasd-controls
networked="template:#head-template;attachTemplateToLocal:false;">
<a-entity visible="true" id="hud-goes-here">
<a-box color="green" depth="1" height="1" width="1" position="0 1 -5"></a-box>
</a-entity>

</a-entity>
<!-- <a-entity cursor="fuse: true; fuseTimeout: 500" laser-controls></a-entity> -->
</a-entity>

<template id="cursor-template">
<!-- <a-entity cursor="fuse: true; fuseTimeout: 500; max-distance: 30000000; rayOrigin: mouse;"
position="0 0 -5"
laser-controls
overlay
geometry="primitive: ring";
material="color: blue; shader: flat">
</a-entity> -->
</template>

<div id="worddisplay"></div>

<a-entity light="color: #ccccff; intensity: 0.2; type: ambient;" visible=""></a-entity>
<a-entity light="color: #ffaaff; intensity: 0.3" position="5 5 5"></a-entity>
</a-scene>
<!-- <a-entity id="refresh-button" geometry="primitive: plane; height: 1; width:1" material="color: red; side: double" position="0 10 -2" scale="2 2 2"></a> -->
<a-entity light="color: #ccccff; intensity: 0.2; type: ambient;" visible=""></a-entity>
<a-entity light="color: #ffaaff; intensity: 0.3" position="5 5 5"></a-entity>
</a-scene>

<div class="actions">
<button id="mic-btn" type="button" class="button">Mute Mic</button>
Expand Down
91 changes: 69 additions & 22 deletions static/js/bookkeeping.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ Object.freeze(DataChannel);

const wordChooserBS = new rxjs.BehaviorSubject(null);
const wordDisplayBS = new rxjs.BehaviorSubject("");
const clickingEnabled = new rxjs.BehaviorSubject(false);

clickingEnabled.subscribe({
next: (isEnabled) => {
// console.log("clicking enabled: ", isEnabled);
// const existingControls = document.querySelectorAll("#camera-rig > a-entity[laser-controls]");
// if (isEnabled && existingControls.length == 0) {
// const template = document.querySelector("#cursor-template");
// const el = template.content.cloneNode(true);
// document.querySelector("#camera-rig").appendChild(el);
// } else if (!isEnabled) {
// existingControls.forEach(el => el.parentNode.removeChild(el));
// }
},
});

const setBookkeeping = (newValue) => {
// FIXME: makes it difficult to change the host in the middle of the game
Expand All @@ -68,19 +83,26 @@ const setBookkeeping = (newValue) => {

updateState();

let describeGameState;
showHudItemById(
"room-code",
`room code is: ${roomCode}${bookkeeping.amITheHost ? " (we are hosting)" : ""}`
);

let roundDesc = `round ${bookkeeping.currentRoundNumber + 1}/${bookkeeping.totalNumberOfRounds} -- `;
let describeGameState = "";
switch (bookkeeping.gameState) {
case GameState.STARTING:
roundDesc = "";
describeGameState = "waiting for players to join . . .";
break;
case GameState.FINISHED:
roundDesc = "";
describeGameState = "game over!";
break;
case GameState.STARTING:
describeGameState = "starting";
break;
case GameState.BREAK:
describeGameState = "intermission";
break;
case GameState.PLAYING:
describeGameState = `round ${bookkeeping.currentRoundNumber}/${bookkeeping.totalNumberOfRounds} --`;
switch (bookkeeping.turnState) {
case TurnState.CHOOSING:
describeGameState += "choosing word";
Expand All @@ -90,14 +112,12 @@ const setBookkeeping = (newValue) => {
break;
}
}
let el = document.querySelector("#am-i-the-host");
if (el) {
el.innerHTML = ` ${bookkeeping.amITheHost ? "(host!)" : ""} -- timer remaining: ${
bookkeeping.timeRemaining
} (${describeGameState}) ${
bookkeeping.turnOrder[bookkeeping.currentPlayerInTurn] === ourNetworkId ? "we are up!" : ""
}`;

let timer = "";
if (roundDesc) {
timer = "\n" + `${bookkeeping.timeRemaining} seconds remaining`;
}
showHudItemById("game-state", roundDesc + describeGameState + timer);
};

const updateState = () => {
Expand Down Expand Up @@ -142,7 +162,7 @@ window.addEventListener("load", () => {
document.body.addEventListener("connected", function (evt) {
ourNetworkId = evt.detail.clientId;
bookkeeping.turnOrder.unshift(ourNetworkId);
document.querySelector("#whoami").innerHTML = ourNetworkId;
// document.querySelector("#whoami").innerHTML = ourNetworkId;
});

document.body.addEventListener("clientConnected", function (evt) {
Expand All @@ -161,20 +181,46 @@ window.addEventListener("load", () => {
next: (v) => {
console.log("word chooser bs subscriber -- ", v);
if (!v) {
document.querySelector("#wordchooser").classList.add("hidden");
document.querySelectorAll("#wordchooser > a-entity").forEach(hideHudItemByEl);
clickingEnabled.next(false);
} else {
console.log("yuh");
document.querySelector("#wordchooser").classList.remove("hidden");
document.querySelectorAll("#wordchooser > button").forEach((el, idx) => {
el.innerHTML = bookkeeping.availableWords[idx];
el.onclick = () => chooseAWord(bookkeeping.availableWords[idx]);
clickingEnabled.next(true);
document.querySelectorAll("#wordchooser > a-entity").forEach((el, idx) => {
showHudItemByEl(el, bookkeeping.availableWords[idx]);
el.addEventListener("click", () => chooseAWord(bookkeeping.availableWords[idx]));
wordDisplayBS.next("clicked!");
});
}
},
});

wordDisplayBS.subscribe({
next: (txt) => (document.querySelector("#worddisplay").innerHTML = txt),
next: (txt) => {
if (txt) {
if (txt != bookkeeping.obscuredWord) {
showHudItemById("word-to-guess", `please draw: ${txt}`);
} else if (bookkeeping.gameState == GameState.BREAK) {
showHudItemById("word-to-guess", `word was: ${txt}`);
} else {
showHudItemById("word-to-guess", `word is: ${txt}`);
}
} else {
hideHudItemById("word-to-guess");
}
},
});

document.querySelectorAll("#wordchooser > a-entity").forEach((el) => {
el.addEventListener("click", (event) => {
chooseAWord(el.getAttribute("text").value);
});

el.addEventListener("mouseover", (event) => {
el.setAttribute("material", "color", "red");
});
el.addEventListener("mouseleave", (event) => {
el.setAttribute("material", "color", "orange");
});
});
});

Expand Down Expand Up @@ -294,10 +340,11 @@ const rungame = async () => {
// )
// );

// // now we have chosen a word
// console.log("the chosen word was ", chosenWord);
const chosenWord = choosableWords[0];

// now we have chosen a word
console.log("the chosen word was ", chosenWord);

//// PHASE 2: Guessing ////
bookkeeping.currentWord = chosenWord;
bookkeeping.timeRemaining = DRAWING_TIME;
Expand Down
19 changes: 19 additions & 0 deletions static/js/hud.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const hideHudItemById = (itemId) => {
const el = document.getElementById(itemId);
hideHudItemByEl(el);
};

const hideHudItemByEl = (el) => {
el.setAttribute("material", "opacity", "0.0");
el.setAttribute("text", "value", "");
};

const showHudItemById = (itemId, text, opacity = 0.5) => {
const el = document.getElementById(itemId);
showHudItemByEl(el, text, opacity);
};

const showHudItemByEl = (el, text, opacity = 0.5) => {
el.setAttribute("material", "opacity", `${opacity}`);
el.setAttribute("text", "value", text);
};
8 changes: 8 additions & 0 deletions static/js/overlay.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
AFRAME.registerComponent("overlay", {
dependencies: ["material"],
init: function () {
this.el.sceneEl.renderer.sortObjects = true;
this.el.object3D.renderOrder = 100;
this.el.components.material.material.depthTest = false;
},
});