首頁  >  文章  >  Java  >  如何使用光線投射演算法在 Java「Windows 迷宮」專案中向牆壁添加不同的高度尺寸?

如何使用光線投射演算法在 Java「Windows 迷宮」專案中向牆壁添加不同的高度尺寸?

Barbara Streisand
Barbara Streisand原創
2024-11-06 01:32:02134瀏覽

How can I add different height sizes to walls in a Java

不同高度尺寸的光線投射

問題

在使用光線投射演算法的Java「windows'迷宮」專案中,所有牆壁都有相同的高度尺寸。目標是創建一個具有不同高度尺寸的版本。

解決方案

1.將高度資訊加入地圖:

在地圖中的每個單元格上新增第三個值,以表示該單元格中牆壁的高度。例如,pmap[y][x] =(顏色、距離、高度)。

2。更新光線投射演算法:

  • 檢查命中偵測的 Z 值: 檢查命中時,包括高度值以確定光線是否擊中牆壁正確的高度。
  • 計算投影高度:根據光線到擊中點的距離和視角計算牆壁的投影高度。
  • 調整渲染:

    • 可變高度渲染:使用投影高度調整牆壁的掃描線渲染,創建牆壁的掃描線渲染,創建3D效果。
    • 頂部渲染: 檢查牆壁背面的命中情況,並從最後渲染的 y 座標到目前的 y 座標渲染頂部顏色。

3。考慮滑鼠滾輪輸入:

允許使用者使用滑鼠滾輪調整牆壁的高度(在地圖編輯器模式下)。

詳細代碼片段:此處是修訂後的castRayInX函數的片段:

    // Check for hits on front or back wall based on direction
    boolean hit = false;
    Color c = null;
    int z = 0;
    if (slope > 0) {
        int firstX = ((eye.getX() / SQUARE_SIZE) + 1) * SQUARE_SIZE;
        for (int x = firstX; x < map[0].length * SQUARE_SIZE; x += SQUARE_SIZE) {
            int y = (int) (slope * (x - eye.getX()) + eye.getY());
            if (isOutside(x, y, Color.MAGENTA, this.showRayCastingX))
                break;
            c = colorAt(x, y);
            z = heightAt(x, y);
            if (c == null)
                c = colorAt(x, y - 1);
            if (c == null)
                c = colorAt(x - 1, y);
            if (c == null)
                c = colorAt(x - 1, y - 1);
            if (c != null) {
                int DX = x - eye.getX();
                double DY = y - eye.getY();
                hit = true;
                break;
            }
        }
        if (!hit && slope != Double.POSITIVE_INFINITY) // check back wall
            for (int x = firstX; x >= 0; x -= SQUARE_SIZE) {
                int y = (int) (slope * (x - eye.getX()) + eye.getY());
                if (isOutside(x, y, Color.MAGENTA, this.showRayCastingX))
                    break;
                c = colorAt(x, y);
                z = heightAt(x, y);
                if (c == null)
                    c = colorAt(x, y - 1);
                if (c == null)
                    c = colorAt(x - 1, y);
                if (c == null)
                    c = colorAt(x - 1, y - 1);
                if (c != null) {
                    int DX = x - eye.getX();
                    double DY = y - eye.getY();
                    hit = true;
                    break;
                }
            }
    } else {
        int firstX = ((eye.getX() / SQUARE_SIZE)) * SQUARE_SIZE;
        for (int x = firstX; x >= 0; x -= SQUARE_SIZE) {
            int y = (int) (slope * (x - eye.getX()) + eye.getY());
            if (isOutside(x, y, Color.MAGENTA, this.showRayCastingX))
                break;
            Color c = colorAt(x, y);
            int z = heightAt(x, y);
            if (c == null)
                c = colorAt(x, y - 1);
            if (c == null)
                c = colorAt(x - 1, y);
            if (c == null)
                c = colorAt(x - 1, y - 1);
            if (c != null) {
                int DX = x - eye.getX();
                double DY = y - eye.getY();
                hit = true;
                break;
            }
        }
        if (!hit && slope != Double.POSITIVE_INFINITY) // check back wall
            for (int x = firstX; x < map[0].length * SQUARE_SIZE; x += SQUARE_SIZE) {
                int y = (int) (slope * (x - eye.getX()) + eye.getY());
                if (isOutside(x, y, Color.MAGENTA, this.showRayCastingX))
                    break;
                Color c = colorAt(x, y);
                int z = heightAt(x, y);
                if (c == null)
                    c = colorAt(x, y - 1);
                if (c == null)
                    c = colorAt(x - 1, y);
                if (c == null)
                    c = colorAt(x - 1, y - 1);
                if (c != null) {
                    int DX = x - eye.getX();
                    double DY = y - eye.getY();
                    hit = true;
                    break;
                }
            }
    }

    // If hit, compute projected height and adjust rendering
    if (hit) {
        h = (int) (this.screenDistance / distance * z);
        int hw = (int) (this.screenDistance / distance * WALL_HEIGHT); // WALL_HEIGHT value is 300px at default
        int y0 = (hw + vh) / 2;
        int y1 = (vh - h) / 2;
        graphics.drawLine(xOnScreen, y0, xOnScreen, y1);
    }

附加說明:

  • 以類似的方式更新castRayInY函數。
  • 要偵測牆壁的背面,只要再增加一個坡度條件:

    } else if (slope > 0 && slope < Double.POSITIVE_INFINITY) {...} // back face

    以上是如何使用光線投射演算法在 Java「Windows 迷宮」專案中向牆壁添加不同的高度尺寸?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn