Rafael Tavares Juliani 1b93182afd INÍCIO
2025-09-04 15:42:21 -03:00

576 lines
13 KiB
HTML
Executable File

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jogo VR Rolimã do livro "Jean: entre jogos e brincadeiras"</title>
<meta name="description" content="">
<script src="aframe.0.8.2.min.js"></script>
<script src="aframe-aabb-collider-component.min.js"></script>
<script>
var RotY;
var RotZ;
AFRAME.registerComponent('rotation-reader', {
tick: function () {
RotZ = this.el.object3D.rotation.y;
RotY = this.el.object3D.rotation.z;
}
});
</script>
</head>
<body>
<a-scene>
<a-assets>
<img id="sky" src="fundo.jpg">
<a-asset-item id="cidade" src="cidade.glb"></a-asset-item>
<!-- A Cidade
"CCity Building Set 1" (https://skfb.ly/LpSC) by Neberkenezer is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
Alterações foram feitas
-->
<a-asset-item id="carrinho" src="carrinho.glb"></a-asset-item>
<a-asset-item id="cone" src="cone.glb"></a-asset-item>
<!--
Cone
"Orange street cone" (https://skfb.ly/6RUHP) by Mateusz Woliński is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
Alterações foram feitas
-->
<audio id="rolima" src="429104__inspectorj__marble-rolling-on-wood-alt.mp3" ></audio>
<!-- Som Rolimã
Usuário InspectorJ do freesound.org
Marble, Rolling on Wood, A.wav
https://freesound.org/people/InspectorJ/sounds/429104/
licença: https://creativecommons.org/licenses/by/3.0/
Foram realizadas alterações no arquivo
-->
<audio id="cont" src="528730__alexhanj__ping_alt.mp3" ></audio>
<!-- Som contagem
Usuário Alexhanj do freesound.org
Ping.aiff
https://freesound.org/people/Alexhanj/sounds/528730/
licença: https://creativecommons.org/publicdomain/zero/1.0/
-->
<audio id="vai" src="403005__inspectorj__ui-confirmation-alert-a4_alt.mp3" ></audio>
<!-- Som do vai
Usuário InspectorJ do freesound.org
UI Confirmation Alert, A4.wav
https://freesound.org/people/InspectorJ/sounds/403005/
licença: https://creativecommons.org/licenses/by/3.0/
-->
<audio id="sucesso" src="60443__jobro__tada1.mp3" ></audio>
<!-- Som de sucesso, conclusão
Usuário jobro do freesound.org
Success!! » tada1.wav
https://freesound.org/people/jobro/sounds/60443/
licença: https://creativecommons.org/licenses/by/3.0/
Foi feita uma pequena alteração
-->
<audio id="batida" src="456319__cupido-1__hit-ball.mp3" ></audio>
<!-- Som batida no cone
Usuário cupido-1 do freesound.org
hit ball.WAV
https://freesound.org/people/cupido-1/sounds/456319/
licença: https://creativecommons.org/publicdomain/zero/1.0/
Alterações foram feitas
-->
<audio id="falhou" src="563850__nikplaymostories__fail-trombone-wah-wah-wah-sound-effect.mp3" ></audio>
<!-- Som de game over - você falhou
Usuário NikPlaymostories do freesound.org
Fail (Trombone wah, wah, wah…) - Sound Effect.mp3
https://freesound.org/people/NikPlaymostories/sounds/563850/
licença: https://creativecommons.org/publicdomain/zero/1.0/
Alterações foram feitas
-->
</a-assets>
<a-sky src="#sky"></a-sky>
<a-entity id="roll" sound="src: #rolima; volume: 3"></a-entity>
<a-entity id="contSom" sound="src: #cont"></a-entity>
<a-entity id="vaiSom" sound="src: #vai"></a-entity>
<a-entity id="batidaSom" sound="src: #batida; volume:5"></a-entity>
<a-entity id="gameOverSom" sound="src: #falhou; volume:5"></a-entity>
<a-entity id="sucessoSom" sound="src: #sucesso; volume:25"></a-entity>
<a-entity id="camera" camera="active: true;" position="0 13.2 5"> <!-- Necessário para posicionar a camera -->
<a-entity rotation-reader camera="active: true" look-controls position="0 0 0" rotation="0 0 0">
<a-text id="contagem" visible="false" value="3" position="0 0.1 -0.4" width="3" color="#FFFFFF" align="center"></a-text>
<a-text id="instrucao" value="Desvie dos cones. Clique no desenho do canto inferior direito para iniciar." position="0 0.05 -0.2" width="0.5" color="#FFFFFF" align="center"></a-text>
<a-text id="textoFinal" visible="false" value="Isso! Vamos complicar um pouco? Aguarde a contagem novamente." position="0 0.05 -0.2" width="0.5" color="#FFFFFF" align="center"></a-text>
<a-text id="gameOver" visible="false" value="Que pena... Tente outra vez! Aguarde..." position="0 0.05 -0.2" width="0.5" color="#FFFFFF" align="center"></a-text>
</a-entity>
</a-entity>
<a-entity gltf-model="#cidade" position="22.5 0 -180" rotation="0 90 0"></a-entity>
<a-entity id="player" class="player" gltf-model="#carrinho" position="0 13 5" rotation="-4 0 0"></a-entity>
</a-scene>
<script>
var cam = document.querySelector('#camera');
var player = document.querySelector('#player');
var textoFinal = document.querySelector('#textoFinal');
var contagem = document.querySelector('#contagem');
let play;
var Px;
var Py;
let roll = document.querySelector('#roll');
let contSom = document.querySelector('#contSom');
let vaiSom = document.querySelector('#vaiSom');
let batidaSom = document.querySelector('#batidaSom');
let sucessoSom = document.querySelector('#sucessoSom');
let gameOverSom = document.querySelector('#gameOverSom');
let k = 0.1; //velocidade
var fase = 1;
function contarElArr(arr, el) {
return arr.filter(item => item == el).length;
}
function finalizarJogo(e) {
player.removeEventListener('hitstart', finalizarJogo);
var obj = e.detail.id;
cancelAnimationFrame(play);
roll.components.sound.stopSound();
batidaSom.components.sound.playSound();
setTimeout(() => {
gameOverSom.components.sound.playSound();
batidaSom.components.sound.stopSound();
}, 500);
gameOver.setAttribute('visible', true);
setTimeout(() => {
gameOverSom.components.sound.stopSound();
gameOver.setAttribute('visible', false);
voltarPosicaoInicial(0);
}, 3000);
console.log("Objeto colidido: "+obj);
}
function sortearObstaculos() {
let val = 12 - fase;
let qtde = parseInt(val,10)-1;
let posicoes = [0,15,30,45,60,75,90,105,120,135,150,165,180,195];
let sorteados = [];
for (i=0;i<qtde;i++){
let status = false;
let sorteado = Math.floor(Math.random()*(posicoes.length-1)); // sorteia números de 0 até a quantidade de posições menos um.
let rep = contarElArr(sorteados,posicoes[sorteado]);
if ( rep >= 2){
posicoes.splice(sorteado, 1);
sorteado = Math.floor(Math.random()*(posicoes.length-1)); // sorteia números de 0 até a quantidade de posições menos um.
sorteados.push(posicoes[sorteado]);
status = true;
} else {
sorteados.push(posicoes[sorteado]);
status = true;
}
if (status){
let sorteadoECD = Math.floor((Math.random()*3)+1); //sorteia 1, 2 ou 3. "1" esquerda, "2", centro e "3", direita.
let id = sorteado.toString();
let posX;
if(sorteadoECD == 1){
posX = -2.1;
} else if(sorteadoECD == 2){
posX = 0;
} else {
posX = 2.1;
}
let el = document.createElement('a-entity');
el.setAttribute('gltf-model','#cone');
let sceneEl = document.querySelector('a-scene');
sceneEl.appendChild(el);
el.id = id;
el.object3D.position.x = posX;
el.object3D.position.z = -10 - sorteados[i]; // -10 para o primeiro obstáculo não ficar muito em cima no início
el.object3D.position.y = (10 + sorteados[i])*(-0.0699) + 12.65;
el.setAttribute('aabb-collider','objects: .player; collideNonVisible: true');
}//fecha if do status
}// fecha for
}// fecha a funcao sortearObstaculos
function checarFim() {
if(this.player.object3D.position.z <= -210){
cancelAnimationFrame(play);
sucessoSom.components.sound.playSound();
roll.components.sound.stopSound();
if (fase == 1){
textoFinal.setAttribute('visible', true);
setTimeout(() => {
voltarPosicaoInicial(1);
}, 3000);
} else if (fase == 2) {
textoFinal.setAttribute('value','Uau! Uma mais complicada?')
textoFinal.setAttribute('visible', true);
setTimeout(() => {
voltarPosicaoInicial(2);
}, 3000);
} else if (fase == 3) {
textoFinal.setAttribute('value','Irado! Vou complicar mais!')
textoFinal.setAttribute('visible', true);
setTimeout(() => {
voltarPosicaoInicial(3);
}, 3000);
} else if (fase == 4) {
textoFinal.setAttribute('value','Fim. Que fera!')
textoFinal.setAttribute('visible', true);
}
}
}
function voltarPosicaoInicial(numFase) {
this.player.object3D.position.z = 5;
this.player.object3D.position.y = 13;
this.cam.object3D.position.z = 5;
this.cam.object3D.position.y = 13.2;
fase = numFase + 1;
k = parseInt(fase,10)*0.1;
console.log('Fase: '+fase+' k: '+k);
textoFinal.setAttribute('visible', false);
iniciarContagem();
}
function iniciarContagem() {
player.addEventListener('hitstart', finalizarJogo);
sortearObstaculos();
contSom.components.sound.stopSound();
instrucao.setAttribute('visible', false);
let tempoRestante = 3;
let contador = setInterval(function(){
contagem.setAttribute('visible', true);
if(tempoRestante <= -1){
clearInterval(contador);
contagem.setAttribute('visible', false);
requestAnimationFrame(moverPlayer);
roll.components.sound.playSound();
}
if(tempoRestante > 0){
contagem.setAttribute('value', tempoRestante);
contSom.components.sound.playSound();
} else if (tempoRestante == 0){
contagem.setAttribute('value', 'Vai!');
vaiSom.components.sound.playSound();
}
tempoRestante -= 1;
}, 1000);
}
function andarPraFrente(Py) {
this.player.object3D.position.z = -1*(Py + k);
this.player.object3D.position.y = (Py + k)*(-0.0699) + 13; //faz a descida do carrinho
this.cam.object3D.position.z = player.object3D.position.z;
this.cam.object3D.position.y = (Py + k)*(-0.0699) + 13.2; //faz a descida da câmera
checarFim();
}
const moverPlayer = () => {
play = requestAnimationFrame(moverPlayer);
Px = player.object3D.position.x;
Py = -1*(player.object3D.position.z);
if ((RotZ % Math.PI == 0) && ((RotZ/Math.PI) % 2 == 0)){//anda para frente
andarPraFrente(Py);
} else if ((-1*Math.sin(RotZ)) > 0 && Math.cos(RotZ) > 0){ //Diagonal entre frente e direita
this.player.object3D.rotation.y = RotZ;
let DeltaX = (Px + k*(-1*Math.sin(RotZ)));
DeltaX <= 2.5? null:DeltaX = 2.5;
this.player.object3D.position.z = -1*(Py + k*(Math.cos(RotZ)));
this.player.object3D.position.x = DeltaX;
this.player.object3D.position.y = (Py + k*(Math.cos(RotZ)))*(-0.0699) + 13; //faz a descida do carrinho
this.cam.object3D.position.z = player.object3D.position.z;
this.cam.object3D.position.x = DeltaX;
this.cam.object3D.position.y = player.object3D.position.y+0.2; //faz a descida da câmera
checarFim();
} else if (Math.sin(RotZ) > 0 && (-1*Math.cos(RotZ)) < 0){//Diagonal entre frente e esquerda
this.player.object3D.rotation.y = RotZ;
let DeltaX = (Px - k*(Math.sin(RotZ)));
DeltaX >= -2.5? null: DeltaX = -2.5;
this.player.object3D.position.z = -1*(Py + k*(Math.cos(RotZ)));
this.player.object3D.position.x = DeltaX;
this.player.object3D.position.y = (Py + k*(Math.cos(RotZ)))*(-0.0699) + 13; //faz a descida do carrinho
this.cam.object3D.position.z = player.object3D.position.z;
this.cam.object3D.position.x = DeltaX;
this.cam.object3D.position.y = player.object3D.position.y+0.2; //faz a descida da câmera
checarFim();
}else if ((RotZ/(Math.PI/2)) % 2 != 0 && (RotZ/(Math.PI/2)) % 4 == 1 || ((-1*Math.sin(RotZ)) < 0 && Math.cos(RotZ) < 0) || ((RotZ % Math.PI == 0) && ((RotZ/Math.PI) % 2 != 0)) || (Math.sin(RotZ) < 0 && (-1*Math.cos(RotZ))) || ((RotZ/(Math.PI/2)) % 2 != 0 && (RotZ/(Math.PI/2)) % 4 == 3)){
//Andar para esquerda || Diagonal entre esquerda e pra baixo || Andar pra baixo || Diagonal entre direita e pra baixo || Anda para direita - nessa ordem (separados por ou)
//Nesses casos, o carrinho deve continuar andando para frente
andarPraFrente(Py);
}
}
document.querySelector('a-scene').addEventListener('enter-vr', function () {
iniciarContagem();
});
</script>
</body>
</html>