I am in very early stages of making a Three.js checkers game. I have the board made, and now i want to put the board on top of a table, how can I do it? Here is my code so far. (the comments are in Portuguese, sorry).
// Cria uma nova cena 3D usando a biblioteca Three.js.
var scene = new THREE.Scene();
// Inicializa uma câmera perspectiva com um campo de visão de 80 graus, uma razão de aspecto baseada na largura e altura da janela do navegador, e define distâncias de recorte entre 0.1 e 1000.
var camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
// Posiciona a câmera 10 unidades distante do plano xy na direção z.
camera.position.z = 10;
// Cria um renderizador WebGL que permite renderizar a cena 3D no navegador.
var renderer = new THREE.WebGLRenderer();
// Define o tamanho do renderizador para ocupar a largura e altura completas da janela.
renderer.setSize(window.innerWidth, window.innerHeight);
// Define a cor de fundo do renderizador para um tom escuro de verde.
scene.background = new THREE.Color(0x38761D);
// Adiciona o elemento DOM do renderizador ao corpo do documento, permitindo que a cena seja visível no navegador.
document.body.appendChild(renderer.domElement);
// Instancia um objeto Board (presumivelmente uma classe definida em outro lugar no código) que gerencia o tabuleiro do jogo.
var board = new Board();
// Chama o método build da instância board, passando a cena como parâmetro para adicionar elementos ao tabuleiro na cena.
board.build(scene);
// Calcula o campo de visão vertical em radianos a partir do campo de visão em graus da câmera.
var vFOV = camera.fov * Math.PI / 180;
// Calcula a altura visível com base na distância da câmera (10 unidades).
var height = 2 * Math.tan(vFOV / 2) * 10;
// Calcula a razão de aspecto da janela.
var aspect = window.innerWidth / window.innerHeight;
// Calcula a largura visível com base na altura visível e na razão de aspecto.
var width = height * aspect;
// Adiciona uma luz ambiente à cena para iluminar todos os objetos igualmente com uma cor cinza escura.
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
// Adiciona uma luz focal à cena, posiciona-a acima da origem e permite que ela projete sombras.
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 0, 10);
spotLight.castShadow = true;
scene.add(spotLight);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 0, 10);
pointLight.castShadow = true;
var lightType = 'ambient'; // Variável para controlar qual luz está ativa
// Cria uma div para mostrar o tipo de luz ativa
var lightIndicator = document.createElement('div');
lightIndicator.style.position = 'absolute';
lightIndicator.style.top = '50px';
lightIndicator.style.right = '10px';
lightIndicator.innerHTML = "Luz Ativa: Ambient Light";
document.body.appendChild(lightIndicator);
// Função para alternar entre as luzes
function toggleLight() {
if (lightType === 'ambient') {
scene.remove(ambientLight);
scene.add(pointLight);
lightType = 'point';
lightIndicator.innerHTML = "Luz Ativa: Point Light";
} else {
scene.remove(pointLight);
scene.add(ambientLight);
lightType = 'ambient';
lightIndicator.innerHTML = "Luz Ativa: Ambient Light";
}
}
// Cria um botão na interface para alternar as luzes
var button = document.createElement('button');
button.innerHTML = "Alterar Iluminação";
button.onclick = toggleLight;
button.style.position = 'absolute';
button.style.top = '10px';
button.style.right = '10px';
button.style.fontSize = '20px';
button.style.border = "thick solid #359bbd";
button.style.backgroundColor = "#2a35c9";
button.style.color = "#ffffff"; // Define a cor da fonte para branco
document.body.appendChild(button);
// Cria um raio para detectar interseções com objetos na cena com base nas coordenadas do mouse.
var raycaster = new THREE.Raycaster();
// Inicializa um objeto para armazenar as coordenadas x e y do mouse.
var mouse = { x: 0, y: 0 };
// Cria e configura uma div para exibir informações sobre as peças no jogo, estilizando-a e adicionando-a ao corpo do documento.
var black = document.createElement('div');
black.setAttribute('id', 'black');
black.style.position = 'absolute';
black.style.color = '#D1D1D1';
black.style.width = 100;
black.style.height = 100;
black.style.fontSize = '24px';
black.innerHTML = "<table>" +
"<tr style='font-weight:bold;'><td>Brancas</td><td>( 12 Restantes )</td></tr>" +
"<tr style='color: black'><td>Vermelhas</td><td>( 12 Restantes )</td></tr>" +
"</table>";
black.style.border = "thick solid #359bbd";
black.style.backgroundColor = "#2a35c9";
black.style.top = 1.5 + '%';
black.style.left = 1 + '%';
black.style.padding = "1%";
document.body.appendChild(black);
// Define uma variável para controlar se uma peça está sendo movida.
var grabbed = false;
// Inicializa os controles de órbita para permitir a interação com a câmera através do mouse.
controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
// Configura eventos do mouse para manipulação das peças do jogo e interação com a cena.
$(document).ready(function () {
$(document.body).mousedown(function(event) {
// Atualiza a posição do mouse com base no evento do clique.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Define o raio a partir da posição da câmera e das coordenadas do mouse.
raycaster.setFromCamera(mouse, camera);
// Calcula interseções com objetos na cena.
var intersects = raycaster.intersectObjects(scene.children);
// Processa interseções para manipulação de peças ou controle da câmera.
for (var i = 0; i < intersects.length; i++) {
if (intersects[i].object['checkersObject'] == 'Piece') {
var success = board.grab(intersects[i].object["col"], intersects[i].object["row"]);
if (success) {
board.showLegals(intersects[i].object["col"], intersects[i].object["row"], scene);
grabbed = true;
}
} else if (intersects[i].object['checkersObject'] == 'Tile') {
controls.enabled = false;
}
}
// Atualiza a posição da peça sendo segurada com base na posição do mouse.
board.moveHolding(scene, camera, mouse.x, mouse.y);
});
$(document.body).mousemove(function(event) {
// Atualiza continuamente a posição do mouse durante o movimento.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Move a peça que está sendo segurada conforme o mouse se move.
board.moveHolding(scene, camera, mouse.x, mouse.y);
});
$(document.body).mouseup(function (event) {
// Atualiza a posição do mouse quando o botão do mouse é solto.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Define o raio a partir da posição da câmera e das coordenadas do mouse.
raycaster.setFromCamera(mouse, camera);
// Calcula interseções com objetos na cena.
var intersects = raycaster.intersectObjects(scene.children);
// Processa interseções para soltar peças ou reativar controles de câmera.
for (var i = 0; i < intersects.length; i++) {
if (intersects[i].object['checkersObject'] == 'Tile') {
var success = board.drop(intersects[i].object["col"], intersects[i].object["row"], scene);
if (success) {
grabbed = false;
}
}
board.unshowLegals(scene);
}
controls.enabled = true;
});
// Chama a função de renderização para atualizar a visualização da cena.
render();
});
// Configura o evento de redimensionamento da janela para ajustar a câmera e o renderizador.
$(window).resize(function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Define a posição original da câmera e controla se a animação está ativa.
var origin = camera.position;
var animate = true;
var clock = new THREE.Clock();
// Função para animar a câmera se necessário (não utilizada ativamente).
function rotateAnimation() {
camera.position.y += clock.getElapsedTime() * 2.5;
camera.position.z += clock.getElapsedTime() * 2.5;
}
function createTable(scene) {
const tableWidth = 200; // Mais largo que o tabuleiro para dar uma boa aparência
const tableHeight = 5; // Altura razoável para a mesa
const tableDepth = 100; // Profundidade proporcional à largura
const tableGeometry = new THREE.BoxGeometry(tableWidth, tableHeight, tableDepth);
const tableMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 }); // Cor de madeira
const tableMesh = new THREE.Mesh(tableGeometry, tableMaterial);
tableMesh.position.set(0, -tableHeight / 2, 0); // Ajuste para alinhar ao centro na base
scene.add(tableMesh);
return tableMesh.position.y + tableHeight / 2; // Retorna a posição do topo da mesa
}
function setupScene() {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // Azul claro como céu
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 50, 150);
camera.lookAt(new THREE.Vector3(0, 0, 0));
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(50, 50, 50);
scene.add(pointLight);
const tableTopHeight = createTable(scene);
const board = new Board();
board.build(scene);
board.mesh.position.y = tableTopHeight; // Posiciona o tabuleiro em cima da mesa
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
}
setupScene();
// Função de renderização que é chamada recursivamente para atualizar e renderizar a cena.
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}