Skip to content

Revise API plan generation documentation for clarity - #63

Open
valdineifreita35-a11y wants to merge 1 commit into
TestSprite:v1.0from
valdineifreita35-a11y:patch-1
Open

Revise API plan generation documentation for clarity#63
valdineifreita35-a11y wants to merge 1 commit into
TestSprite:v1.0from
valdineifreita35-a11y:patch-1

Conversation

@valdineifreita35-a11y

Copy link
Copy Markdown
<title>Construtor 3D Realista + Animais</title> <style> body { margin: 0; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } #info { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); background: rgba(0, 0, 0, 0.6); color: white; padding: 8px 20px; border-radius: 30px; font-size: 14px; pointer-events: none; backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.2); white-space: nowrap; } #ui-panel { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 15px; background: rgba(30, 30, 40, 0.8); padding: 15px 25px; border-radius: 60px; backdrop-filter: blur(8px); border: 1px solid rgba(255,255,255,0.15); box-shadow: 0 8px 30px rgba(0,0,0,0.5); flex-wrap: wrap; justify-content: center; } .btn { background: #3a4a5a; border: none; color: white; padding: 10px 22px; border-radius: 40px; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.2s ease; letter-spacing: 0.5px; box-shadow: 0 4px 0 #1f2a33; display: flex; align-items: center; gap: 8px; } .btn:hover { transform: translateY(-2px); filter: brightness(1.2); } .btn:active { transform: translateY(4px); box-shadow: 0 0px 0 #1f2a33; } .btn-casa { background: #e67e22; box-shadow: 0 4px 0 #b85e1a; } .btn-animal { background: #27ae60; box-shadow: 0 4px 0 #1a7a42; } .btn-remover { background: #c0392b; box-shadow: 0 4px 0 #862c21; } .btn span { font-size: 20px; } #contador { position: absolute; bottom: 110px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,0.7); background: rgba(0,0,0,0.4); padding: 5px 16px; border-radius: 20px; font-size: 14px; backdrop-filter: blur(2px); pointer-events: none; } @media (max-width: 600px) { #ui-panel { gap: 10px; padding: 12px 18px; bottom: 20px; } .btn { padding: 8px 14px; font-size: 14px; } #info { font-size: 12px; padding: 5px 15px; white-space: normal; top: 10px; } #contador { bottom: 90px; font-size: 12px; } } </style>
🏡 Clique no chão para construir uma casa | Os animais vagam livremente
🏠 0 casa(s) | 🐾 0 animal(is)
🏠 Adicionar Casa 🐕 Adicionar Animal 🗑️ Remover Animais
<script type="importmap">
    {
        "imports": {
            "three": "https://unpkg.com/three@0.160.0/build/three.module.js",
            "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
        }
    }
</script>

