我有一個java項目誰使「windows迷宮」,並使用光線投射算法。下面是截圖:不同高度尺寸的光芒鑄造
就像你可以看到所有的牆壁具有相同的高度尺寸。我想這樣做,但不同的高度尺寸
private void castRay(int xOnScreen,double angle,double direction) {
R rx = castRayInX(angle,direction);
R ry = castRayInY(angle,direction);
// In case of out-of-space rays
if (rx.getDistance()==Double.MAX_VALUE && ry.getDistance()==Double.MAX_VALUE) {
graphics.setColor(BACKGROUND);
graphics.drawLine(xOnScreen,0,xOnScreen,this.image.getHeight());
return;
}
double distance = rx.getDistance();
double normal = rx.getNormal();
Color c = rx.getColor();
double coef = Math.cos((angle+direction+Math.PI)-normal);
Plot collision = rx.getPlot();
if (ry.getDistance()<rx.getDistance()) {
distance = ry.getDistance();
normal = ry.getNormal();
c = ry.getColor();
coef = Math.cos((angle+direction+Math.PI)-normal);
collision = ry.getPlot();
}
coef = Math.abs(coef);
int factor = map.length*SQUARE_SIZE;
double d = (double)(distance+factor)/factor;
coef *= 1/(d*d);
Color c2 = new Color((int)(c.getRed()*coef),(int)(c.getGreen()*coef),(int)(c.getBlue()*coef));
graphics.setColor(c2);
// graphics.setColor(c); // no illumination
distance *= Math.cos(angle); // lens correction
int h = (int)(this.screenDistance/distance*WALL_HEIGHT); // perspective height
int vh = this.image.getHeight();
graphics.drawLine(xOnScreen,(vh-h)/2,xOnScreen,(vh+h)/2);
drawEye(direction,collision);
}
private R castRayInX(double angleRay,double direction) {
double angle = angleRay+direction;
double x1 = eye.getX()+SQUARE_SIZE*Math.cos(angle);
double y1 = eye.getY()+SQUARE_SIZE*Math.sin(angle);
double slope = (y1-eye.getY())/(x1-eye.getX());
if (Math.cos(angle)==0) {
if (Math.sin(angle)>0)
return new R(Double.MAX_VALUE,3*Math.PI/2,BACKGROUND,null);
else
return new R(Double.MAX_VALUE,Math.PI/2,BACKGROUND,null);
}
if (Math.cos(angle)>0) {
int firstX = ((eye.getX()/SQUARE_SIZE)+1)*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
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);
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();
return new R(Math.sqrt(DX*DX+DY*DY),Math.PI,c,new Plot((int)x,(int)y, WALL_HEIGHT));
}
}
return r;
} else {
int firstX = ((eye.getX()/SQUARE_SIZE))*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
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);
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();
return new R(Math.sqrt(DX*DX+DY*DY),0,c,new Plot((int)x,(int)y, WALL_HEIGHT));
}
}
return r;
}
}
private R castRayInY(double angleRay,double direction) {
// System.out.println("cast ray 2 Y "+angleRay+" "+direction);
double angle = angleRay+direction;
double x1 = eye.getX()+SQUARE_SIZE*Math.cos(angle);
double y1 = eye.getY()+SQUARE_SIZE*Math.sin(angle);
// System.out.println(eye+" "+x1+" "+y1);
double slope = (y1-eye.getY())/(x1-eye.getX());
if (Math.sin(angle)==0) {
if (Math.cos(angle)>0)
return new R(Double.MAX_VALUE,Math.PI,BACKGROUND,null);
else
return new R(Double.MAX_VALUE,0,BACKGROUND,null);
}
if (Math.sin(angle)>0) {
int firstY = ((eye.getY()/SQUARE_SIZE)+1)*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
for (int y = firstY; y<map.length*SQUARE_SIZE; y += SQUARE_SIZE) {
int x = (int)((y-eye.getY())/slope)+eye.getX();
if (isOutside(x,y,Color.CYAN,this.showRayCastingY)) break;
Color c = colorAt(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) {
double DX = x-eye.getX();
int DY = y-eye.getY();
return new R(Math.sqrt(DX*DX+DY*DY),3*Math.PI/2,c,new Plot((int)x,(int)y, WALL_HEIGHT));
}
}
return r;
} else {
int firstY = ((eye.getY()/SQUARE_SIZE))*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
for (int y = firstY; y>=0; y -= SQUARE_SIZE) {
int x = (int)((y-eye.getY())/slope)+eye.getX();
if (isOutside(x,y,Color.CYAN,this.showRayCastingY)) break;
Color c = colorAt(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) {
double DX = x-eye.getX();
int DY = y-eye.getY();
return new R(Math.sqrt(DX*DX+DY*DY),Math.PI/2,c,new Plot((int)x,(int)y, WALL_HEIGHT));
}
}
return r;
}
}
我R
類有現在Plot (x, y, z)
我用WALL_HEIGHT
顏色,距離和正常的光。目前這個工作正常,但我想添加一個像castRayInZ這樣的新函數,但是我沒有全部的數學理論。我的迷宮是由地圖製作這樣的:
private String [][]map = { // each: SQUARE_SIZE x SQUARE_SIZE
{ "Y300", "Z500", "X230", "Y112", "Z321", "X120", "X354" },
{ "X89", " ", " ", " ", "Y120", " ", "X232" },
{ "Z124", " ", "X276", " ", "X123", " ", "X" },
{ "Y290", " ", " ", " ", " ", " ", "X100" },
{ "X32", "Z430", " ", "Y500", "X120", " ", "X123" },
{ "X222", " ", " ", " ", " ", " ", "X210" },
{ "X12", "Y98", "Y763", "X146", "Y111", "Y333", "X321" }
,其中XYZ是顏色(X爲紅色,Y爲綠色和Z爲藍只是測試我的光功能),我添加了一個高度,每平方我的地圖。我將全部長度設置爲SQUARE_LENGTH
,現在可能稍後我會將每個方塊的大小縮小到一個像素,並通過生成它來放大我的地圖。但我真的很想知道如何改變每個方格的高度。現在我的工作就可以了,因爲4天,我沒有任何線索......
編輯
我有一些消息,我改變了我的牆壁的尺寸,但我有一些奇怪的東西,這裏是截圖:
就像你可以看到我有一些奇怪的事情出現在這裏。這裏是我的代碼:
private void castRay(int xOnScreen,double angle,double direction) {
R rx = castRayInX(angle,direction);
R ry = castRayInY(angle,direction);
// In case of out-of-space rays
if (rx.getDistance()==Double.MAX_VALUE && ry.getDistance()==Double.MAX_VALUE) {
graphics.setColor(BACKGROUND);
graphics.drawLine(xOnScreen,0,xOnScreen,this.image.getHeight());
return;
}
double distance = rx.getDistance();
double normal = rx.getNormal();
Color c = rx.getColor();
double coef = Math.cos((angle+direction+Math.PI)-normal);
Plot collision = rx.getPlot();
if (ry.getDistance()<rx.getDistance()) {
distance = ry.getDistance();
normal = ry.getNormal();
c = ry.getColor();
coef = Math.cos((angle+direction+Math.PI)-normal);
collision = ry.getPlot();
}
coef = Math.abs(coef);
int factor = map.length*SQUARE_SIZE;
double d = (double)(distance+factor)/factor;
coef *= 1/(d*d);
Color c2 = new Color((int)(c.getRed()*coef),(int)(c.getGreen()*coef),(int)(c.getBlue()*coef));
graphics.setColor(c);
distance *= Math.cos(angle); // lens correction
int h;
int hw = (int)(this.screenDistance/distance*WALL_HEIGHT); //WALL_HEIGHT value is 300px at default
if(rx.getPlot() != null)
h = (int)(this.screenDistance/distance*rx.getPlot().getZ()); // perspective height
else
h = (int)(this.screenDistance/distance*WALL_HEIGHT);
int vh = this.image.getHeight();
int y0 = (hw+vh)/2;
int y1 = (vh-h)/2;
graphics.drawLine(xOnScreen,y0,xOnScreen,y1);
drawEye(direction,collision);
我的問題應該是從castRayInX
功能:
private R castRayInX(double angleRay,double direction) {
double angle = angleRay+direction;
double x1 = eye.getX()+SQUARE_SIZE*Math.cos(angle);
double y1 = eye.getY()+SQUARE_SIZE*Math.sin(angle);
double slope = (y1-eye.getY())/(x1-eye.getX());
if (Math.cos(angle)==0) {
if (Math.sin(angle)>0)
return new R(Double.MAX_VALUE,3*Math.PI/2,BACKGROUND,null);
else
return new R(Double.MAX_VALUE,Math.PI/2,BACKGROUND,null);
}
if (Math.cos(angle)>0) {
int firstX = ((eye.getX()/SQUARE_SIZE)+1)*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
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 (z == 0) z = heightAt(x,y-1);
if (z == 0) z = heightAt(x-1,y);
if (z == 0) z = heightAt(x-1,y-1);
if (c!=null) {
int DX = x-eye.getX();
double DY = y-eye.getY();
return new R(Math.sqrt(DX*DX+DY*DY),Math.PI,c,new Plot((int)x,(int)y,(int)z));
}
}
return r;
} else {
int firstX = ((eye.getX()/SQUARE_SIZE))*SQUARE_SIZE;
R r = new R(Double.MAX_VALUE,angle+Math.PI,BACKGROUND,null);
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 (z == 0) z = heightAt(x,y-1);
if (z == 0) z = heightAt(x-1,y);
if (z == 0) z = heightAt(x-1,y-1);
if (c!=null) {
int DX = x-eye.getX();
double DY = y-eye.getY();
return new R(Math.sqrt(DX*DX+DY*DY),0,c,new Plot((int)x,(int)y,(int)z));
}
}
return r;
}
}
我應該做一個castRayInZ
功能?或者我應該在其他地方獲得我的z
價值?
你不是已經自己回答了這個問題嗎?每個補丁需要不同的高度值,而不是'WALL_HEIHGT'。你有什麼麻煩? –
使用恆定值很容易,但我不知道如何獲得所有不同的高度。我有一些奇怪的東西 – Jack