2016-06-10 58 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