You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复2.5D光线投射游戏鱼眼畸变及参数优化求助

解决2.5D光线投射游戏的鱼眼畸变与参数优化问题

核心问题分析

你的投射视图出现鱼眼畸变,本质是未对光线距离做视角余弦校正:边缘光线与玩家视线存在夹角,直接使用直线距离会让边缘的墙看起来被拉伸变形。同时画面观感不符合3D效果,是因为墙高的计算逻辑没有结合FOV和投影平面的物理关系。

推荐参数设置

  • FOV(视场角):推荐设置为75,这个数值兼顾写实感和广角视野,是第一人称游戏的常用值;偏好紧凑视角可用65,追求开阔视野则用90。
  • 投影画布尺寸:保持width2=720, height2=360(16:9比例)即可,也可调整为height2=480提升画面高度。
  • 玩家视线高度:对应地图格子大小(你的格子为20单位),设为10(格子高度的一半),符合真实视角逻辑。

代码修改要点

1. 添加鱼眼畸变校正

在计算光线距离后,乘以光线与玩家视线夹角的余弦值,修正距离:

// 原距离计算
let dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// 添加余弦校正
const angleDiff = angle - player.heading;
dist *= Math.cos(angleDiff * Math.PI / 180);

2. 重构墙高计算逻辑

基于投影平面公式计算墙高,替代原有的简单比例计算:

// 提前定义全局参数
const tileSize = 20; // 地图格子大小
const projectionPlaneDist = (width2 / 2) / Math.tan((FOV / 2) * Math.PI / 180);

// 计算墙高
let h = (tileSize / dist) * projectionPlaneDist;
h = Math.min(h, height2); // 限制墙高不超过画布高度

3. 调整FOV参数

把全局FOV修改为:

const FOV = 75;

完整修改后的generateColumns函数

const tileSize = 20;
const projectionPlaneDist = (width2 / 2) / Math.tan((FOV / 2) * Math.PI / 180);

const generateColumns = () => {
    let distances = Array(columns).fill(0);

    for (let i = 0; i < columns; i++) {
        
        let collided = false;

        let rayX = player.x;
        let rayY = player.y;
        
        let angle = (player.heading - FOV / 2) + (i / columns) * FOV;

        let dx = rayCastStep * Math.cos(angle * Math.PI / 180 + Math.PI);
        let dy = rayCastStep * Math.sin(angle * Math.PI / 180 + Math.PI);
        
        while (!collided) {

            rayX -= dx;
            rayY -= dy;

            for (let y = 0; y < map.length; y++) {
                for (let x = 0; x < map[y][0].length; x++) {
                    if (map[y][0][x] == "#" && willCollide({ xC: rayX, yC: rayY }, { x: x * tileSize + tileSize/2, y: y * tileSize + tileSize/2, w: tileSize, h: tileSize })) {
                        collided = true;
    
                        let deltaX = player.x - rayX;
                        let deltaY = player.y - rayY;
                        
                        let dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
                        // 鱼眼校正
                        const angleDiff = angle - player.heading;
                        dist *= Math.cos(angleDiff * Math.PI / 180);
                        
                        // 计算正确的墙高
                        let h = (tileSize / dist) * projectionPlaneDist;
                        h = Math.min(h, height2);
                        
                        distances[i] = {
                            fill: h / height2,
                            h: h
                        }
                    }
                }
            }
        }

        ctx1.strokeStyle = "#fff";
    
        ctx1.beginPath();
        ctx1.moveTo(player.x * (256 / map[0][0].length) / tileSize, player.y * (256 / map.length) / tileSize);
        ctx1.lineTo(rayX * (256 / map[0][0].length) / tileSize, rayY * (256 / map.length) / tileSize)
        ctx1.stroke();

    }
    return distances;
}

效果说明

修改后,鱼眼畸变会完全消除,墙的比例符合真实3D视角逻辑:近处的墙更高,远处的墙按比例缩小,左右边缘的墙不会出现拉伸变形。你可根据视觉偏好调整FOV数值,比如改成85会获得更宽广的视野,适合快节奏游戏体验。

内容的提问来源于stack exchange,提问作者bread

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:45:30