gpt4 book ai didi

Java Game Engine : Raycasted walls are hollow, 损坏,看起来像粪便

转载 作者:搜寻专家 更新时间:2023-11-01 03:18:50 25 4
gpt4 key购买 nike

enter image description here我正在尝试编写光线转换引擎。

我研究了在 http://www.instructables.com/id/Making-a-Basic-3D-Engine-in-Java/ 找到的教程以及在 http://lodev.org/cgtutor/raycasting.html 中找到的 C++ 光线转换教程,经过几次尝试,我将光线转换到正确的方向,因此获得了(半)工作输出。

我让墙出现在世界中,我在游戏中添加了运动,我能够四处移动。然而,无论我面对世界的哪个方向,墙壁(应该是一个立方体)只显示立方体的两侧。因此,它不会显示实心立方体,而是从立方体实际上最靠近相机的一侧跳转,并显示立方体的远侧,这只会在我面向原点 (0,0 ) 存储我的 map 的二维数组。此错误如上图所示。

我认为这个错误是由于整数舍入和光线检测到的墙壁位置被向下舍入造成的,但我似乎无法提出解决方案。我实际上为每个像素列转换两条光线,一条用于检测垂直墙,另一条用于检测水平墙。计算并比较每一个的距离,然后绘制最短距离的墙。

