光线投射引擎运行结果不符合预期的问题排查求助
光线投射引擎渲染异常问题
我正在使用C#和MonoGame开发一个简单的光线投射引擎(目前暂不考虑纹理)。通过递增射线深度的方式检测射线是否击中墙体,再根据玩家与击中位置的距离渲染墙体。
玩家位于横向第3格、纵向第4格,朝向与正北方向呈30°。预期结果为黑色背景上渲染出倾斜的白色墙体,但实际运行结果不符合预期:
我创建了Canvas类用于在纹理上设置像素,通过SpriteBatch渲染:
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;
Game1中的Draw方法代码:
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);
内容的提问来源于stack exchange,提问作者Atomic Peanut
相关产品推荐
相关产品推荐

