2016-06-10 60 views
1

我正在開發一款Java遊戲,僅供學習之用。 我希望玩家選擇對象。所選對象可以移動,但其他(非選定對象)不得移動。java中的遊戲:旋轉選定的對象

Game.java:

import javax.swing.JFrame; 

public class Game { 
    public static void main(String[] args) { 
     JFrame frame = new JFrame("Kibe"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setContentPane(new GamePanel()); 

     frame.pack(); 
     frame.setVisible(true); 
    } 
} 

GamePanel.java:

import javax.swing.JPanel; 
import java.awt.*; 
import java.awt.image.*; 
import java.awt.event.*; 
import java.util.*; 

public class GamePanel extends JPanel implements Runnable, KeyListener { 
    // fields 
    public static final int WIDTH = 640, HEIGHT = 480; 

    private Thread thread; 
    private boolean running; 

    private int FPS = 30; 
    private double averageFPS; 

    private BufferedImage image; 
    private Graphics2D g; 

    public ArrayList<Circle> circles; 
    private int selectedCircle; 

    // constructor 
    public GamePanel(){ 
     super(); 
     setPreferredSize(new Dimension(WIDTH, HEIGHT)); 
     setFocusable(true); 
     requestFocus(); 
    } 
    // functions 

    public void addNotify(){ 
     super.addNotify(); 
     if(thread == null){ 
      thread = new Thread(this); 
      thread.start(); 
     } 
     addKeyListener(this); 
    } 

    public void run(){ 
     running = true; 

     image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); 
     g = (Graphics2D) image.getGraphics(); 

     circles = new ArrayList<Circle>(); 

     long startTime; 

     gameUpdate(); 
     gameRender(); 
     gameDraw(); 

     long URDTimeMillis; 
     long waitTime; 
     long totalTime = 0; 

     int frameCount = 0; 
     int maxFrameCount = 30; 

     long targetTime = 1000/FPS; 

     while(running){ // the game loop 
      startTime = System.nanoTime(); 

      gameUpdate(); 
      gameRender(); 
      gameDraw(); 

      URDTimeMillis = (System.nanoTime() - startTime)/1000000; 
      waitTime = targetTime - URDTimeMillis; 

      try{ 
       Thread.sleep(waitTime); 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 

      frameCount++; 
      if(frameCount == maxFrameCount){ 
       averageFPS = 1000.0/((totalTime/frameCount)/1000000); 
       frameCount = 0; 
       totalTime = 0; 
      } 
     } 
    } 

    private void gameUpdate(){ 
     circles.get(selectedCircle).update(); 
    } 

    private void gameRender(){ 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, WIDTH, HEIGHT); 

     for(int i = 0; i < circles.size(); i++){ 
      circles.get(i).draw(g); 
     } 
    } 

    private void gameDraw(){ 
     Graphics g2 = this.getGraphics(); 
     g2.drawImage(image, 0, 0, null); 
     g2.dispose(); 
    } 

    // key functions 
    public void keyTyped(KeyEvent e){ 
     int keyCode = e.getKeyCode(); 
    } 
    public void keyPressed(KeyEvent e){ 
     int keyCode = e.getKeyCode(); 
     if(keyCode == KeyEvent.VK_SPACE){ 
      circles.add(new Circle()); 
     } 
     else if(keyCode == KeyEvent.VK_Z){ 
      selectedCircle = (selectedCircle + 1) % circles.size(); 
     } 
    } 
    public void keyReleased(KeyEvent e){ 
     int keyCode = e.getKeyCode(); 
    } 
} 

Circle.java:

import java.awt.*; 

public class Circle { 
    // fields 
    private double x; 
    private double y; 
    private int speed; 

    private int dx; 
    private int dy; 
    private int r; 

    private boolean up; 
    private boolean down; 
    private boolean left; 
    private boolean right; 

    private Color color; 

    // constructor 
    public Circle(){ 
     x = Math.random() * GamePanel.WIDTH/2 + GamePanel.HEIGHT/4; 
     y = -r; 
     speed = 5; 

     dx = 0; 
     dy = 0; 
     r = 5; 

     color = Color.WHITE; 
    } 

    // functions 
    public void setUp(boolean b) { up = b; } 
    public void setDown(boolean b) { down = b; } 
    public void setLeft(boolean b) { left = b; } 
    public void setRight(boolean b) { right = b; } 

    public void update(){ 
     if(up) 
      dy = -speed; 
     else 
      dy = 0; 

     if(down) 
      dy = speed; 

     if(left) 
      dx = -speed; 
     else 
      dx = 0; 

     if(right) 
      dx = speed; 

     color = Color.RED; 
    } 

    public void draw(Graphics2D g){ 
     g.setColor(Color.WHITE); 
     g.fillOval((int) x - r, (int) y - r, 2 * r, 2 * r); 
    } 
} 

,當我嘗試運行錯誤:

線程「Thread-2」中的異常java.lang.IndexOutOfBoundsException:Index:0,Si ze:0 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) 在GamePanel.gameUpdate(GamePanel.java:102) 在GamePanel.run(GamePanel.java:51) 在java.lang.Thread.run(未知來源)

+1

哪一行是:'GamePanel.java:102'? –

+2

錯誤信息很清楚,你有沒有試過去理解它? –

回答

2

的錯誤信息是明確的:

IndexOutOfBoundsException: Index: 0, Size: 0 

你試圖從一個ArrayList的第一個項目e是0,這意味着沒有第0項(第一項)。

這條線:

private void gameUpdate(){ 
    circles.get(selectedCircle).update(); // here **** 
} 

這是在遊戲開始發生圓圈ArrayList中持有任何圈子對象之前。

一個解決方案是試圖提取的東西不存在,比如之前做有效性檢查,

private void gameUpdate() { 
    if (selectedCircle < circles.size()) { 
     circles.get(selectedCircle).update(); 
    } 
}  

當然,這不會阻止你很快就會與此代碼遇到其他問題包括

  • 負的Thread.sleep倍
  • 與由上Swing組件調用getGraphics()而獲得的圖形對象繪製
  • 直接從後臺線程進行Swing調用
+0

大,非常感謝。 – kibe

+1

@VitorLeal:不客氣。解決這個問題的關鍵是仔細閱讀異常堆棧跟蹤,因爲它會告訴你*什麼*錯誤,確切地說*哪裏*。如果問題在執行後仍然不清楚,那麼通過調試程序運行代碼,大多數IDE都有一個,然後在異常站點之前檢查變量**的狀態。 –

+0

很抱歉,這麼晚評論這個。 我該如何解決你說的這3個錯誤: -negative Thread。睡眠時間 - 使用通過在Swing組件上調用getGraphics()獲得的Graphics對象進行繪圖 - 直接從後臺線程進行Swing調用 – kibe