光线投射引擎的意外结果

问题描述 投票:0回答:1
我正在尝试使用 C# 和 Monogame 创建一个简单的光线投射引擎。 (我现在不担心纹理。)按照

本教程,我创建了增加光线深度的代码(我知道这是低效且不准确的),直到它撞到墙上。然后我渲染墙,其大小取决于玩家与光线击中位置之间的距离。

用户位于横 3 格、下 4 格的位置,面朝北 30°。预期的结果是在黑色背景上呈现白色倾斜的墙壁。以下是该程序的结果:

我有一个名为

Canvas

 的类,我用它来设置纹理上的像素以使用 
SpriteBatch
 进行渲染。

Canvas.cs


using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Raycaster { public class Canvas { Texture2D texture; Color[] pixels; bool changed = false; public Canvas(GraphicsDevice graphicsDevice, int width, int height) { texture = new Texture2D(graphicsDevice, width, height); pixels = new Color[width * height]; } public void Draw(SpriteBatch _spriteBatch) { if (changed) { changed = false; texture.SetData(pixels); } _spriteBatch.Draw(texture, new Vector2(0, 0), Color.White); } public void SetPixel(int x, int y, Color color) { int position = x + (y * texture.Width); if (position >= 0 && position < pixels.Length) { pixels[position] = color; changed = true; } } public void Clear() { pixels = new Color[texture.Width * texture.Height]; } } }
以下是我在

Game1.cs

中设置的一些变量和常量

const int Width = 1024; const int Height = 700; int[,] map = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 }, { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; Vector2 playerPosition = new Vector2(192, 256); double playerRotation = 30; const double playerFOV = 60; const double deltaAngle = playerFOV / Width; const int unitsPerSquare = 64; Canvas canvas;
这是我在

Draw

方法中使用的代码,在
Game1
中:

GraphicsDevice.Clear(Color.Black); canvas.Clear(); double angle = playerRotation - (playerFOV / 2); for (int column = 0; column < Width; column++) { int depth = 0; bool wallFound = false; Vector2 wallHit = new Vector2(0, 0); while (!wallFound) { if (depth > 1024) break; double x = playerPosition.X + depth * Math.Cos(angle); double y = playerPosition.Y + depth * Math.Sin(angle); if (x < 0 || y < 0 || x > Width || y > Height) break; for (int i = 0; i < map.GetLength(0); i++) { if (wallFound) break; for (int j = 0; j < map.GetLength(1); j++) { if (wallFound) break; int value = map[i, j]; if (value == 0) continue; else if (value == 1) { Vector2 currentPosition = new Vector2((float)x, (float)y); Rectangle cubeRectangle = new Rectangle(i * unitsPerSquare, j * unitsPerSquare, unitsPerSquare, unitsPerSquare); if (cubeRectangle.Contains(currentPosition)) { wallFound = true; wallHit = currentPosition; } } } } depth++; } if (wallFound) { float distance = Vector2.Distance(playerPosition, wallHit); int wallRenderHeight = (int)Math.Round(Width * (1 / (distance / unitsPerSquare))); int wallRenderY = (Height / 2) - (wallRenderHeight / 2); for (int i = 0; i < wallRenderHeight; i++) canvas.SetPixel(column, i + wallRenderY, Color.White); } angle += deltaAngle; } _spriteBatch.Begin(); canvas.Draw(_spriteBatch); _spriteBatch.End(); base.Draw(gameTime);
    
c# rendering monogame raycasting
1个回答
0
投票
方法

Math.Sin

Math.Cos
 采用弧度而不是角度。在使用三角函数之前,我通过将角度(以度为单位)转换为弧度来修复该程序:

double angleRadians = Math.PI * angle / 180; double x = playerPosition.X + depth * Math.Cos(angleRadians); double y = playerPosition.Y + depth * Math.Sin(angleRadians);
    
© www.soinside.com 2019 - 2024. All rights reserved.