Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ab2312983 | |||
| 4418fd3279 | |||
| 8e5b1ed77f | |||
| 90cf44906d | |||
| 37ca135c28 | |||
| edf3d840c0 |
8 changed files with 252 additions and 91 deletions
11
config.xml
11
config.xml
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget id="org.adrianvictor.impostor" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<widget id="org.adrianvictor.impostor" version="1.1.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<name>Impostor</name>
|
||||
<description>
|
||||
A game of word guessing where an impostor is trying to get along.
|
||||
A game of guessing where everyone but the impostor knows the word.
|
||||
</description>
|
||||
<author email="adrianvictor@disroot.org" href="https://adrianvic.github.io">
|
||||
Adrian Victor
|
||||
|
|
@ -17,11 +17,6 @@
|
|||
<icon src="res/icon/android/hdpi.png" density="hdpi" />
|
||||
<icon src="res/icon/android/mdpi.png" density="mdpi" />
|
||||
<icon src="res/icon/android/ldpi.png" density="ldpi" />
|
||||
<splash src="res/screen/android/splash-port-ldpi.png" density="port-ldpi" />
|
||||
<splash src="res/screen/android/splash-port-mdpi.png" density="port-mdpi" />
|
||||
<splash src="res/screen/android/splash-port-hdpi.png" density="port-hdpi" />
|
||||
<splash src="res/screen/android/splash-port-xhdpi.png" density="port-xhdpi" />
|
||||
<splash src="res/screen/android/splash-port-xxhdpi.png" density="port-xxhdpi" />
|
||||
<splash src="res/screen/android/splash-land-ldpi.png" density="land-ldpi" />
|
||||
<preference name="SplashScreen" value="none"/>
|
||||
</platform>
|
||||
</widget>
|
||||
1
docs
Symbolic link
1
docs
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
www
|
||||
24
package-lock.json
generated
24
package-lock.json
generated
|
|
@ -9,7 +9,9 @@
|
|||
"version": "1.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"cordova-android": "^15.0.0"
|
||||
"cordova-android": "^15.0.0",
|
||||
"cordova-android-stayawake": "github:rootzoll/cordova-android-stayawake",
|
||||
"cordova-plugin-vibration": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@netflix/nerror": {
|
||||
|
|
@ -190,6 +192,12 @@
|
|||
"node": ">=20.17.0 || >=22.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cordova-android-stayawake": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "git+ssh://git@github.com/rootzoll/cordova-android-stayawake.git#19e13d80ed9870b7e833de1ff3049ee477179491",
|
||||
"dev": true,
|
||||
"license": "Apache 2.0"
|
||||
},
|
||||
"node_modules/cordova-common": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-common/-/cordova-common-6.0.0.tgz",
|
||||
|
|
@ -209,6 +217,20 @@
|
|||
"node": ">=20.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cordova-plugin-vibration": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cordova-plugin-vibration/-/cordova-plugin-vibration-3.1.1.tgz",
|
||||
"integrity": "sha512-qgv67Rueo4Pydfant3TwnXeFiN9dl+6lKMM6h5jYg9XewiGAGOr8vfWsTvQssC3m3xMKGS1ap3xPNH+BzZ4RMA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"cordovaDependencies": {
|
||||
"4.0.0": {
|
||||
"cordova": ">100"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
|
|
|
|||
12
package.json
12
package.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.adrianvictor.impostor",
|
||||
"displayName": "Impostor",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "A game of word guessing where an impostor is trying to get along.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
|
@ -15,9 +15,15 @@
|
|||
"cordova": {
|
||||
"platforms": [
|
||||
"android"
|
||||
]
|
||||
],
|
||||
"plugins": {
|
||||
"cordova-plugin-vibration": {},
|
||||
"cordova-android-stayawake": {}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"cordova-android": "^15.0.0"
|
||||
"cordova-android": "^15.0.0",
|
||||
"cordova-android-stayawake": "github:rootzoll/cordova-android-stayawake",
|
||||
"cordova-plugin-vibration": "^3.1.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
res/colors.xml
Normal file
4
res/colors.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<color name="cdv_splashscreen_background">#000000</color>
|
||||
</resources>
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
<link rel="stylesheet" href="style.css">
|
||||
<script src="script.js" defer></script>
|
||||
<script type="text/javascript" src="cordova.js"></script>
|
||||
<script src="StayAwake.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
|
@ -15,6 +16,17 @@
|
|||
</header>
|
||||
|
||||
<div id="playlistHolder">
|
||||
<div id="hintCheckHolder" class="optionsHolder">
|
||||
<p>Dicas</p>
|
||||
<input type="checkbox" id="hintCheck" checked>
|
||||
</div>
|
||||
<div id="timerInputHolder" class="optionsHolder">
|
||||
<p>Temporizador (minutos)</p>
|
||||
<input type="number" max="" id="timerInput" value="3" >
|
||||
</div>
|
||||
|
||||
<div class="optionsHolder">
|
||||
<p>Jogadores</p>
|
||||
<div id="playersList">
|
||||
<div class="playerHolder">
|
||||
<input type="text" placeholder="Nome do primeiro jogador"/>
|
||||
|
|
@ -27,9 +39,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<button id="newPlayerButton">Adicionar jogador</button>
|
||||
<div id="hintCheckHolder">
|
||||
<p>Dicas</p>
|
||||
<input type="checkbox" id="hintCheck" checked>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -38,6 +47,7 @@
|
|||
</div>
|
||||
|
||||
<div id="bottomBar">
|
||||
<button id="changeTheme" onclick="changeTheme()">Mudar tema</button>
|
||||
<button id="startGame">Próximo</button>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@ const startButton = document.querySelector("#startGame");
|
|||
const logArea = document.querySelector("#gameLog");
|
||||
const body = document.querySelector("body");
|
||||
const hintCheckbox = document.querySelector("#hintCheck");
|
||||
const timerInput = document.getElementById("timerInput");
|
||||
|
||||
const isCordova = typeof cordova !== 'undefined';
|
||||
|
||||
const theme = localStorage.getItem('theme');
|
||||
|
||||
if (theme == "light") {
|
||||
body.classList.add("light-theme");
|
||||
}
|
||||
|
||||
let stage = 0;
|
||||
let currentPlayer = 0;
|
||||
|
|
@ -12,6 +21,7 @@ let allPlayers;
|
|||
let currentName;
|
||||
let secret;
|
||||
let enableHint;
|
||||
let timer;
|
||||
|
||||
nPlayerButton.addEventListener('click', () => {
|
||||
const holder = document.createElement("div");
|
||||
|
|
@ -66,18 +76,32 @@ startButton.addEventListener('click', () => {
|
|||
case -1:
|
||||
currentName = allPlayers[currentPlayer].value;
|
||||
clear(`
|
||||
<p>Entregue o dispositivo para:<br><span class="playerName">${currentName}</span><br>para continuar.</p>
|
||||
<p>Entregue o dispositivo para:<br><span class="playerName">${currentName}</span><br>para continuar</p>
|
||||
`);
|
||||
stage = 1;
|
||||
break;
|
||||
|
||||
case 2: {
|
||||
clear("O jogo começou! Cada um deve falar uma palavra relacionada ao tema.\nProssiga após a votação.");
|
||||
clear("O jogo começou! Cada um deve falar uma palavra relacionada ao tema.\n<p id='timer'>Prepare-se!</p>");
|
||||
startTimer(timerInput.value);
|
||||
stage += 1;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
if (isCordova && !!navigator.vibrate) {
|
||||
navigator.vibrate(0);
|
||||
}
|
||||
|
||||
if (isCordova && !!StayAwake.enableScreenTimeout) {
|
||||
StayAwake.enableScreenTimeout();
|
||||
}
|
||||
clearInterval(timer);
|
||||
clear("O jogo acabou! Votem para expulsar um jogador.")
|
||||
stage += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
case 4: {
|
||||
clear(`O impostor era <b>${impostor}</b>; a palavra era <b>${secret.word}</b>; a dica <b>${secret.hint}</b>.`);
|
||||
stage += 1;
|
||||
break;
|
||||
|
|
@ -89,29 +113,29 @@ startButton.addEventListener('click', () => {
|
|||
currentPlayer = 0;
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function choose() {
|
||||
function choose() {
|
||||
const randomIndex = Math.floor(Math.random() * allPlayers.length);
|
||||
return allPlayers[randomIndex].value;
|
||||
}
|
||||
}
|
||||
|
||||
function log(text) {
|
||||
function log(text) {
|
||||
logArea.innerHTML = logArea.innerHtml + "<br>" + text;
|
||||
}
|
||||
}
|
||||
|
||||
function clear(text) {
|
||||
function clear(text) {
|
||||
logArea.classList.forEach(item => {
|
||||
logArea.classList.remove(item);
|
||||
})
|
||||
logArea.innerHTML = text;
|
||||
}
|
||||
}
|
||||
|
||||
function logClass(className) {
|
||||
function logClass(className) {
|
||||
logArea.classList.toggle(className);
|
||||
}
|
||||
}
|
||||
|
||||
async function getWordWithHint() {
|
||||
async function getWordWithHint() {
|
||||
try {
|
||||
const response = await fetch('words.json');
|
||||
const data = await response.json();
|
||||
|
|
@ -125,4 +149,43 @@ async function getWordWithHint() {
|
|||
} catch (error) {
|
||||
console.error('Error loading words:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startTimer(minutes) {
|
||||
const now = new Date();
|
||||
const minutesLater = new Date(now.getTime() + minutes * 60 * 1000);
|
||||
timer = setInterval(() => {
|
||||
const timerElement = document.getElementById("timer");
|
||||
if (!timerElement) { return; }
|
||||
const rightNow = new Date().getTime();
|
||||
var distance = minutesLater.getTime() - rightNow;
|
||||
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||
timerElement.innerText = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (isCordova && !!StayAwake.disableScreenTimeout) {
|
||||
StayAwake.disableScreenTimeout();
|
||||
}
|
||||
|
||||
if (distance < 0) {
|
||||
clearInterval(timer);
|
||||
|
||||
if (!!navigator.vibrate) {
|
||||
navigator.vibrate([1000, 500, 1000, 2000, 1000, 500, 1000, 2000, 1000, 500, 1000, 2000]);
|
||||
}
|
||||
|
||||
if (isCordova && !!StayAwake.enableScreenTimeout) {
|
||||
StayAwake.enableScreenTimeout();
|
||||
}
|
||||
|
||||
timerElement.innerText = "Acabou!";
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
|
||||
function changeTheme(){
|
||||
body.classList.toggle('light-theme');
|
||||
console.log(body.classList.contains('light-theme') ? "light" : "dark")
|
||||
localStorage.setItem('theme', body.classList.contains('light-theme') ? "light" : "dark");
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
:root {
|
||||
--background: black;
|
||||
--backgroundLighter: rgb(20, 20, 20);
|
||||
--foreground: white;
|
||||
--saBORbackground: rgba(54, 54, 54, 0.5);
|
||||
--saBORforeground: darkgrey;
|
||||
|
|
@ -7,10 +8,24 @@
|
|||
--civilColor: rgb(0, 50, 0);
|
||||
}
|
||||
|
||||
.light-theme {
|
||||
--background: white;
|
||||
--backgroundLighter: rgb(230, 230, 230);
|
||||
--foreground: black;
|
||||
--saBORbackground: rgba(200, 200, 200, 0.5);
|
||||
--saBORforeground: darkgrey;
|
||||
--impostorColor: rgb(200, 120, 120);
|
||||
--civilColor: rgb(120, 200, 120);
|
||||
}
|
||||
|
||||
* {
|
||||
transition: .2s;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
scrollbar-color: var(--foreground) transparent;
|
||||
scrollbar-width: thin;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
@ -23,8 +38,11 @@ body {
|
|||
padding: 2em;
|
||||
gap: 1em;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
width: 30vw;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
header {
|
||||
|
|
@ -92,19 +110,21 @@ button {
|
|||
}
|
||||
|
||||
/* button:hover {
|
||||
background-color: var(--foreground);
|
||||
color: var(--background);
|
||||
background-color: var(--foreground);
|
||||
color: var(--background);
|
||||
} */
|
||||
|
||||
.playerHolder {
|
||||
margin-bottom: 1em;
|
||||
display: flex;
|
||||
gap: .6em;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
font-family: monospace;
|
||||
color: white;
|
||||
color: var(--foreground);
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -115,12 +135,11 @@ input:focus {
|
|||
|
||||
#newPlayerButton {
|
||||
width: 100%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#startGame {
|
||||
margin-top: auto;
|
||||
margin-left: auto;
|
||||
/* margin-top: auto;
|
||||
margin-left: auto; */
|
||||
}
|
||||
|
||||
#gameLog {
|
||||
|
|
@ -128,6 +147,7 @@ input:focus {
|
|||
margin: auto 0;
|
||||
text-align: center;
|
||||
transition: .4s;
|
||||
border-width: medium 0;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
|
|
@ -142,6 +162,17 @@ input:focus {
|
|||
background-color: var(--civilColor);
|
||||
}
|
||||
|
||||
#playlistHolder {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-right: 0.5em;
|
||||
padding: 1em .4em 0 .4em;
|
||||
background-color: var(--backgroundLighter);
|
||||
border-top: medium solid var(--saBORbackground);
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
body.game #playlistHolder {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -150,14 +181,20 @@ body.game #gameLog {
|
|||
display: unset;
|
||||
}
|
||||
|
||||
body.game header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#bottomBar {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
gap: .6em;
|
||||
flex-shrink: 0;
|
||||
margin-top: 0;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
#hintCheckHolder p {
|
||||
margin: auto 0 auto 0;
|
||||
margin: auto auto auto 0;
|
||||
}
|
||||
|
||||
#hintCheckHolder {
|
||||
|
|
@ -165,11 +202,34 @@ body.game #gameLog {
|
|||
gap: .4em;
|
||||
}
|
||||
|
||||
#timerInput {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.optionsHolder {
|
||||
border-bottom: medium solid var(--saBORbackground);
|
||||
margin-bottom: 1em;
|
||||
border-radius: 5px;
|
||||
padding: 0 .8em 1em;
|
||||
|
||||
p {
|
||||
margin-bottom: .4em;
|
||||
}
|
||||
}
|
||||
|
||||
.optionsHolder:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.playerName {
|
||||
font-size: x-large;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
#timer {
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
.rainbowText {
|
||||
background: linear-gradient(to right, var(--foreground), var(--background), var(--foreground), var(--impostorColor), var(--foreground), var(--civilColor)); -webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
|
|
@ -197,6 +257,6 @@ body.game #gameLog {
|
|||
|
||||
@media (max-width: 720px) {
|
||||
body {
|
||||
width: 96vw;
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue