我正在開發一個具有 GUI 和可移動坦克的專案。雖然坦克移動得很好,但我無法弄清楚如何單獨移動/旋轉它們。我還需要清理我的代碼,因為我覺得我有很多額外的事情要做。
這是一些代碼,如果需要,我可以發布更多,但這是我嘗試過的。
我有4節課。導彈,坦克和董事會。我在 Tank 類中呼叫 keylisteners,我應該在 doDrawing 方法中這樣做嗎?doDrawing 方法在 Board 類中。
private void doDrawing(Graphics g)
{
final double rads = Math.toRadians(120);
final double sin = Math.abs(Math.sin(rads));
final double cos = Math.abs(Math.cos(rads));
final int w = (int) Math.floor(tank1.getX() * cos tank1.getX() * sin);
final int h = (int) Math.floor(tank1.getY() * cos tank1.getY() * sin);
Graphics2D g2d = (Graphics2D) g;
g2d.translate(w, h);
g2d.rotate(rot, tank1.getX(), tank1.getY());
AffineTransform backup = g2d.getTransform();
AffineTransform trans = new AffineTransform();
g2d.setTransform(backup);
//g2d.drawImage(tank1.getImage(), tank1.getX(), tank1.getY(), this);
trans.setToIdentity();
trans.rotate(rot, h, w);
trans.translate(h,w);
trans.setTransform(backup);
g2d.drawImage(tank1.getImage(), tank1.getX(), tank1.getY(), this);
//g2d.drawImage(tank1.getImage(), tank1.getX(), tank1.getY(), this);
g2d.drawImage(tank2.getImage(), tank2.getX(), tank2.getY(), this);
List<Missile> missiles = tank1.getMissiles();
for (Missile missile : missiles)
{
//trans.rotate(Math.toRadians(rads), w/2, h/2);
g2d.drawImage(missile.getImage(), missile.getX(), missile.getY() - 7, this);
//g2d.rotate(rot, missile.getX(), missile.getY() - 7);
}
}
uj5u.com熱心網友回復:
所以,只是看著...
private void doDrawing(Graphics g)
{
//...
Graphics2D g2d = (Graphics2D) g;
g2d.translate(w, h);
g2d.rotate(rot, tank1.getX(), tank1.getY());
AffineTransform backup = g2d.getTransform();
AffineTransform trans = new AffineTransform();
g2d.setTransform(backup);
//g2d.drawImage(tank1.getImage(), tank1.getX(), tank1.getY(), this);
trans.setToIdentity();
trans.rotate(rot, h, w);
trans.translate(h,w);
trans.setTransform(backup);
g2d.drawImage(tank1.getImage(), tank1.getX(), tank1.getY(), this);
g2d.drawImage(tank2.getImage(), tank2.getX(), tank2.getY(), this);
//...
}
很明顯,您正在對Graphics背景關系應用一個永遠不會撤消的轉換,因此所有繪制都將應用相同的轉換。
您需要做的第一件事是將繪制邏輯分解,以便它可以繪制單個物體。
您需要做的第二件事是在對Graphics背景關系進行任何修改之前創建背景關系的副本,這將防止父副本繼續進行這些修改,然后這些修改將與未來的修改相結合。
也許像...
private void doDrawing(Graphics g) {
// Because I don't trust anybody
Graphics2D g2d = (Graphics2D) g.create();
drawTank(tank1, g2d);
g2d.dispose();
g2d = (Graphics2D) g.create();
drawTank(tank2, g2d);
g2d.dispose();
}
private void drawTank(Tank tank, Graphics2D g) {
final double rads = Math.toRadians(120);
final double sin = Math.abs(Math.sin(rads));
final double cos = Math.abs(Math.cos(rads));
final int w = (int) Math.floor(tank.getX() * cos tank.getX() * sin);
final int h = (int) Math.floor(tank.getY() * cos tank.getY() * sin);
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(w, h);
// `rot` should be derived from the tank ... no idea where this is
g2d.translate(tank.getX(), tank.getY());
// Origin has now been translated to the tanks position
g2d.rotate(rot, 0, 0);
g2d.drawImage(tank.getImage(), 0, 0, this);
// We no longer to need to keep these resources
g2d.dispose();
// Create a new "clean" copy
g2d = (Graphics2D) g.create();
// I don't know if it's needed, but I would, personally, calculate
// any required rotation again, but that's me
List<Missile> missiles = tank1.getMissiles();
for (Missile missile : missiles) {
g2d.drawImage(missile.getImage(), missile.getX(), missile.getY() - 7, this);
}
}
例如,請參閱:
- Java - 就地旋轉影像
- 如何沿斜坡移動油漆圖形?
uj5u.com熱心網友回復:
建議:
- 使用模型視圖代碼結構將邏輯與顯示分開
- 為此,創建一個 Tank邏輯類,它知道自己的位置和方向(或角度),并將您的保存
java.util.List<Tank>在程式的模型中。 - 更改聽者內的 Tank 位置和方向。
- 僅使用 View 類(GUI 類)來 a) 繪制類模型的狀態和 b) 從用戶那里獲得輸入。
- 附帶建議:如果這是 Swing,請避免使用 KeyListeners,而是使用Key Bindings
- 您可以為每個坦克使用單獨的仿射變換
uj5u.com熱心網友回復:
如果您的坦克同步移動/旋轉,我猜原因是它們都接收相同的關鍵事件并以相同的方式做出反應。
將 keylistener (或另一個答案中建議的更好的 KeyBindings )放入您的 Board 類。偵聽器將檢查按下/釋放哪個鍵,并向正確的坦克發出移動或轉動或其他命令。這樣你就可以讓一個坦克對 WASD 做出反應,而另一個對上/下/左/右做出反應。
但是 tank 類中的方法不對關鍵事件做出反應,但可以命名為 forward、backward、turnleft、turnright。
doDrawing 方法應該正如它的名字所暗示的那樣:只執行繪圖。這可以發生任何次數以獲得良好的螢屏重繪 率或在另一個視窗不再隱藏您的游戲后重繪棋盤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/529928.html
標籤:爪哇摇摆awt