我的问题是如何正确绘制墙壁

 public class Screen {

//VARIABLE DECLARATIONS
//-----------------------
int FOV = 60; //field of view in degrees
int screenwidth = 800; //variable holds the vertical resolution of the screen
int screenheight = 600; //variable holds the horizontal resolution of the screen
double camx; //cameras x coordinate
double camy; //cameras y coordinate
double camAngle; //direction of camera in degrees
double rayAngle; //angle of ray being cast in radians
int x = 0; //holds the current pixel column being looped through
double IncrementAngle = (double)FOV / (double)screenwidth; //calculates the change in the rays angle for each horizontal pixel

int[][] map; //stores the 2d map that represents the 3d world of the game

public Screen() {

public int[] update(int[] pixels, int[][] m, double ca, double cx, double cy, int fov) {

FOV = fov;
IncrementAngle = (double)FOV / (double)screenwidth; //calculates the change in the rays angle for each horizontal pixel

camAngle = ca;
camx = cx;
camy = cy;

map = m;

int x = 0;

Color c; //declares new color

//fills background
for (int n = 0; n < pixels.length; n++) pixels[n] = Color.BLACK.getRGB();

for (double ray = (double)(FOV / 2); ray > (double)(-FOV / 2); ray -= IncrementAngle) {
double vdist = Integer.MAX_VALUE, hdist = Integer.MAX_VALUE;
double perpendicularDist = 0;
double theta;
double lineheight;
int drawstart, drawend;
int side = 0;

int r = 0, g = 0, b = 0, a = 0; //variables that determinbe what colours will be drawn (red, green, blue, and alpha for
transparency)

rayAngle = Math.toRadians(camAngle + ray);

try {
vdist = VertDist(rayAngle);
}
catch (ArrayIndexOutOfBoundsException e) {}
try {
hdist = HorDist(rayAngle);
}
catch (ArrayIndexOutOfBoundsException e) {}

theta = Math.abs(rayAngle - Math.toRadians(camAngle)); //angle difference between the ray being cast and the cameras
direction

if (hdist < vdist) {
perpendicularDist = hdist * Math.cos(theta);
lastSide = 0;
r = Color.GRAY.getRed();
g = Color.GRAY.getGreen();
b = Color.GRAY.getBlue();
a = Color.GRAY.getAlpha();
}
else {
perpendicularDist = vdist * Math.cos(theta);
lastSide = 1;
r = Color.DARK_GRAY.getRed();
g = Color.DARK_GRAY.getGreen();
b = Color.DARK_GRAY.getBlue();
a = Color.DARK_GRAY.getAlpha();
}
//creates pulsating effect with wall colours
r -= pulse;
g += pulse * 2;
b -= pulse;

c = new Color(r, g, b, a);

lineheight = screenheight / perpendicularDist;

drawstart = (int)(-lineheight / 2) + (screenheight / 2);
drawend = (int)(lineheight / 2) + (screenheight / 2);

if (drawstart < 0) drawstart = 0;
if (drawend >= screenheight) drawend = screenheight - 1;

for (int y = drawstart; y < drawend; y++) {
pixels[x + (y * screenwidth)] = c.getRGB();
}

if (x < screenwidth) x++;
else x = 0;
}

//returns pixels array to main class to be shown to screen
return pixels;
}

public double VertDist(double angle) {
double rx = 0, ry = 0;
double stepX = 0, stepY = 0;
double FstepX = 0, FstepY = 0;
double Fxcomp = 0, Fycomp = 0;
double xcomp = 0, ycomp = 0;
double mapx = camx, mapy = camy;
boolean hit = false;
double obliqueDist = 0;

rx = Math.cos(angle);
ry = Math.sin(angle);

if (rx < 0) {
stepX = -1;
FstepX = (camx - ((int)camx)) * stepX;
}
else if (rx > 0) {
stepX = 1;
FstepX = ((int)(camx + 1)) - camx;
}

ycomp = (stepX * Math.tan(angle) * -1);
Fycomp = Math.abs(FstepX) * ycomp;

if (map[(int)(mapx)][(int)(mapy)] > 0) hit = true;

mapx += FstepX;
mapy += Fycomp;

if (map[(int)(mapx)][(int)(mapy)] > 0) hit = true;
else {
while (!hit && mapx > 0 && mapy > 0) { //loops while a wall has not been found and while positive indexes are still being
checked
mapx += stepX;
mapy += ycomp;
if (map[(int)(mapx)][(int)(mapy)] > 0) {
hit = true;
//if (Math.toDegrees(rayAngle) < 270 && Math.toDegrees(rayAngle) > 90) {
// mapy -= stepX;
// mapx -= ycomp;
//}
}
}
}

mapx = Math.abs(mapx - camx);
mapy = Math.abs(mapy - camy);

obliqueDist = Math.sqrt((mapx*mapx) + (mapy*mapy));
//change to be not fixed angle based
//if (angle > Math.toRadians(135) && angle < Math.toRadians(225)) {
// obliqueDist -= Math.sqrt(stepX*stepX + ycomp*ycomp);
//}
return obliqueDist;
}

public double HorDist(double angle) {
double rx, ry;
double stepX = 0, stepY = 0;
double FstepX = 0, FstepY = 0;
double Fxcomp, Fycomp;
double xcomp, ycomp;
double mapx = camx, mapy = camy;
boolean hit = false;
double obliqueDist = 0;

rx = Math.cos(angle);
ry = Math.sin(angle);

if (ry < 0) {
stepY = 1;
FstepY = ((int)(camy + 1)) - camy;
}
else if (ry > 0) {
stepY = -1;
FstepY = (camy - (int)camy) * stepY;
}

xcomp = stepY / (Math.tan(angle) * -1);
Fxcomp = Math.abs(FstepY) * xcomp;

if (map[(int)(mapx)][(int)(mapy)] > 0) hit = true;

mapx += Fxcomp;
mapy += FstepY;

if (map[(int)(mapx)][(int)(mapy)] > 0) hit = true;
else {
while (!hit) {
mapx += xcomp;
mapy += stepY;
if (map[(int)(mapx)][(int)(mapy)] > 0) hit = true;
}
}

mapx = Math.abs(mapx - camx);
mapy = Math.abs(mapy - camy);

obliqueDist = Math.sqrt((mapx*mapx) + (mapy*mapy));
//change to be not fixed angle based
//if (angle > Math.toRadians(45) && angle < Math.toRadians(135)) {
// obliqueDist -= Math.sqrt(xcomp*xcomp + stepY*stepY);
//}
return obliqueDist;
} }

最佳答案

好的,所以我能够修复它。事实证明,正如我所想的那样,问题是由于整数舍入(墙坐标会向下舍入)造成的。当光线转换到二维数组中 x 或 y(或两者)接近零的方向时,墙坐标会向下舍入,到墙的距离计算不正确,结果看起来像图片以上。

我发现发生这种情况是因为我将墙坐标存储为 double ,虽然 double 肯定比整数更准确,但它们仍然不准确。所以发生的事情是壁坐标会非常接近它们应该有的但略有偏离,当我在检查射线壁碰撞时将这些值转换为整数时,它们会向下舍入到实际值下的值协调并为我提供不正确的距离。

所以为了解决这个问题,我添加了一个非常小的值(大约 0.0001)乘以射线的步进方向(步进方向可以是正数或负数 1 并确定后续垂直/水平阵列网格线之间的垂直距离)到射线坐标,同时检查射线壁碰撞,以平衡我的算法的轻微不准确。简而言之,这样做是让检测到的墙离玩家更近 0.0001 个单位,从而绕过不准确并导致光线坐标成功向下舍入到墙的实际坐标。

关于Java Game Engine : Raycasted walls are hollow, 损坏,看起来像粪便,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37803495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com