Pracuję nad grą w przestrzeni 3D z niektórymi ludźmi, a jedną z rzeczy, do których zostałem przydzielony, jest stworzenie komputerowego "tunelu" prowadzącego statek przejeżdża, z tunelem wykonanym z kwadratów, które użytkownik leci do celu, zwiększając jego liczbę, gdy użytkownik zbliża się do celu.Kierowanie komputerowym symulatorem statku kosmicznego z koncentrycznymi polami wskaźnika
Konieczne jest jedynie renderowanie kwadratów dla punktów znajdujących się przed statkiem, ponieważ to wszystko jest widoczne dla użytkownika. W drodze do miejsca docelowego komputer pokładowy ma postawić kwadraty na HUD, które reprezentują stałe punkty w przestrzeni między tobą a celem, które są małe w oddali i stają się większe, gdy punkty zbliżają się do jednostki.
miałem iść na realizację tego i nie wydaje się zrozumieć to, głównie za pomocą logarytmów (Math.log10(x)
i takie). Próbowałem uzyskać pozycję statku w "przestrzeni logarytmicznej", aby dowiedzieć się, od jakiego indeksu zacząć rysowanie kwadratów, ale wtedy fakt, że mam tylko odległość do miejsca docelowego, aby pracować, myląc sprawę, zwłaszcza gdy należy wziąć pod uwagę, że liczba kwadratów musi się zmieniać dynamicznie, aby upewnić się, że są one stałe w odpowiednich miejscach w przestrzeni (tj. kwadraty są rozmieszczone w odstępach co najmniej 200, zanim zostaną przekształcone logarytmicznie).
W związku z tym miałem działającą implementację ze statkiem między początkiem 0.0d a końcem 1.0d, chociaż wdrożenie nie było takie przyjemne. W każdym razie problem zasadniczo sprowadza się do natury 1d. W tym przypadku docenimy każdą radę, w tym możliwe obejścia w celu osiągnięcia tego samego efektu lub rozwiązania.
(Również, istnieje wideo Youtube pokazujący ten efekt: http://www.youtube.com/watch?v=79F9Nj7GgfM&t=3m5s)
Wiwaty,
Chris
Edit: rephrased całą pytanie.
Edit: nowy kod testowa:
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();
}
});
}
}
1) Nie mieszać Swing ('JApplet') & AWT (' Canvas') elementy. 2) Aplet jest nieco trudniejszy do przetestowania przez innych. Rozważ użycie aplikacji hybrydowej/apletu. 3) Czy masz pytanie? Co to jest? –
OK. Uruchomiłem teraz kod. Oprócz pytania nadal nie jestem do końca jasny, co powinno się dziać. Czy czerwone i żółte kropki powinny być wyrównane? Również magenta porusza się od lewej do prawej. Czy żółty wzorzec podobno jest tym, co pilot widzi przedni oknem (będzie rzutowany na prawą ścianę z naszej perspektywy)? –
Tak, byłoby idealnie, gdyby czerwone i żółte punkty były wyrównane. Muszę stworzyć mały podsekcję czerwonych kropek, które * powinny * być żółtymi kropkami. Powinny one pozostawać w ustalonych punktach w przestrzeni na ścieżce celu związanej z odległością od celu. –