我正在使用java3D制作游戏。它涉及使用“wasd”键进行翻译并使用鼠标旋转的视图。但是,当我同时旋转和平移时,屏幕上的3D形状会来回闪烁。
我尝试研究这个问题,大多数人说我需要双缓冲,但Java3D会自动加倍缓冲。
如何使我的程序平稳无闪烁地运行?
这是我的一部分代码,包括一些设置以及旋转和翻译方法:
import java.applet.Applet;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class PlayerMechanics extends Applet implements KeyListener, MouseListener,
MouseMotionListener
{
Runner runner;
SimpleUniverse universe;
Canvas3D c;
BranchGroup mainGroup = new BranchGroup();
TransformGroup charViewGroup = new TransformGroup();
ViewingPlatform CharVP;
TransformGroup groundGroup;
final static int SCREENWIDTH = 900;
final static int SCREENHEIGHT = 540;
final float CHARACTERHEIGHT = 2.0f;
float MouseX = 0.0f;
float MouseY = 0.0f;
float Speed = 0.0f;
float Iteration = 0.0f;
float xinterval = 0.0f;
float zinterval = 0.0f;
float xloc = 0.0f;
float yloc = 0.0f;
float zloc = 0.0f;
float CVrotX = 0.0f;
float CVrotY = 0.0f;
float CVrotZ = 0.0f;
Vector3f loc = new Vector3f(xloc, yloc, zloc);
boolean moveForward = false;
boolean moveLeft = false;
boolean moveBackward = false;
boolean moveRight = false;
boolean rotUp = false;
boolean rotLeft = false;
boolean rotDown = false;
boolean rotRight = false;
public PlayerMechanics()
{
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
c = new Canvas3D(config);
add("Center", c);
c.addKeyListener(this);
c.addMouseListener(this);
c.addMouseMotionListener(this);
universe = new SimpleUniverse(c);
//Position Cursor in Center of Screen
repositionCursor();
//Create Cubes
for(float a = 0.0f; a < 0.4; a = a + 0.1f)
{
float CubeSize = 0.5f;
float x = 0.0f;
float y = 0.0f;
float z = -5.0f;
if(a == 0.1f)
{
x = -5.0f;
y = 0.0f;
z = 0.0f;
}
else if(a == 0.2f)
{
x = 0.0f;
y = 0.0f;
z = 5.0f;
}
else if(a == 0.3f)
{
x = 5.0f;
y = 0.0f;
z = 0.0f;
}
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
ColorCube cube = new ColorCube(CubeSize);
Vector3f vector = new Vector3f(x, y, z);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cube);
mainGroup.addChild(tg);
}
//Set viewpoint
charViewGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
CharVP = universe.getViewingPlatform();
charViewGroup = CharVP.getMultiTransformGroup().getTransformGroup(0);
resetViewingPlatform();
universe.addBranchGraph(mainGroup);
runner = new Runner();
runner.start();
}
public class Runner extends Thread
{
public void run()
{
while(true)
{
try
{
characterMovement();
Thread.sleep(50);
}
catch(Exception e)
{
System.out.println("Error Encountered! " +
e.getMessage() + "!");
}
}
}
}
@Override
public void mouseDragged(MouseEvent e){}
@Override
public void mouseMoved(MouseEvent e)
{
float XZero = (float)(SCREENWIDTH/2);
float YZero = (float)(SCREENHEIGHT/2);
MouseX = (float)(e.getX());
MouseY = (float)(e.getY());
float NewX = XZero - MouseX;
float NewY = YZero - MouseY;
changeRotationView(NewX, NewY);
repositionCursor();
}
@Override
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
switch(keyCode)
{
case KeyEvent.VK_W:
moveForward = true;
break;
case KeyEvent.VK_A:
moveLeft = true;
break;
case KeyEvent.VK_S:
moveBackward = true;
break;
case KeyEvent.VK_D:
moveRight = true;
break;
//Press Esc to close program
case KeyEvent.VK_ESCAPE:
System.exit(0);
break;
}
}
@Override
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
switch(keyCode)
{
case KeyEvent.VK_W:
moveForward = false;
break;
case KeyEvent.VK_A:
moveLeft = false;
break;
case KeyEvent.VK_S:
moveBackward = false;
break;
case KeyEvent.VK_D:
moveRight = false;
break;
}
}
@Override
public void keyTyped(KeyEvent e){}
@Override
public void mouseClicked(MouseEvent e){}
@Override
public void mouseEntered(MouseEvent e){}
@Override
public void mouseExited(MouseEvent e){}
@Override
public void mousePressed(MouseEvent e){}
@Override
public void mouseReleased(MouseEvent e){}
public void resetViewingPlatform()
{
Transform3D charViewTrans = new Transform3D();
charViewGroup.getTransform(charViewTrans);
//Set Rotation
Transform3D charViewRotY = new Transform3D();
Transform3D charViewRotX = new Transform3D();
charViewRotY.rotY(CVrotY);
charViewRotX.rotX(CVrotX);
charViewTrans.mul(charViewRotY, charViewRotX);
Transform3D charViewTHPRotY = new Transform3D();
Transform3D charViewTHPRotX = new Transform3D();
charViewTHPRotY.rotY(CVrotY);
charViewTHPRotX.rotX(-0.1f);
//Set Translation
loc = new Vector3f(xloc, yloc, zloc);
charViewTrans.setTranslation(loc);
charViewGroup.setTransform(charViewTrans);
}
public void characterMovement()
{
float angle = CVrotY;
float walkSpeed = 0.3f;
byte xSign = 1;
byte zSign = 1;
boolean flipflop = false;
//Quadrant I
if(CVrotY < (float)(-Math.PI/2) && CVrotY > (float)(-Math.PI))
{
angle = (float)(-Math.PI) - CVrotY;
xSign = 1;
zSign = 1;
}
//Quadrant II
if(CVrotY < 0 && CVrotY > (float)(-Math.PI/2))
{
xSign = 1;
zSign = -1;
flipflop = true;
}
//Quadrant III
if(CVrotY > 0 && CVrotY < (float)(Math.PI/2))
{
xSign = -1;
zSign = -1;
}
//Quadrant IV
if(CVrotY > (float)(Math.PI/2) && CVrotY < (float)(Math.PI))
{
angle = (float)(Math.PI) - CVrotY;
xSign = -1;
zSign = 1;
flipflop = true;
}
xinterval = walkSpeed*(float)(Math.sin(angle));
zinterval = walkSpeed*(float)(Math.cos(angle));
if(moveForward)
{
xloc = xloc + (Math.abs(xinterval)*xSign);
zloc = zloc + (Math.abs(zinterval)*zSign);
}
if(moveLeft)
{
if(!flipflop)
{
xloc = xloc + (Math.abs(zinterval)*xSign);
zloc = zloc - (Math.abs(xinterval)*zSign);
}
else
{
xloc = xloc + (Math.abs(zinterval)*-xSign);
zloc = zloc - (Math.abs(xinterval)*-zSign);
}
}
if(moveBackward)
{
xloc = xloc - (Math.abs(xinterval)*xSign);
zloc = zloc - (Math.abs(zinterval)*zSign);
}
if(moveRight)
{
if(!flipflop)
{
xloc = xloc - (Math.abs(zinterval)*xSign);
zloc = zloc + (Math.abs(xinterval)*zSign);
}
else
{
xloc = xloc - (Math.abs(zinterval)*-xSign);
zloc = zloc + (Math.abs(xinterval)*-zSign);
}
}
resetViewingPlatform();
}
public void changeRotationView(float x, float y)
{
//Rotate Y-axis
CVrotY = CVrotY + (x/100)/2;
if(CVrotY >= (float)(Math.PI))
{
CVrotY = CVrotY - (float)(2*Math.PI);
}
else if(CVrotY <= (float)(-Math.PI))
{
CVrotY = CVrotY + (float)(2*Math.PI);
}
//Rotate X-axis
if(CVrotX <= (float)(Math.PI/2) && CVrotX >= (float)(-Math.PI/2))
{
CVrotX = CVrotX + (y/100)/2;
}
else
{
if(CVrotX <= (float)(-Math.PI/2))
{
CVrotX = (float)((-Math.PI/2)+0.001);
}
if(CVrotX >= (float)(Math.PI/2))
{
CVrotX = (float)((Math.PI/2)-0.001);
}
}
resetViewingPlatform();
}
public void repositionCursor()
{
try
{
Point windowLoc = c.getLocationOnScreen();
int xCoord = (windowLoc.x + (SCREENWIDTH/2));
int yCoord = (windowLoc.y + (SCREENHEIGHT/2));
Robot robot = new Robot();
robot.mouseMove(xCoord, yCoord);
}
catch(AWTException e){}
}
public static void main(String[] args)
{
PlayerMechanics playerMechanics = new PlayerMechanics();
new MainFrame(playerMechanics, SCREENWIDTH, SCREENHEIGHT);
}
}
任何帮助将不胜感激。谢谢!