Chr*_*ett 11 java math applet logarithm
我正在与一些人一起制作一个3D太空交易游戏,而我被指派做的其中一件事就是制作一个引导计算机的"隧道",船只穿过,隧道由用户制成的正方形飞到目的地,随着用户离目的地越来越近.
只需渲染船前点的方块,因为这是用户可见的所有内容.在前往目的地的途中,船上的计算机应该在HUD上放置方块,这些方块代表你和目的地之间的空间中的固定点,这些点在距离很小并且随着点接近飞行器而变大.
我已经开始实现这个并且似乎无法解决这个问题,主要是使用对数(Math.log10(x)
等等).我试图在"对数空间"中获得船位,以帮助找出在绘制正方形时从哪个索引开始,但事实上我只能到目的地工作的距离混淆了这个问题,尤其是当你考虑到方块的数量必须动态变化以确保它们保持固定在空间中的正确位置(即,在以对数方式变换之前,方块以200左右的间隔定位).
关于这一点,我在0.0d的开始和1.0d的结束之间有一个工作实现,虽然实现不太好.无论如何,问题基本上归结为1d性质.对于此问题,任何建议都会受到赞赏,包括可能达到相同效果的解决方法或解决方案.
(此外,还有一个显示此效果的Youtube视频:http://www.youtube.com/watch?v = 79F9Nj7GgfM&t = 3m5s)
干杯,
克里斯
编辑:改写整个问题.
编辑:新的测试台代码:
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();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
Att*_*ila 10
假设您希望正方形高度相等(当您到达它们时),您可以根据到达目的地的距离(d
)以及到达它们时所需的正方形高度来计算缩放系数(h
).
从这两条信息中,您可以计算连接船到目的地的线(图像中的水平线)与连接方块顶部和目的地的线之间atan
的角度(alpha
)的反正切()(角线)在你的形象).
编辑:更正的
公式使用角度,您可以计算h'
距目的地任何给定距离的square()的高度:您知道到目的地的距离(d'
)和角度(alpha
); 距离处的正方形的高度d'
是h'=r'*sin(alpha)
- sin(alpha)=cos(alpha)*tan(alpha)
和r'=d'/cos(alpha)
(目的地与正方形顶部之间的距离 - "半径").或者更容易:h'=d'*tan(alpha)
.
注意:采用算法来改变高度(当你到达它们时)正方形相对简单:在计算角度时,只假设一个固定高度的(幻影)方格,并相对于那个方块缩放.
如果d'
您的图形库为您计算了距离处的正方形的高度,那么您只需要计算出放置正方形的距离.
从目的地到广场的距离是多少?
1)如果你想要显示不同数量的方块(在船前),但可能需要考虑无数个方块(基于d
),你可以选择最接近目的地d1
的距离()并计算距离通过公式得到的其他正方形s^k*k*d1
,其中s
(比例因子)是k
'th square(从目的地计数)的数> 1 .当结果大于时,您可以停止算法d
.
请注意,如果d
足够大,最接近距离的方块将阻挡目的地(由于角度较小,它们中有许多并且它们的高度很小).在这种情况下,您可以引入最小距离(可能基于d
),在此之下您不显示正方形 - 您将不得不尝试确切的值以查看正确/可接受的内容.
2)如果你想要一个固定数量的正方形(sn
)显示,无论如何d
,你可以通过公式计算方格距目的地的距离d*s^k
,其中s
数字<1,k
是方形的索引(从船).除非sn
很高,否则关于小方块的考虑可能不适用于此.
要修复更新的代码,请将relavant部件更改为:
double 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);
}
Run Code Online (Sandbox Code Playgroud)
您还应该将scalingFactor减小到~1.5的幅度.
编辑:如果更换配方s^k*k*d1
与s^(k-1)*k*d1
,然后第一方将完全在远处d1
.
编辑:固定平方高度计算公式
编辑:更新的代码
归档时间: |
|
查看次数: |
1008 次 |
最近记录: |