<script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

    // --- CENA, CÂMERA E RENDERIZADOR ---
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x87CEEB);
    scene.fog = new THREE.Fog(0x87CEEB, 18, 30);

    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
    camera.position.set(8, 6, 10);
    camera.lookAt(0, 0, 0);

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    document.body.prepend(renderer.domElement);

    // --- CONTROLES (Orbit) ---
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 1, 0);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.maxPolarAngle = Math.PI / 2.4;
    controls.minDistance = 3;
    controls.maxDistance = 25;

    // --- LUZES ---
    const ambientLight = new THREE.AmbientLight(0x404060, 0.4);
    scene.add(ambientLight);

    const hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
    scene.add(hemiLight);

    const sunLight = new THREE.DirectionalLight(0xffeedd, 1.8);
    sunLight.position.set(12, 18, 10);
    sunLight.castShadow = true;
    sunLight.shadow.mapSize.width = 1024;
    sunLight.shadow.mapSize.height = 1024;
    sunLight.shadow.camera.near = 0.5;
    sunLight.shadow.camera.far = 40;
    sunLight.shadow.camera.left = -15;
    sunLight.shadow.camera.right = 15;
    sunLight.shadow.camera.top = 15;
    sunLight.shadow.camera.bottom = -15;
    scene.add(sunLight);

    const fillLight = new THREE.DirectionalLight(0x88aaff, 0.3);
    fillLight.position.set(-8, 4, -5);
    scene.add(fillLight);

    // --- CHÃO ---
    const groundMat = new THREE.MeshStandardMaterial({ 
        color: 0x5da130, 
        roughness: 0.9, 
        metalness: 0.0 
    });
    const ground = new THREE.Mesh(new THREE.PlaneGeometry(22, 22), groundMat);
    ground.rotation.x = -Math.PI / 2;
    ground.position.y = 0;
    ground.receiveShadow = true;
    scene.add(ground);

    // Grade auxiliar (opcional, mas ajuda na percepção 3D)
    const gridHelper = new THREE.GridHelper(22, 20, 0x88aa55, 0x446633);
    gridHelper.position.y = 0.01;
    scene.add(gridHelper);

    // --- VARIÁVEIS GLOBAIS ---
    const houses = [];
    const animals = [];
    const occupiedPositions = [];
    const clock = new THREE.Clock();
    const raycaster = new THREE.Raycaster();
    const pointer = new THREE.Vector2();

    // --- FUNÇÃO PARA CRIAR UMA CASA REALISTA ---
    function buildHouse(posX, posZ) {
        const group = new THREE.Group();
        
        // Materiais
        const wallMat = new THREE.MeshStandardMaterial({ color: 0xf5e6d3, roughness: 0.6 });
        const roofMat = new THREE.MeshStandardMaterial({ color: 0xcc5533, roughness: 0.8 });
        const doorMat = new THREE.MeshStandardMaterial({ color: 0x5d3a1a, roughness: 0.9 });
        const windowMat = new THREE.MeshStandardMaterial({ color: 0x8ecae6, emissive: 0x1a2a3a, emissiveIntensity: 0.2 });

        // Paredes (base)
        const walls = new THREE.Mesh(new THREE.BoxGeometry(1.9, 1.3, 1.9), wallMat);
        walls.position.y = 0.65;
        walls.castShadow = true;
        walls.receiveShadow = true;
        group.add(walls);

        // Telhado (pirâmide de 4 lados)
        const roof = new THREE.Mesh(new THREE.ConeGeometry(1.6, 0.9, 4), roofMat);
        roof.position.y = 1.3 + 0.45;
        roof.rotation.y = Math.PI / 4;
        roof.castShadow = true;
        roof.receiveShadow = true;
        group.add(roof);

        // Porta (frente, eixo Z positivo)
        const door = new THREE.Mesh(new THREE.BoxGeometry(0.4, 0.6, 0.05), doorMat);
        door.position.set(0, 0.3, 0.96);
        group.add(door);

        // Janelas (laterais)
        const winPositions = [
            [0.7, 0.7, 0.4], // direita
            [-0.7, 0.7, 0.4], // esquerda
            [0.4, 0.7, -0.7], // traseira direita
            [-0.4, 0.7, -0.7] // traseira esquerda
        ];
        winPositions.forEach(pos => {
            const win = new THREE.Mesh(new THREE.BoxGeometry(0.35, 0.35, 0.05), windowMat);
            win.position.set(pos[0], pos[1], pos[2]);
            // Rotaciona as janelas laterais para ficarem viradas para fora
            if (Math.abs(pos[0]) > 0.5) {
                win.rotation.y = Math.PI / 2;
            }
            group.add(win);
        });

        // Pequenos detalhes: batentes da porta
        const frameMat = new THREE.MeshStandardMaterial({ color: 0x8b6b4a });
        const frame = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.64, 0.08), frameMat);
        frame.position.set(0, 0.3, 0.96);
        group.add(frame);

        group.position.set(posX, 0, posZ);
        scene.add(group);
        houses.push(group);
        occupiedPositions.push({ x: posX, z: posZ });
        
        atualizarContador();
        return group;
    }

    // --- FUNÇÃO PARA CRIAR UM ANIMAL (CACHORRO ESTILIZADO) ---
    function createAnimal() {
        const group = new THREE.Group();
        const bodyMat = new THREE.MeshStandardMaterial({ color: 0xd4a373, roughness: 0.7 });
        const darkMat = new THREE.MeshStandardMaterial({ color: 0x8d6b4a, roughness: 0.8 });
        const eyeMat = new THREE.MeshStandardMaterial({ color: 0x111111 });

        // Corpo
        const body = new THREE.Mesh(new THREE.BoxGeometry(0.45, 0.3, 0.65), bodyMat);
        body.position.y = 0.15;
        body.castShadow = true;
        body.receiveShadow = true;
        group.add(body);

        // Cabeça
        const head = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.25, 0.3), bodyMat);
        head.position.set(0, 0.35, 0.45);
        head.castShadow = true;
        head.receiveShadow = true;
        group.add(head);

        // Focinho
        const snout = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.1, 0.15), darkMat);
        snout.position.set(0, 0.3, 0.6);
        group.add(snout);

        // Olhos
        const eyePos = [[-0.1, 0.4, 0.55], [0.1, 0.4, 0.55]];
        eyePos.forEach(pos => {
            const eye = new THREE.Mesh(new THREE.SphereGeometry(0.04, 6), eyeMat);
            eye.position.set(pos[0], pos[1], pos[2]);
            group.add(eye);
        });

        // Orelhas
        const earMat = new THREE.MeshStandardMaterial({ color: 0x7a5230 });
        const earPos = [[-0.2, 0.45, 0.4], [0.2, 0.45, 0.4]];
        earPos.forEach(pos => {
            const ear = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.15, 0.05), earMat);
            ear.position.set(pos[0], pos[1], pos[2]);
            group.add(ear);
        });

        // Pernas
        const legMat = new THREE.MeshStandardMaterial({ color: 0xb08968 });
        const legPos = [[-0.15, 0.075, -0.25], [0.15, 0.075, -0.25], [-0.15, 0.075, 0.25], [0.15, 0.075, 0.25]];
        legPos.forEach(pos => {
            const leg = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.15, 0.08), legMat);
            leg.position.set(pos[0], pos[1], pos[2]);
            leg.castShadow = true;
            group.add(leg);
        });

        // Rabo
        const tail = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.12, 0.04), darkMat);
        tail.position.set(0, 0.25, -0.4);
        tail.rotation.x = 0.3;
        group.add(tail);
        group.userData.tail = tail; // para animar depois

        // Posição inicial aleatória dentro do terreno
        const angle = Math.random() * Math.PI * 2;
        const radius = 2 + Math.random() * 7;
        group.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);

        // Definir alvo aleatório para movimento
        group.userData.target = new THREE.Vector3(
            (Math.random() - 0.5) * 18,
            0,
            (Math.random() - 0.5) * 18
        );
        group.userData.speed = 0.6 + Math.random() * 0.6;
        group.userData.bobPhase = Math.random() * Math.PI * 2;

        scene.add(group);
        animals.push(group);
        atualizarContador();
        return group;
    }

    // --- FUNÇÃO PARA CRIAR ÁRVORES (DECORAÇÃO) ---
    function createTree(posX, posZ) {
        const group = new THREE.Group();
        const trunkMat = new THREE.MeshStandardMaterial({ color: 0x8B5A2B, roughness: 0.9 });
        const leafMat = new THREE.MeshStandardMaterial({ color: 0x2E8B57, roughness: 0.6 });

        const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.18, 0.6), trunkMat);
        trunk.position.y = 0.3;
        trunk.castShadow = true;
        group.add(trunk);

        const foliage1 = new THREE.Mesh(new THREE.SphereGeometry(0.45, 6), leafMat);
        foliage1.position.y = 0.75;
        foliage1.castShadow = true;
        group.add(foliage1);

        const foliage2 = new THREE.Mesh(new THREE.SphereGeometry(0.35, 6), leafMat);
        foliage2.position.set(0.3, 0.9, 0.2);
        foliage2.castShadow = true;
        group.add(foliage2);

        const foliage3 = new THREE.Mesh(new THREE.SphereGeometry(0.35, 6), leafMat);
        foliage3.position.set(-0.25, 0.95, -0.2);
        foliage3.castShadow = true;
        group.add(foliage3);

        group.position.set(posX, 0, posZ);
        scene.add(group);
    }

    // --- SEMEAR ÁRVORES INICIAIS ---
    for (let i = 0; i < 30; i++) {
        const x = (Math.random() - 0.5) * 18;
        const z = (Math.random() - 0.5) * 18;
        // Evita colidir com o centro onde o jogador vai construir
        if (Math.abs(x) < 2 && Math.abs(z) < 2) continue;
        createTree(x, z);
    }

    // --- SEMEAR ANIMAIS E CASA INICIAL ---
    for (let i = 0; i < 3; i++) {
        createAnimal();
    }
    buildHouse(0, 0);

    // --- INTERAÇÃO COM CLICK NO CHÃO ---
    function onPointerDown(event) {
        // Verifica se clicou no canvas (evita disparar ao clicar nos botões)
        if (event.target !== renderer.domElement) return;

        const rect = renderersections l

Removed outdated content and added new interactive elements for live engagement. Updated sections on plan generation, test structure, and user instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant