坤坤3D迷宫HTML代码

<!DOCTYPE html>
<html>
<head>
    <title>3D迷宫</title>
    <style>
        body { margin: 0; overflow: hidden; }
    </style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

<script>
// 全局变量声明
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 100);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 在全局变量区域新增:
let isMouseLocked = false;


const mazeLayout = [
    // 边界墙(强化外层结构)
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    // 新的随机分布与数字平衡
    [1,0,3,4,0,5,2,3,5,4,2,0,5,3,4,0,2,5,0,3,0,1],
    [1,0,5,0,3,0,0,0,0,5,0,4,0,0,0,0,4,0,0,3,0,1],
    [1,0,0,0,5,0,4,2,0,0,0,3,5,2,0,0,5,0,0,0,0,1],
    [1,0,4,0,1,0,0,1,0,5,0,1,0,0,0,0,1,0,2,0,0,1],
    [1,0,3,0,1,0,0,1,0,4,0,1,0,5,0,0,1,0,5,4,0,1],
    [1,0,0,0,4,1,1,5,0,0,0,4,5,3,0,0,1,0,3,0,0,1],
    [1,0,5,0,0,0,0,0,0,3,0,5,0,2,0,0,1,0,0,0,0,1],
    [1,0,2,5,0,4,5,0,2,2,0,0,0,0,0,0,1,0,5,4,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,3,5,2,0,0,1,0,4,0,0,1],
    [1,0,4,0,5,3,2,0,5,0,4,1,0,1,0,0,1,0,0,0,0,1],
    [1,0,5,0,0,0,0,0,4,0,3,1,0,1,0,0,1,0,2,5,0,1],
    [1,0,0,0,3,5,2,0,0,0,0,1,0,1,0,0,1,0,5,2,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,3,0,0,1],
    [1,0,3,0,5,4,2,0,3,0,5,1,0,1,0,0,1,0,0,0,0,1],
    [1,0,4,0,0,0,0,0,3,0,2,1,0,1,0,0,1,0,5,2,0,1],
    [1,0,0,0,2,1,1,4,0,0,0,4,5,3,0,0,1,0,2,0,0,1],
    [1,0,5,0,1,0,0,1,0,4,0,1,0,0,0,0,1,0,0,0,0,1],
    [1,0,2,0,1,0,0,1,0,3,0,1,0,5,0,0,1,0,2,0,0,1],
    [1,0,5,4,0,3,5,0,2,2,0,0,0,0,0,0,1,0,4,0,0,1],
    [1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
const walls = [];
const moveSpeed = 0.15;
let verticalSpeed = 0;
let canJump = true;
let keys = { forward: false, back: false, left: false, right: false, jump: false };
let cameraDirection = new THREE.Vector3();
let cameraRight = new THREE.Vector3();
let yaw = 0, pitch = 0;
let prevMouseX = 0, prevMouseY = 0;
let sensitivity = 0.3;
let frameCount = 0;
const playerRadius = 0.5;

// 初始化场景
const floorGeometry = new THREE.PlaneGeometry(50, 50);
const floorMaterial = new THREE.MeshPhongMaterial({ color: 0x444444 });
const floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI/2;
scene.add(floor);

camera.position.set(0, 2, 8);
camera.rotation.set(0, 0, 0);
// 在初始化时添加事件监听:
renderer.domElement.addEventListener('click', () => {
    if (!isMouseLocked) {
        renderer.domElement.requestPointerLock();
    }
});

document.addEventListener('pointerlockchange', () => {
    isMouseLocked = document.pointerLockElement === renderer.domElement;
});

document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
        document.exitPointerLock();
        isMouseLocked = false;
    }
});

// 灯光设置
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(0, 10, 0);
scene.add(directionalLight);
function createTextTexture(text, options = {}) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = 512;
    canvas.height = 512;

    // 设置渐变背景
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
    gradient.addColorStop(0, '#FF3366');
    gradient.addColorStop(0.5, '#4FACFE');
    gradient.addColorStop(1, '#00F2FE');

    // 设置文字样式
    ctx.font = 'bold 72px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    // 调整文字垂直位置,将文字向上移动一些
    const textY = canvas.height * 0.4;  // 从0.5改为0.4,使文字更靠上

    // 添加发光效果
    ctx.shadowColor = '#FF9ECD';
    ctx.shadowBlur = 15;
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;

    // 绘制描边
    ctx.strokeStyle = '#FFFFFF';
    ctx.lineWidth = 8;
    ctx.strokeText(text, canvas.width/2, textY);

    // 使用渐变填充文字
    ctx.fillStyle = gradient;
    ctx.fillText(text, canvas.width/2, textY);

    // 调整装饰线的位置
    ctx.beginPath();
    ctx.strokeStyle = '#FFD700';
    ctx.lineWidth = 2;
    ctx.moveTo(100, textY + 80);  // 装饰线也相应上移
    ctx.lineTo(canvas.width - 100, textY + 80);
    ctx.stroke();

    return new THREE.CanvasTexture(canvas);
}

// 为每个文字创建不同的样式
const caiTexture = createTextTexture('蔡徐坤', {
    gradient: ['#FF3366', '#4FACFE', '#00F2FE']
});

const jiTexture = createTextTexture('鸡你太美', {
    gradient: ['#FF416C', '#FF4B2B', '#F7971E']
});

const manTexture = createTextTexture('一个真正的man', {
    gradient: ['#8E2DE2', '#4A00E0', '#6A11CB']
});

const youTexture = createTextTexture('你干嘛哎呦', {
    gradient: ['#20E2D7', '#F9D423', '#FF4E50']
});
// 生成迷宫部分完整修改后的代码:
const wallMaterial = new THREE.MeshPhongMaterial({ color: 0x999999 });

for (let row = 0; row < mazeLayout.length; row++) {
    for (let col = 0; col < mazeLayout[row].length; col++) {
        const value = mazeLayout[row][col];
        if (value >= 1) { // 只要>=1就生成墙
            let material;
            if (value === 1) {
                material = wallMaterial;
            } else if (value === 2) {
                material = new THREE.MeshBasicMaterial({ map: caiTexture, side: THREE.DoubleSide });
            } else if (value === 3) {
                material = new THREE.MeshBasicMaterial({ map: jiTexture, side: THREE.DoubleSide });
            } else if (value === 4) {
                material = new THREE.MeshBasicMaterial({ map: manTexture, side: THREE.DoubleSide });
            } else if (value === 5) {
                material = new THREE.MeshBasicMaterial({ map: youTexture, side: THREE.DoubleSide });
            }

            const wall = new THREE.Mesh(new THREE.BoxGeometry(2,5,2), material);
            wall.position.x = (col*2) - 11 +1;
            wall.position.z = (row*2) - 11 +1;
            walls.push(wall);
            scene.add(wall);
        }
    }
}
// 输入处理
document.addEventListener('keydown', (e) => {
    switch(e.code) {
        case 'KeyW': keys.forward = true; break;
        case 'KeyS': keys.back = true; break;
        case 'KeyA': keys.left = true; break;
        case 'KeyD': keys.right = true; break;
        case 'Space': keys.jump = true; break;
    }
});

document.addEventListener('keyup', (e) => {
    switch(e.code) {
        case 'KeyW': keys.forward = false; break;
        case 'KeyS': keys.back = false; break;
        case 'KeyA': keys.left = false; break;
        case 'KeyD': keys.right = false; break;
        case 'Space': keys.jump = false; break;
    }
});

document.addEventListener('mousemove', (e) => {
    let dx = e.movementX || 0;
    let dy = e.movementY || 0;

    // 过滤微小移动
    if (Math.abs(dx) < 0.3) dx = 0;
    if (Math.abs(dy) < 0.3) dy = 0;

    prevMouseX = dx;
    prevMouseY = dy;
});

document.body.style.cursor = 'none';
// 跳跃逻辑相关变量
const JUMP_FORCE = 2.5;
const GRAVITY = 0.8;
let lastJumpTime = 0;

// 玩家相关变量
const GROUND_LEVEL = 1.5; // 地面高度
const PLAYER_RADIUS = 0.5; // 玩家半径
const PLAYER_HEIGHT = PLAYER_RADIUS * 2; // 玩家总高度

// 碰撞检测函数
function isColliding(position) {
    const playerBox = new THREE.Box3();
    playerBox.setFromCenterAndSize(
        position,
        new THREE.Vector3(PLAYER_RADIUS * 2, PLAYER_HEIGHT, PLAYER_RADIUS * 2)
    );

    for (const wall of walls) {
        const wallBox = new THREE.Box3().setFromObject(wall);
        if (playerBox.intersectsBox(wallBox)) return true;
    }

    return false;
}

// 更新跳跃逻辑
function updateJump() {
    // 精确的地面检测
    const isOnGround = camera.position.y <= GROUND_LEVEL + PLAYER_HEIGHT;

    // 处理跳跃,添加时间间隔控制
    if (keys.jump && isOnGround && canJump) {
        const currentTime = performance.now();
        if (currentTime - lastJumpTime > 250) {
            verticalSpeed = JUMP_FORCE;
            canJump = false;
            lastJumpTime = currentTime;
        }
    }

    // 更新位置
    camera.position.y += verticalSpeed * 0.014;
    verticalSpeed -= GRAVITY * 0.014;

    // 地面碰撞处理
    if (camera.position.y <= GROUND_LEVEL + PLAYER_HEIGHT) {
        camera.position.y = GROUND_LEVEL + PLAYER_HEIGHT;
        verticalSpeed = 0;
        canJump = true;
    }
}

// 主循环
function animate() {
    requestAnimationFrame(animate);

    // 更新跳跃逻辑
    updateJump();

    // 渲染场景
    renderer.render(scene, camera);
}

// 启动动画
animate();

// 监听键盘事件
window.addEventListener('keydown', (event) => {
    if (event.code === 'Space') {
        keys.jump = true;
    }
});

window.addEventListener('keyup', (event) => {
    if (event.code === 'Space') {
        keys.jump = false;
    }
});
// 移动逻辑
function updateMovement() {
    camera.getWorldDirection(cameraDirection);
    cameraDirection.y = 0;
    cameraDirection.normalize();
    
    cameraRight.crossVectors(cameraDirection, new THREE.Vector3(0,1,0)).normalize();

    let moveVector = new THREE.Vector3(0,0,0);
    if(keys.forward) moveVector.add(cameraDirection);
    if(keys.back) moveVector.add(cameraDirection.negate());
    if(keys.left) moveVector.add(cameraRight.negate());
    if(keys.right) moveVector.add(cameraRight);

    moveVector.normalize();

    const stepSize = moveSpeed * 0.1 * 0.2;
    const steps = 5;

    for (let i = 0; i < steps; i++) {
        const stepVector = moveVector.clone().multiplyScalar(stepSize);
        const newPosition = camera.position.clone().add(stepVector);
        
        if (!isColliding(newPosition)) {
            camera.position.copy(newPosition);
        } else {
            camera.position.add( stepVector.multiplyScalar(-0.5) );
            break;
        }
    }
}


// 视角控制

function updateCameraRotation() {
    if (!isMouseLocked) return;

    // 更严格的防抖阈值(0.5改为0.1)
    if (Math.abs(prevMouseX) < 0.05) prevMouseX = 0;
    if (Math.abs(prevMouseY) < 0.05) prevMouseY = 0;

    // 完全静止时立即返回
    if (prevMouseX === 0 && prevMouseY === 0) return;

    // 统一灵敏度计算(修复原代码重复计算问题)
    const deltaX = prevMouseX * sensitivity * 0.002;
    const deltaY = prevMouseY * sensitivity * 0.002;

    // 应用旋转
    yaw -= deltaX;
    pitch -= deltaY;

    // 加强视角限制
    pitch = Math.max(Math.min(pitch, Math.PI/2 - 0.2), -Math.PI/2 + 0.2);  // 保留10度安全区
    yaw = yaw % (Math.PI * 2);  // 保持yaw在合理范围内

    // 设置旋转顺序防止侧转
    camera.rotation.order = 'YXZ';  // 关键设置:先Y轴后X轴
    camera.rotation.set(pitch, yaw, 0);
}

// 自动修复位置
function fixPosition() {
    const originalPos = camera.position.clone();
    
    if (isColliding(originalPos)) {
        camera.position.y += 0.5;
    }
    
    if (isColliding(camera.position)) {
        camera.position.copy(originalPos).add(cameraDirection.multiplyScalar(-1));
    }
}

// 动画循环
function animate() {
    updateCameraRotation();
    
    updateMovement();
    updateJump();
    
    if (frameCount % 30 === 0) {
        fixPosition();
    }
    
    renderer.render(scene, camera);
    requestAnimationFrame(animate);
    frameCount++;
}

animate();

// 获取渲染器的canvas元素
const canvas = renderer.domElement;

// 提示用户如何操作(更新提示内容)
console.log("按 F 键进入全屏模式,双击 Esc 退出全屏并显示光标");

let escPressCount = 0;
const ESC_DOUBLE_CLICK_INTERVAL = 300; // 双击判定时间间隔(毫秒)

// 专用全屏进入函数
function enterFullScreen() {
    if (!document.fullscreenElement) {
        canvas.requestFullscreen().catch(console.error);
        document.body.style.cursor = 'none';
    }
}

// 专用全屏退出函数
function exitFullScreen() {
    if (document.fullscreenElement) {
        document.exitFullscreen();
    }
    document.body.style.cursor = 'auto';
}

// 监听键盘事件:F 键强制进入全屏
document.addEventListener('keydown', (e) => {
    if (e.key.toLowerCase() === 'f') {  // 支持大小写
        enterFullScreen();
        e.preventDefault(); // 阻止默认行为
    }
});

// 双击 ESC 检测逻辑
document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
        const now = Date.now();
        
        if (!escPressCount || now - escPressCount > ESC_DOUBLE_CLICK_INTERVAL) {
            escPressCount = now;
            return;
        }

        // 检测到双击
        exitFullScreen();
        escPressCount = 0;
        e.preventDefault();
    }
});

// 全屏状态变化监听
document.addEventListener('fullscreenchange', () => {
    if (!document.fullscreenElement) {
        document.body.style.cursor = 'auto';
    }
});

// 额外添加:鼠标移动时显示光标(游戏常用设计)
let cursorTimeout;
document.addEventListener('mousemove', () => {
    document.body.style.cursor = 'auto';
    clearTimeout(cursorTimeout);
    cursorTimeout = setTimeout(() => {
        if (document.fullscreenElement) {
            document.body.style.cursor = 'none';
        }
    }, 2000); // 2秒无操作后隐藏光标
});


</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值