2017-07-19 27 views
1

第一篇文章,所以我會盡量保持清晰。 基本上,我想要做的是創建一個小遊戲,你有一艘船,你可以從它射擊子彈。船使用切線公式相應地旋轉到玩家的DeltaX和DeltaY。我使用的是標準的遊戲循環像這樣的:一個對象中的圖形正在影響另一個對象的圖形 - JAVA

public void run() { 
    long lastTime = System.nanoTime(); 
    double amountOfTicks = 60.0; 
    double ns = 1000000000/amountOfTicks; 
    double delta = 0; 
    long timer = System.currentTimeMillis(); 
    @SuppressWarnings("unused") 
    int frames = 0; 
    while(running){ 
     long now = System.nanoTime(); 
     delta += (now - lastTime)/ns; 
     lastTime = now; 
     while(delta >=1){ 
       tick(); 
       delta--; 
      } 
     if(running) 
     repaint(); 
     frames++; 

     if(System.currentTimeMillis() - timer > 1000) 
     { 
      timer += 1000; 
      frames = 0; 
     } 
    } 
    stop(); 
} 

我的「遊戲」運行在一個JPanel,一個名爲董事會類的子類。在循環中,我調用更新信息的方法tick()和repaint(),該方法用作渲染方法。這是我的paintComponent(Graphics g)方法:

public void paintComponent(Graphics g) { 
    //This is for background 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.setColor(Color.black); 
    g2d.fill(new Rectangle(0, 0, Constants.width, Constants.height)); 

    //This is where actual game rendering occurs 
    handler.render(g); 
    g.dispose(); 
} 

可以看出,我沒有渲染我的Board類中的所有東西。我對我的處理程序這樣做。這是我如何處理處理程序:

public void render(Graphics g) { 
    for (int i = 0; i < handlerList.size(); i++) { 
     //handlerList is a LinkedList 
     handlerList.get(i).render(g); 
    } 
} 

LinkedList handlerList包含實體。 實體是一個抽象類,它是玩家和子彈的父親的生物的父親。 這是一個播放器實例的渲染代碼:其跟蹤的對象條件

public void render(Graphics g) {   
    float centerX = x + (width/2); 
    float centerY = y + (height/2); 

    double theta = findAngle(deltaX, deltaY); 

    Graphics2D g2d = (Graphics2D) g; 
    if(!stopped) g2d.rotate(theta, centerX, centerY); 
    else g2d.rotate(stoppedTheta, centerX, centerY); 
    g2d.drawImage(shipImage, (int)x, (int)y, (int)width, (int)height, null); 
} 

有一個布爾「停止」。由於我希望能夠旋轉我的飛船,因此我使用Graphics2D而不是Graphics。

下面是子彈的渲染代碼:

public void render(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 

    g2d.setColor(Color.yellow); 
    g2d.fillOval((int)x, (int)y, (int)width, (int)height); 
} 

它看起來正確的,據我所知。每當我沒有子彈,遊戲運行良好,你可以看到在this GIF: 免責聲明:抱歉低質量和水印,我剛格式化電腦,沒有時間安裝適當的東西。 ...

當我添加一顆子彈this發生:

x和子彈不會改變的y位置,但子彈與船舶旋轉。我假設它與濫用「dispose()」方法有關,但我不確定可以採取什麼措施來修復它。

預先感謝您。

+0

開始'的Graphics2D G2D =(Graphics2D的)克;''到的Graphics2D G2D =(Graphics2D的)g.create();' - 你不應該調用'在沒有創建的上下文中處置 – MadProgrammer

+0

如果修改上下文的轉換,則必須撤消該上下文,方法是創建上下文的快照並在完成上下文處理時進行處理,或手動對其進行處理並記住,轉換正在複合 – MadProgrammer

+0

作爲一般技巧,我會在它返回之前每次調用'render'方法和'g2d.dispose()'之前調用'Graphics2D g2d =(Graphics2D)g',因爲我不相信其他的人們可能會這樣做;) - 這意味着每個對象將獲得它自己的'Graphics'上下文的快照 – MadProgrammer

回答

1
  1. 永遠不要叫disposeGraphics環境下,你沒有明確地創建(或快照與create),這可能進一步導致問題下來渲染管線。
  2. Graphics是一個共享的情境,因此你需要銘記的你做出的一些修改和撤消你做任何「顯著」的轉變,特別是轉化

如果是我,我想創建一個每次調用render和它的後dispose以前Graphics上下文的快照,例如

public void render(Graphics g) { 
    for (int i = 0; i < handlerList.size(); i++) { 
     //handlerList is a LinkedList 
     Graphics2D g2d = (Graphics2D)g.create(); 
     handlerList.get(i).render(g2d); 
     g2d.dispose(); 
    } 
} 

這確保了什麼都改變了render使得該Graphics上下文之前的下一個元素是被撤銷呈現

如果更改複合,那麼我會在循環開始之前創建快照,然後在它之後創建快照。

無論在哪種情況下,這意味着您可以控制所做的更改以及它們如何影響其他元素。

此外,請記住,轉換是通過改變混合

相關問題