java中的游戏:旋转所选对象

时间:2016-06-10 23:54:49

标签: java swing game-engine

我正在开发一款仅用于学习目的的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);
    }
}

我尝试运行时出错:

  

线程中的异常&#34;线程-2&#34; java.lang.IndexOutOfBoundsException:Index:0,Si   泽:0           在java.util.ArrayList.rangeCheck(未知来源)           at java.util.ArrayList.get(Unknown Source)           在GamePanel.gameUpdate(GamePanel.java:102)           在GamePanel.run(GamePanel.java:51)           在java.lang.Thread.run(未知来源)

1 个答案:

答案 0 :(得分:2)

错误消息很明确:

IndexOutOfBoundsException: Index: 0, Size: 0

您尝试从大小为0的ArrayList中获取第0项,这意味着 没有第0项(第一项)。

这一行:

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

这是在圈子ArrayList保存任何Circle对象之前的游戏开始时发生的。

一种解决方案是在尝试提取不存在的内容之前进行有效性检查,例如,

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

当然,这不会阻止您很快遇到的其他问题,包括

  • 负Thread.sleep次
  • 使用通过在Swing组件上调用getGraphics()获得的Graphics对象进行绘制
  • 直接从后台线程进行Swing调用