2013-04-09 42 views
1

我正在開發R-Type的一個非常簡單的版本作爲大學的工作,但儘管它的工作,手藝速度是很慢,所以運動是醜陋的笨拙。 我用刷新方法刷新屏幕,還有其他方法或方法比它更好嗎?在主面板Java的繪畫方法的問題,可笑的刷新速度

Video of Movement

Paint方法

@Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
     RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.drawImage(fondo, 0, 0,1200,600,this); 
     pj.paint(g2); 
     g2D=g2; 

    } 

PJ的paint方法

public void paint(Graphics2D g) { 

    g.drawImage(imagen,x,y,this); 
} 

PJ的舉動方法

public void move (KeyEvent e) { 
    int dx = 0; int dy = 0; 
    int code = e.getKeyCode(); 

    switch (code) { 
    case KeyEvent.VK_Q: dy-=1; break; 
    case KeyEvent.VK_A: dy+=1; break; 
    case KeyEvent.VK_P: dx+=1; break; 
    case KeyEvent.VK_O: dx-=1; break; 
    } 

    int x = (getX()<maxX&&getX()!=0) ? getX()+dx : getX(); 
    int y = (getY()<maxY&&getY()!=0) ? getY()+dy : getY(); 

    if (getY()>=maxY||getY()==0) { 
     if (dy==+1) y=y+1; 
    } 

    setPosicion(x, y); 

} 
+0

試基準標記在主面板中的paint方法的每一步看到的是哪一部分最慢的能力回來的結果 – Stephan 2013-04-09 09:24:50

回答

2
  • 圖像0​​應該已經縮放到1200x600。
  • 我不確定,但是需要super.paint(g)?您也可以使用paintComponent

事件處理(您似乎在鍵上向下移動1個像素)必須正確完成。我會設置方向和速度(1px),並將其留給擺動計時器以進行連續移動。

重繪最好的彈性/彈性:repaint(20L)(每秒50幀); 類似按鍵事件可能與EventQueue.invokeLater(new Runnable() { ... });

特別是您可能會使用修改過的區域進行重繪。

+1

PaintComponet會是首選,但是,是的,super.paint是必需的。更好地使用Swing Timer延遲重新繪製-IMHO – MadProgrammer 2013-04-09 10:00:08

2

您可以找到類似程序here的一個很好的示例。這個例子演示瞭如何創建一個新線程,並讓該線程在主循環中進行每次迭代。

Here是關於在Java中加載遊戲圖像的另一個問題。

它看起來像鞦韆本身是非常糟糕的在遊戲中使用圖像。你可能想考慮使用更合適的庫。

+0

Swing對於大多數2D風格的遊戲都可以,唯一需要擔心的是Swing使用被動渲染過程,這意味着雖然可以請求重繪,但不能保證何時會發生重繪 – MadProgrammer 2013-04-10 00:09:16

+0

嗨那裏瘋了! :D 是的,我在Java中並沒有真正做過太多的遊戲開發,我只是在評論和其他線索中做了些什麼。他們似乎表明,儘管Swing在渲染和渲染方面可能並不特別糟糕,但它對圖像來說並不是很好。如果我沒有記錯,我認爲你可以在repaint()之前調用revalidate()來確保重繪發生... – MirroredFate 2013-04-10 00:29:39

2

下面是使用背景作爲簡單遊戲循環的簡單示例。它更新遊戲對象的狀態並計算所需的延遲以保持所需的fps。

遊戲對象(Ship)有可能加速/減速超過短時間內

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.geom.Path2D; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class AnimationTest { 

    public static void main(String[] args) { 
     new AnimationTest(); 
    } 

    public AnimationTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new GamePane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    public class GamePane extends JPanel { 

     private Ship ship; 

     public GamePane() { 

      ship = new Ship(); 
      Thread thread = new Thread(new MainLoop(this)); 
      thread.setDaemon(true); 
      thread.start(); 

      InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap am = getActionMap(); 

      // Key controls... 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upPressed"); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downPressed"); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upReleased"); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downReleased"); 

      am.put("upPressed", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        // Change the direction... 
        ship.setDirection(-1); 
        // Accelerate by 1 per frame 
        ship.setVelocity(1); 
       } 

      }); 
      am.put("downPressed", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        // Change direction 
        ship.setDirection(1); 
        // Accelerate by 1 per frame 
        ship.setVelocity(1); 
       } 

      }); 
      am.put("upReleased", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        // Deccelerate by 1 per frame 
        ship.setVelocity(-1); 
       } 

      }); 
      am.put("downReleased", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        // Deccelerate by 1 per frame 
        ship.setVelocity(-1); 
       } 

      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     public void updateState() { 
      // Update the state of the game objects. 
      // This would typically be better done in 
      // some kind of model 
      ship.update(getWidth(), getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      // Paint the game state... 
      Graphics2D g2d = (Graphics2D) g.create(); 
      ship.paint(g2d); 
      g2d.dispose(); 
     } 

    } 

    public class MainLoop implements Runnable { 

     private GamePane pane; 
     private int fps = 25; 

     public MainLoop(GamePane pane) { 
      this.pane = pane; 
     } 

     @Override 
     public void run() { 
      // Wait until the screen is ready 
      while (pane.getHeight() <= 0) { 
       try { 
        Thread.sleep(125); 
       } catch (InterruptedException ex) { 
       } 
      } 
      // Main loop 
      while (true) { 
       // Start time loop 
       long startTime = System.currentTimeMillis(); 
       // Update the game state 
       pane.updateState(); 
       // Calculate the amount of time it took to update 
       long elasped = System.currentTimeMillis() - startTime; 
       // Calculate the number of milliseconds we need to sleep 
       long sleep = Math.round((1000f/fps) - elasped); 
       pane.repaint(); 
       if (sleep > 0) { 
        try { 
         Thread.sleep(sleep); 
        } catch (InterruptedException ex) { 
        } 
       } 
      } 
     } 

    } 

    public static class Ship { 

     public static int MAX_SPEED = 8; 
     private int direction = 0; 
     private int velocity = 0; 
     private int x; 
     private int y; 
     private int speed = 0; 
     private Path2D shape; 
     private boolean initState; 

     public Ship() { 
      shape = new Path2D.Float(); 
      shape.moveTo(0, 0); 
      shape.lineTo(5, 5); 
      shape.lineTo(0, 10); 
      shape.lineTo(0, 0); 
      shape.closePath(); 
      initState = true; 
     } 

     public void setDirection(int direction) { 
      this.direction = direction; 
     } 

     public void setVelocity(int velocity) { 
      this.velocity = velocity; 
     } 

     public void update(int width, int height) { 
      if (initState) { 
       y = (height - 10)/2; 
       initState = false; 
      } else { 
       // Add the velocity to the speed 
       speed += velocity; 
       // Don't over accelerate 
       if (speed > MAX_SPEED) { 
        speed = MAX_SPEED; 
       } else if (speed < 0) { 
        speed = 0; 
       } 
       // Adjust out position if we're moving 
       if (speed > 0) { 
        y += (direction * speed); 
       } 

       // Bounds check... 
       if (y - 5 < 0) { 
        y = 5; 
       } else if (y + 5 > height) { 
        y = height - 5; 
       } 
      } 
     } 

     public void paint(Graphics2D g2d) { 
      int yPos = y - 5; 
      g2d.translate(10, yPos); 
      g2d.fill(shape); 
      g2d.translate(-10, -yPos); 
     } 

    } 

}