Better visuals, add timer, add vibration on mobile, add light theme.

This commit is contained in:
天クマ 2026-04-30 17:25:14 -03:00
commit 37ca135c28
7 changed files with 243 additions and 88 deletions

View file

@ -7,30 +7,39 @@
<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>
<img src="logo.png">
<h1 class="rainbowText">Impostor</h1>
</header>
<div id="playlistHolder">
<div id="playersList">
<div class="playerHolder">
<input type="text" placeholder="Nome do primeiro jogador"/>
</div>
<div class="playerHolder">
<input type="text" placeholder="Nome do segundo jogador"/>
</div>
<div class="playerHolder">
<input type="text" placeholder="Nome do terceiro jogador"/>
</div>
</div>
<button id="newPlayerButton">Adicionar jogador</button>
<div id="hintCheckHolder">
<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"/>
</div>
<div class="playerHolder">
<input type="text" placeholder="Nome do segundo jogador"/>
</div>
<div class="playerHolder">
<input type="text" placeholder="Nome do terceiro jogador"/>
</div>
</div>
<button id="newPlayerButton">Adicionar jogador</button>
</div>
</div>
<div name="gameLog" id="gameLog">
@ -38,6 +47,7 @@
</div>
<div id="bottomBar">
<button id="changeTheme" onclick="changeTheme()">Mudar tema</button>
<button id="startGame">Próximo</button>
</div>
</body>

View file

@ -4,6 +4,13 @@ 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 theme = localStorage.getItem('theme');
if (theme == "light") {
body.classList.add("light-theme");
}
let stage = 0;
let currentPlayer = 0;
@ -12,6 +19,7 @@ let allPlayers;
let currentName;
let secret;
let enableHint;
let timer;
nPlayerButton.addEventListener('click', () => {
const holder = document.createElement("div");
@ -66,63 +74,113 @@ 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>
`);
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.");
stage += 1;
<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.\n<p id='timer'>Prepare-se!</p>");
startTimer(timerInput.value);
stage += 1;
break;
}
case 3: {
if (!!navigator.vibrate) {
navigator.vibrate(0);
}
if (!!StayAwake.enableScreenTimeout) {
StayAwake.enableScreenTimeout();
}
clearInterval(timer);
clear("O jogo acabou! Votem para expulsar um jogador.")
stage += 1;
break;
}
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;
}
default:
body.classList.remove("game");
stage = 0;
currentPlayer = 0;
break;
}
case 3: {
clear(`O impostor era <b>${impostor}</b>; a palavra era <b>${secret.word}</b>; a dica <b>${secret.hint}</b>.`);
stage += 1;
break;
});
function choose() {
const randomIndex = Math.floor(Math.random() * allPlayers.length);
return allPlayers[randomIndex].value;
}
function log(text) {
logArea.innerHTML = logArea.innerHtml + "<br>" + text;
}
function clear(text) {
logArea.classList.forEach(item => {
logArea.classList.remove(item);
})
logArea.innerHTML = text;
}
function logClass(className) {
logArea.classList.toggle(className);
}
async function getWordWithHint() {
try {
const response = await fetch('words.json');
const data = await response.json();
const randomWordObj = data[Math.floor(Math.random() * data.length)];
const randomHint = randomWordObj.hints[Math.floor(Math.random() * randomWordObj.hints.length)];
return {
word: randomWordObj.word,
hint: randomHint
};
} catch (error) {
console.error('Error loading words:', error);
}
default:
body.classList.remove("game");
stage = 0;
currentPlayer = 0;
break;
}
});
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 (!!StayAwake.disableScreenTimeout) {
StayAwake.disableScreenTimeout();
}
if (distance < 0) {
clearInterval(timer);
function choose() {
const randomIndex = Math.floor(Math.random() * allPlayers.length);
return allPlayers[randomIndex].value;
}
if (!!navigator.vibrate) {
navigator.vibrate([1000, 500, 1000, 2000, 1000, 500, 1000, 2000, 1000, 500, 1000, 2000]);
}
function log(text) {
logArea.innerHTML = logArea.innerHtml + "<br>" + text;
}
if (!!StayAwake.enableScreenTimeout) {
StayAwake.enableScreenTimeout();
}
function clear(text) {
logArea.classList.forEach(item => {
logArea.classList.remove(item);
})
logArea.innerHTML = text;
}
function logClass(className) {
logArea.classList.toggle(className);
}
async function getWordWithHint() {
try {
const response = await fetch('words.json');
const data = await response.json();
const randomWordObj = data[Math.floor(Math.random() * data.length)];
const randomHint = randomWordObj.hints[Math.floor(Math.random() * randomWordObj.hints.length)];
return {
word: randomWordObj.word,
hint: randomHint
};
} catch (error) {
console.error('Error loading words:', error);
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");
}

View file

@ -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;
}
}