Java 具有同心指示方块的宇宙飞船模拟器制导计算机瞄准
我正在和一些人一起做一个3D空间交易游戏,我被指派去做的一件事就是制作一个引导计算机“隧道”,让飞船通过,隧道由正方形组成,用户可以飞到他们的目的地,随着用户离目的地越来越近,数量也越来越多 只需要为船前方的点渲染正方形,因为这是用户可以看到的全部内容。在他们前往目的地的途中,船上的计算机应该在HUD上放置正方形,表示你和目的地之间空间中的固定点,这些点的距离很小,并且随着点接近飞船而变大 我尝试过实现它,但似乎无法理解,主要是使用对数(Java 具有同心指示方块的宇宙飞船模拟器制导计算机瞄准,java,math,applet,logarithm,Java,Math,Applet,Logarithm,我正在和一些人一起做一个3D空间交易游戏,我被指派去做的一件事就是制作一个引导计算机“隧道”,让飞船通过,隧道由正方形组成,用户可以飞到他们的目的地,随着用户离目的地越来越近,数量也越来越多 只需要为船前方的点渲染正方形,因为这是用户可以看到的全部内容。在他们前往目的地的途中,船上的计算机应该在HUD上放置正方形,表示你和目的地之间空间中的固定点,这些点的距离很小,并且随着点接近飞船而变大 我尝试过实现它,但似乎无法理解,主要是使用对数(Math.log10(x)等等)。我试图得到“对数空间”
Math.log10(x)
等等)。我试图得到“对数空间”中的船舶位置,以帮助找出绘制正方形时从哪个索引开始,但事实上,我只有到目的地的距离可供处理,这使问题变得混乱,特别是当你考虑平方的数量必须动态变化以确保它们在空间的正确位置保持固定时(即,在对数变换之前,这些正方形被定位在200左右的间隔)。
关于这一点,我在0.0d的开始和1.0d的结束之间使用了ship的一个工作实现,尽管这个实现不是很好。无论如何,问题本质上归结为一维性质。对于此问题的任何建议,包括实现相同效果或解决方案的可能解决方法,我们将不胜感激
(还有一段Youtube视频显示了这种效果:)
干杯,克里斯 编辑:重新表述整个问题 编辑:新测试台代码:
package st;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferStrategy;
import java.text.DecimalFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class StUI2 extends JFrame {
public static final double DEG_TO_RAD = Math.PI / 180.0d;
public static final DecimalFormat decimalFormat = new DecimalFormat("0.0000");
public static final Font MONO = new Font("Monospaced", Font.PLAIN, 10);
public class StPanel extends Canvas {
protected final Object imgLock = new Object();
protected int lastWidth = 1, lastHeight = 1;
protected boolean first = true;
protected Color bgColour = Color.DARK_GRAY, gridColour = Color.GRAY;
double shipWrap = 700;
double shipFrame = 100;
double shipPos = 0;
long lastUpdateTimeMS = -1;
long currUpdateTimeMS = -1;
public StPanel() {
setFocusable(true);
setMinimumSize(new Dimension(1, 1));
setAlwaysOnTop(true);
}
public void internalPaint(Graphics2D g) {
synchronized (imgLock) {
if (lastUpdateTimeMS < 0) {
lastUpdateTimeMS = System.currentTimeMillis();
}
currUpdateTimeMS = System.currentTimeMillis();
long diffMS = currUpdateTimeMS - lastUpdateTimeMS;
g.setFont(MONO);
shipPos += (60d * ((double)diffMS / 1000));
if (shipPos > shipWrap) {
shipPos = 0d;
}
double shipPosPerc = shipPos / shipWrap;
double distToDest = shipWrap - shipPos;
double compression = 1000d / distToDest;
g.setColor(bgColour);
Dimension d = getSize();
g.fillRect(0, 0, (int)d.getWidth(), (int)d.getHeight());
//int amnt2 = (int)unlog10((1000d / distToDest));
g.setColor(Color.WHITE);
g.drawString("shipPos: " + decimalFormat.format(shipPos), 10, 10);
g.drawString("distToDest: " + decimalFormat.format(distToDest), 10, 20);
g.drawString("shipWrap: " + decimalFormat.format(shipWrap), 150, 10);
int offset = 40;
g.setFont(MONO);
double scalingFactor = 10d;
double dist = 0;
int curri = 0;
int i = 0;
do {
curri = i;
g.setColor(Color.GREEN);
dist = distToDest - getSquareDistance(distToDest, scalingFactor, i);
double sqh = getSquareHeight(dist, 100d * DEG_TO_RAD);
g.drawLine(30 + (int)dist, (offset + 50) - (int)(sqh / 2d), 30 + (int)dist, (offset + 50) + (int)(sqh / 2d));
g.setColor(Color.LIGHT_GRAY);
g.drawString("i: " + i + ", dist: " + decimalFormat.format(dist), 10, 120 + (i * 10));
i++;
} while (dist < distToDest);
g.drawLine(10, 122, 200, 122);
g.drawString("last / i: " + curri + ", dist: " + decimalFormat.format(dist), 10, 122 + (i * 10));
g.setColor(Color.MAGENTA);
g.fillOval(30 + (int)shipPos, offset + 50, 4, 4);
lastUpdateTimeMS = currUpdateTimeMS;
}
}
public double getSquareDistance(double initialDist, double scalingFactor, int num) {
return Math.pow(scalingFactor, num) * num * initialDist;
}
public double getSquareHeight(double distance, double angle) {
return distance / Math.tan(angle);
}
/* (non-Javadoc)
* @see java.awt.Canvas#paint(java.awt.Graphics)
*/
@Override
public void paint(Graphics g) {
internalPaint((Graphics2D)g);
}
public void redraw() {
synchronized (imgLock) {
Dimension d = getSize();
if (d.width == 0) d.width = 1;
if (d.height == 0) d.height = 1;
if (first || d.getWidth() != lastWidth || d.getHeight() != lastHeight) {
first = false;
// remake buf
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
//create an object that represents the device that outputs to screen (video card).
GraphicsDevice gd = ge.getDefaultScreenDevice();
gd.getDefaultConfiguration();
createBufferStrategy(2);
lastWidth = (int)d.getWidth();
lastHeight = (int)d.getHeight();
}
BufferStrategy strategy = getBufferStrategy();
Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
internalPaint(g);
g.dispose();
if (!strategy.contentsLost()) strategy.show();
}
}
}
protected final StPanel canvas;
protected Timer viewTimer = new Timer(1000 / 60, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
canvas.redraw();
}
});
{
viewTimer.setRepeats(true);
viewTimer.setCoalesce(true);
}
/**
* Create the applet.
*/
public StUI2() {
JPanel panel = new JPanel(new BorderLayout());
setContentPane(panel);
panel.add(canvas = new StPanel(), BorderLayout.CENTER);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 300);
setTitle("Targetting indicator test #2");
viewTimer.start();
}
public static double unlog10(double x) {
return Math.pow(10d, x);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
StUI2 ui = new StUI2();
}
});
}
}
包st;
导入java.awt.BorderLayout;
导入java.awt.Canvas;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Font;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.GraphicsDevice;
导入java.awt.GraphicsEnvironment;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.image.BufferStrategy;
导入java.text.DecimalFormat;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
导入javax.swing.Timer;
公共类StUI2扩展了JFrame{
公共静态最终双度至弧度=Math.PI/180.0d;
公共静态最终DecimalFormat DecimalFormat=新DecimalFormat(“0.0000”);
公共静态最终字体MONO=新字体(“单间距”,Font.PLAIN,10);
公共类StPanel扩展画布{
受保护的最终对象imgLock=新对象();
受保护的int lastWidth=1,lastHeight=1;
受保护布尔值优先=真;
保护色BGCOLOR=Color.DERK_GRAY,GRIDCOLOR=Color.GRAY;
双层包装=700;
双船架=100;
双shipPos=0;
long LastUpdateTimes=-1;
长电流UpdateTimes=-1;
公共StPanel(){
设置聚焦(真);
setMinimumSize(新尺寸(1,1));
setAlwaysOnTop(真);
}
公共空间内部油漆(图形2D g){
已同步(imgLock){
if(lastUpdateTimes<0){
LastUpdateTimes=System.currentTimeMillis();
}
currentUpdateTimes=System.currentTimeMillis();
long diffMS=currenupdatetimems-lastUpdateTimeMS;
g、 setFont(MONO);
shipPos+=(60d*((双)diffMS/1000));
如果(发货位置>包裹发货){
shipPos=0d;
}
双shipPosPerc=shipPos/Shippwrap;
双distToDest=换装-换装位置;
双重压缩=1000d/distToDest;
g、 setColor(bgcolor);
维度d=getSize();
g、 fillRect(0,0,(int)d.getWidth(),(int)d.getHeight());
//int amnt2=(int)unlog10((1000d/distToDest));
g、 setColor(Color.WHITE);
g、 抽绳(“shipPos:+decimalFormat.格式(shipPos),10,10);
g、 抽绳(“distToDest:+decimalFormat.format(distToDest)),10,20;
g、 抽绳(“包裹式:”+decimalFormat.format(包裹式),150,10);
整数偏移=40;
g、 setFont(MONO);
双比例因子=10d;
双距离=0;
int curri=0;
int i=0;
做{
curri=i;
g、 setColor(Color.GREEN);
dist=distToDest-getSquareDistance(distToDest,scalingFactor,i);
双sqh=getSquareHeight(距离,100d*DEG_至_RAD);
g、 绘图线(30+(内部)距离,(偏移+50)-(内部)(sqh/2d),30+(内部)距离,(偏移+50)+(内部)(sqh/2d));
g、 setColor(颜色:浅灰色);
g、 抽绳(“i:+i+”,dist:+decimalFormat.format(dist),10120+(i*10));
i++;
}而(distdouble dist = 0;
double d1 = 10;
int curri = 0;
int i = 1;
int maxSquareHeight = 40;
double angle = Math.atan(maxSquareHeight/distToDest);
while (true)
{
curri = i;
g.setColor(Color.GREEN);
dist = getSquareDistance(d1, scalingFactor, i);
if (dist > distToDest) {
break;
}
double sqh = getSquareHeight(dist, angle);
g.drawLine(30 + (int)(shipWrap - dist), offset+50-(int)(sqh / 2d), 30 + (int)(shipWrap - dist), offset+50+(int)(sqh / 2d));
g.setColor(Color.LIGHT_GRAY);
i++;
}
public double getSquareHeight(double distance, double angle) {
return distance * Math.tan(angle);
}