raycasting 엔진을 작성하려고합니다.Java Game Engine : Raycasted 벽이 투명하고 부서지며 대변처럼 보입니다.
http://www.instructables.com/id/Making-a-Basic-3D-Engine-in-Java/에있는 자습서와 http://lodev.org/cgtutor/raycasting.html에있는 C++ 레이캐스팅 자습서를 공부하고 몇 가지 시도를 한 후에 광선을 올바른 방향으로 전송하여 작업 결과를 얻었습니다.
나는 세계에 나타나기 위해 벽을 얻었고 나는 게임으로 움직임을 추가했고 나는 움직일 수 있었다. 그러나 벽 (큐브라고 생각되는)은 내가 세상에서 직면하고있는 방향에 관계없이 입방체의 두 면만 보여줍니다. 그래서 단단한 입방체를 보여주는 대신 실제로 카메라에 가장 가까운 입방체의 측면에서 점프하여 대신 큐브의 먼 쪽을 보여줍니다. 이것은 원점을 향한 메신저 (0,0) 내지도가 저장되어있는 2 차원 배열의.이 오류는 위의 이미지에 표시됩니다.
이 오류는 정수 반올림과 광선에 의해 감지되는 광선의 위치가 반올림 됨으로 인한 것 같지만 아직 해결 방법을 찾지 못하는 것 같습니다. 저는 실제로 각 픽셀 열에 대해 두 개의 광선을 주조했습니다. 하나는 수직 벽을 감지하고 다른 하나는 수평 벽을 감지합니다. 각 거리가 계산되고 비교 된 다음 최단 거리 벽이 그려집니다.
내 문제는 내가 그것을 고칠 수 있었다, 그래서 벽이 제대로
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;
} }
단락을 사용하는 법을 배우십시오. 논리적 인 단절이없는 거대한 텍스트의 벽은 사람들을 끄고 질문 및/또는 하향 표시를 건너 뜁니다. 그런 다음 질문을 작성할 때 간결하고 요점을 지키십시오. 관련없는 정보는 모두 생략하십시오. 우리는 당신이이 점에 어떻게 도달했는지에 대한 전체 역사를 알 필요가 없습니다. 구체적인 질문을하십시오. –
내가 간결하고 간결하게 게시물을 편집했습니다. 내가 너무 많이 떼어 낸다면 자유롭게 돌아가서 편집 할 수 있습니다. 그러나 문제를 나타내는 *** *** 예제로 코드를 줄이려면 매우 유용 할 것입니다. 산문과 마찬가지로이 문제와 무관 한 것을 제거하고 [mcve]를 만드십시오. 그렇게하는 과정은 아마도 당신에게 꽤 많은 것을 가르쳐 줄 것이고 당신 자신의 문제를 해결할 수도 있습니다. 그것은 항상 저를 위해 그렇게 작동합니다. –
실제로 직접 downvoting 및 떠나는 대신 내 게시물에 건설적인 비판을 떠나 주셔서 감사합니다. 다음에 내가 게시 할 때 염두에두고 말한 것을 계속 유지하십시오. 나는 실제로 불필요한 모든 비트들을 제거하려고하고 있었고, 그렇게 해 주셔서 감사합니다. – xonerex