我正在尝试为游戏扩展实现滚动角度,并且为了模拟它,我最好的方法是围绕屏幕中心旋转矩形。
问题是当我用简单的旋转功能旋转矩形时,会出现黑色条纹(注意我使用的是BufferStrategy)。
截图
这是旋转功能:
public void rot(int ai[], int ai1[], int i, int j, int k, int l)
{
if(k != 0)
{
for(int i1 = 0; i1 < l; i1++)
{
int j1 = ai[i1];
int k1 = ai1[i1];
ai[i1] = i + (int)((float)(j1 - i) * cos(k) - (float)(k1 - j) * sin(k));
ai1[i1] = j + (int)((float)(j1 - i) * sin(k) + (float)(k1 - j) * cos(k));
}
}
}
请注意,矩形数据以连续的方式存储。
实施例。 :第一个矩形的y坐标为[0,0,100,100],第二个矩形的坐标为[100,100,200,200],依此类推。
我不想使用Graphics2D.rotate(),因为为了我的目的而分支过多的质量,并且抗锯齿只会产生相同的条纹,但它们看起来更平滑。
我该怎么办?
编辑:提供的测试代码。
主类:
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import javax.swing.JOptionPane;
class ReplayViewer extends Canvas implements Runnable
{
private static final long serialVersionUID = 355508539070062621L;
private static boolean running = false;
private Thread thread;
private Graphics g;
private BufferStrategy bs;
Medium medium;
private synchronized void start()
{
if(running)
return;
createBufferStrategy(3);
bs = this.getBufferStrategy();
g = bs.getDrawGraphics();
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop()
{
try
{
thread.join();
g.dispose();
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void run()
{
long lastTime = System.nanoTime();
final float numOfTicks = 30F;
float ns = 1000000000 / numOfTicks;
double delta = 0;
while(running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if (delta >= 1)
{
updateGameState();
drawToScreen();
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
delta--;
}
}
stop();
}
private void updateGameState()
{
}
private void drawToScreen()
{
medium.d(g);
bs.show();
}
public ReplayViewer()
{
medium = new Medium();
setPreferredSize(new Dimension(medium.w, medium.h));
}
public static void main(String[] args)
{
try
{
final Frame frame = new Frame("NFM Replay Viewer");
ReplayViewer rply = new ReplayViewer();
frame.add(rply);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
running = false;
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
});
rply.start();
} catch (Exception e)
{
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Viewer cannot be open!", "Error", 0);
}
}
}
中等班级:
import java.awt.Color;
import java.awt.Graphics;
public class Medium
{
int focus_point;
int ground;
int skyline;
int fade[] = { 3000, 4500, 6000, 7500, 9000, 10500, 12000, 13500, 15000, 16500, 18000, 19500, 21000, 22500, 24000, 25500 };
int cldd[] = { 210, 210, 210, 1, -1000 };
int clds[] = { 210, 210, 210 };
int osky[] = { 170, 220, 255 };
int csky[] = { 170, 220, 255 };
int ogrnd[] = { 205, 200, 200 };
int cgrnd[] = { 205, 200, 200 };
int texture[] = { 0, 0, 0, 50 };
int cpol[] = { 215, 210, 210 };
int crgrnd[] = { 205, 200, 200 };
int cfade[] = { 255, 220, 220 };
int snap[] = { 0, 0, 0 };
int fogd;
boolean loadnew;
boolean lightson;
boolean darksky;
int lightn;
int lilo;
boolean lton;
int noelec;
int trk;
boolean crs;
int cx;
int cy;
int cz;
int xz;
int zy;
int x;
int y;
int z;
int iw;
int ih;
int w;
int h;
int nsp;
int spx[];
int spz[];
int sprad[];
int adv;
float tcos[];
float tsin[];
int lastmaf;
int checkpoint;
boolean lastcheck;
float elecr;
boolean cpflik;
boolean nochekflk;
int cntrn;
boolean diup[] = { false, false, false };
int rand[] = { 0, 0, 0 };
int trn;
int hit;
int ogpx[][];
int ogpz[][];
float pvr[][];
int cgpx[];
int cgpz[];
int pmx[];
float pcv[];
int sgpx;
int sgpz;
int nrw;
int ncl;
int noc;
int clx[];
int clz[];
int cmx[];
int clax[][][];
int clay[][][];
int claz[][][];
int clc[][][][];
int nmt;
int mrd[];
int nmv[];
int mtx[][];
int mty[][];
int mtz[][];
int mtc[][][];
int nst;
int stx[];
int stz[];
int stc[][][];
boolean bst[];
int twn[];
int resdown;
int xy;
public float sin(int i)
{
for(; i >= 360; i -= 360) { }
for(; i < 0; i += 360) { }
return tsin[i];
}
public float cos(int i)
{
for(; i >= 360; i -= 360) { }
for(; i < 0; i += 360) { }
return tcos[i];
}
public int ys(int i, int j)
{
if (j < 10)
j = 10;
return ((j - focus_point) * (cy - i)) / j + i;
}
public void d(Graphics graphics2d)
{
nsp = 0;
int loops = 0;
if (xz > 360)
{
xz -= 360;
}
if (xz < 0)
{
xz += 360;
}
for(; zy >= 90; zy -= 180) { loops++; }
for(; zy < -90; zy += 180) { loops--; }
ground = 250 - y;
int ai[] = new int[4];
int ai1[] = new int[4];
int i = cgrnd[0];
int j = cgrnd[1];
int k = cgrnd[2];
int l = crgrnd[0];
int i1 = crgrnd[1];
int j1 = crgrnd[2];
int k1;
if(loops % 2 == 0)
k1 = h + cx;
else
k1 = ih - cx;
for (int l1 = 0; l1 < 16; l1++)
{
int j2 = fade[l1];
int l2;
if(loops % 2 == 0)
{
l2 = ground;
if (zy != 0)
{
l2 = cy + (int) ((ground - cy) * cos(zy) - (fade[l1] - cz) * sin(zy));
j2 = cz + (int) ((ground - cy) * sin(zy) + (fade[l1] - cz) * cos(zy));
}
} else
{
l2 = -ground + h;
if(zy != 0)
{
l2 = cy + (int)((float)(-ground + h - cy) * cos(zy) - (float)(fade[l1] - cz) * sin(zy));
j2 = cz + (int)((float)(-ground + h - cy) * sin(zy) + (float)(fade[l1] - cz) * cos(zy));
}
}
ai[0] = iw;
ai1[0] = ys(l2, j2);
if (ai1[0] < ih - cx)
{
ai1[0] = ih - cx;
}
if (ai1[0] > h + cx)
{
ai1[0] = h + cx;
}
ai[1] = iw - cx;
ai1[1] = k1;
ai[2] = w + cx;
ai1[2] = k1;
ai[3] = w + cx;
ai1[3] = ai1[0];
k1 = ai1[0];
if (l1 > 0)
{
l = (l * 7 + cfade[0]) / 8;
i1 = (i1 * 7 + cfade[1]) / 8;
j1 = (j1 * 7 + cfade[2]) / 8;
if (l1 < 3)
{
i = (i * 7 + cfade[0]) / 8;
j = (j * 7 + cfade[1]) / 8;
k = (k * 7 + cfade[2]) / 8;
} else
{
i = l;
j = i1;
k = j1;
}
}
rot(ai, ai1, cx, cy, xy, 4);
graphics2d.setColor(new Color(i, j, k));
graphics2d.fillPolygon(ai, ai1, 4);
}
if (lightn != -1 && lton)
{
if (lightn < 16)
{
if (lilo > lightn + 217)
{
lilo -= 3;
} else
{
lightn = (int) (16F + 16F * random());
}
} else if (lilo < lightn + 217)
{
lilo += 7;
} else
{
lightn = (int) (16F * random());
}
csky[0] = (int) (lilo + lilo * (snap[0] / 100F));
if (csky[0] > 255)
{
csky[0] = 255;
}
if (csky[0] < 0)
{
csky[0] = 0;
}
csky[1] = (int) (lilo + lilo * (snap[1] / 100F));
if (csky[1] > 255)
{
csky[1] = 255;
}
if (csky[1] < 0)
{
csky[1] = 0;
}
csky[2] = (int) (lilo + lilo * (snap[2] / 100F));
if (csky[2] > 255)
{
csky[2] = 255;
}
if (csky[2] < 0)
{
csky[2] = 0;
}
}
i = csky[0];
j = csky[1];
k = csky[2];
int i2 = i;
int k2 = j;
int i3 = k;
int j3;
int k3;
if(loops % 2 == 0)
{
j3 = cy + (int) ((skyline - 700 - cy) * cos(zy) - (7000 - cz) * sin(zy));
k3 = cz + (int) ((skyline - 700 - cy) * sin(zy) + (7000 - cz) * cos(zy));
} else
{
j3 = cy + (int) ((-skyline + 700 + h - cy) * cos(zy) - (7000 - cz) * sin(zy));
k3 = cz + (int) ((-skyline + 700 + h - cy) * sin(zy) + (7000 - cz) * cos(zy));
}
j3 = ys(j3, k3);
int l3;
if(loops % 2 == 0)
l3 = ih - cx;
else
l3 = h + cx;
for (int i4 = 0; i4 < 16; i4++)
{
int k4 = fade[i4];
int i5;
if (loops % 2 == 0)
{
i5 = skyline;
if (zy != 0)
{
i5 = cy + (int) ((skyline - cy) * cos(zy) - (fade[i4] - cz) * sin(zy));
k4 = cz + (int) ((skyline - cy) * sin(zy) + (fade[i4] - cz) * cos(zy));
}
} else
{
i5 = -skyline + h;
if (zy != 0)
{
i5 = cy + (int) ((-skyline + h - cy) * cos(zy) - (fade[i4] - cz) * sin(zy));
k4 = cz + (int) ((-skyline + h - cy) * sin(zy) + (fade[i4] - cz) * cos(zy));
}
}
ai[0] = iw - cx;
ai1[0] = ys(i5, k4);
if (ai1[0] < ih - cx)
{
ai1[0] = ih - cx;
}
if (ai1[0] > h + cx)
{
ai1[0] = h + cx;
}
ai[1] = iw - cx;
ai1[1] = l3;
ai[2] = w + cx;
ai1[2] = l3;
ai[3] = w + cx;
ai1[3] = ai1[0];
l3 = ai1[0];
if (i4 > 0)
{
i = (i * 7 + cfade[0]) / 8;
j = (j * 7 + cfade[1]) / 8;
k = (k * 7 + cfade[2]) / 8;
}
rot(ai, ai1, cx, cy, xy, 4);
graphics2d.setColor(new Color(i, j, k));
graphics2d.fillPolygon(ai, ai1, 4);
}
ai[0] = iw - cx;
ai1[0] = l3;
ai[1] = iw - cx;
ai1[1] = k1;
ai[2] = w + cx;
ai1[2] = k1;
ai[3] = w + cx;
ai1[3] = l3;
float f = (Math.abs(y) - 250F) / (fade[0] * 2);
if (f < 0.0F)
{
f = 0.0F;
}
if (f > 1.0F)
{
f = 1.0F;
}
i = (int) ((i * (1.0F - f) + l * (1.0F + f)) / 2.0F);
j = (int) ((j * (1.0F - f) + i1 * (1.0F + f)) / 2.0F);
k = (int) ((k * (1.0F - f) + j1 * (1.0F + f)) / 2.0F);
rot(ai, ai1, cx, cy, xy, 4);
graphics2d.setColor(new Color(i, j, k));
graphics2d.fillPolygon(ai, ai1, 4);
if (resdown != 2)
{
for (int j4 = 1; j4 < 20; j4++)
{
int l4 = 7000;
int j5;
if (loops % 2 == 0)
{
j5 = skyline - 700 - j4 * 70;
if (zy != 0 && j4 != 19)
{
j5 = cy + (int) ((skyline - 700 - j4 * 70 - cy) * cos(zy) - (7000 - cz) * sin(zy));
l4 = cz + (int) ((skyline - 700 - j4 * 70 - cy) * sin(zy) + (7000 - cz) * cos(zy));
}
} else
{
j5 = -skyline + 700 + j4 * 70 + h;
if (zy != 0 && j4 != 19)
{
j5 = cy + (int) ((-skyline + 700 + j4 * 70 + h - cy) * cos(zy) - (7000 - cz) * sin(zy));
l4 = cz + (int) ((-skyline + 700 + j4 * 70 + h - cy) * sin(zy) + (7000 - cz) * cos(zy));
}
}
ai[0] = iw - cx;
if (j4 != 19)
{
ai1[0] = ys(j5, l4);
if (ai1[0] > h + cx)
{
ai1[0] = h + cx;
}
if (ai1[0] < ih - cx)
{
ai1[0] = ih - cx;
}
} else
{
if (loops % 2 == 0)
ai1[0] = ih - cx;
else
ai1[0] = h + cx;
}
ai[1] = iw - cx;
ai1[1] = j3;
ai[2] = w + cx;
ai1[2] = j3;
ai[3] = w + cx;
ai1[3] = ai1[0];
j3 = ai1[0];
i2 = (int) (i2 * 0.99099999999999999D);
k2 = (int) (k2 * 0.99099999999999999D);
i3 = (int) (i3 * 0.998D);
rot(ai, ai1, cx, cy, xy, 4);
graphics2d.setColor(new Color(i2, k2, i3));
graphics2d.fillPolygon(ai, ai1, 4);
}
}
zy += 180 * loops;
zy++;
xy++;
}
public float random()
{
if (cntrn == 0) {
int i = 0;
do {
rand[i] = (int) (10D * Math.random());
if (Math.random() > Math.random())
diup[i] = false;
else
diup[i] = true;
} while (++i < 3);
cntrn = 20;
} else {
cntrn--;
}
int j = 0;
do
if (diup[j]) {
rand[j]++;
if (rand[j] == 10)
rand[j] = 0;
} else {
rand[j]--;
if (rand[j] == -1)
rand[j] = 9;
}
while (++j < 3);
trn++;
if (trn == 3)
trn = 0;
return rand[trn] / 10F;
}
public Medium()
{
focus_point = 400;
ground = 250;
skyline = -300;
fogd = 7;
loadnew = false;
lightson = false;
darksky = false;
lightn = -1;
lilo = 217;
lton = false;
noelec = 0;
trk = 0;
crs = false;
cx = 400;
cy = 225;
cz = 50;
xz = 0;
zy = 0;
x = 0;
y = -1000;
z = 0;
iw = 0;
ih = 0;
w = 800;
h = 450;
nsp = 0;
spx = new int[7];
spz = new int[7];
sprad = new int[7];
adv = 500;
tcos = new float[360];
tsin = new float[360];
lastmaf = 0;
checkpoint = -1;
lastcheck = false;
elecr = 0.0F;
cpflik = false;
nochekflk = false;
cntrn = 0;
trn = 0;
hit = 45000;
ogpx = null;
ogpz = null;
pvr = null;
cgpx = null;
cgpz = null;
pmx = null;
pcv = null;
sgpx = 0;
sgpz = 0;
nrw = 0;
ncl = 0;
noc = 0;
clx = null;
clz = null;
cmx = null;
clax = null;
clay = null;
claz = null;
clc = null;
nmt = 0;
mrd = null;
nmv = null;
mtx = null;
mty = null;
mtz = null;
mtc = null;
nst = 0;
stx = null;
stz = null;
stc = null;
bst = null;
twn = null;
resdown = 0;
for (int i = 0; i < 360; i++)
{
tcos[i] = (float) Math.cos(i * 0.017453292519943295D);
}
for (int j = 0; j < 360; j++)
{
tsin[j] = (float) Math.sin(j * 0.017453292519943295D);
}
xy = 0;
}
public void rot(int ai[], int ai1[], int i, int j, int k, int l)
{
if(k != 0)
{
for(int i1 = 0; i1 < l; i1++)
{
int j1 = ai[i1];
int k1 = ai1[i1];
ai[i1] = i + (int)((float)(j1 - i) * cos(k) - (float)(k1 - j) * sin(k));
ai1[i1] = j + (int)((float)(j1 - i) * sin(k) + (float)(k1 - j) * cos(k));
}
}
}
}
答案 0 :(得分:0)
旋转和其他矩阵变换实际上很难做到。您看到的工件很可能是由于旋转代码中的逻辑错误或浮点精度错误(您是否尝试使用double
而不是float
?)。< / p>
但好消息是,你实际上并不需要重新实现这个轮子。 Java完全为此目的提供AffineTransform
类。基本上,您可以转换图形对象的状态,而不是您自己绘制的元素。这里是Java tutorial,还有很多related questions。