如何创建计时器任务的新实例而不是全部取消并重新启动它?

时间:2016-01-21 08:29:55

标签: java swing mouselistener timertask

好吧,我有一个项目,我必须在java上制作游戏。在我的游戏中,有一艘射击激光的宇宙飞船。我有或多或少想出射击激光的机制,但我目前正在使用计时器任务让激光飞过JFrame并给人一种激光拍摄的印象。

问题是,一旦我开始多次拍摄,TimerTask似乎就会出错。

主要的目标是以给定的速度在屏幕上移动对象

我能做些什么来实现这个目标吗?有没有更好的方法来实现这个? 我感谢所有得到的帮助,谢谢。 以下是一些代码:

public Space() {
        this.setBackground(Color.BLACK);
        this.setCursor(Cursor.getDefaultCursor());

        this.addMouseMotionListener(new MouseAdapter() {
            public void mouseMoved(MouseEvent e) {
                repaint();
                x = e.getX()-spaceFighterIcon.getIconHeight()/2;
                y = e.getY()-spaceFighterIcon.getIconWidth()/2;

            }
            public void mouseDragged(MouseEvent e) {
                repaint();
                x = e.getX()-spaceFighterIcon.getIconHeight()/2; //Positions the cursor on the middle of the spaceShip and viceVersa 
                y = e.getY()-spaceFighterIcon.getIconWidth()/2; 

            }
        }
        );
        this.addMouseListener(new MouseAdapter(){

            public void mousePressed(MouseEvent e) {
                if(timerRunning = true){
                laserTimer.cancel();
                laserTimer.purge();
                laserFired = false;
                }
                if(SwingUtilities.isLeftMouseButton(e)){ // Gets where the laser is going to be shot from 
                    repaint();
                    laserX = e.getX()-spaceFighterIcon.getIconWidth()/6; 
                    laserY = e.getY();
                    laserFired = true;
                }
                if(SwingUtilities.isRightMouseButton(e)){

                }
                if(SwingUtilities.isMiddleMouseButton(e)){

                }
            }
        });
    }

    public void paintComponent(Graphics g) {
        this.graphics = g;
        super.paintComponent(g);

        spaceFighterIcon.paintIcon(this, g, x, y);
        if(laserFired == true){
            shootLaser();
        }
    }
    public void shootLaser(){
        laserIcon.paintIcon(this, graphics, laserX, laserY-50); // paints the laser
        laserTimer = new Timer();
        laserTimer.schedule(new AnimateLasers(), 0, 200); // Timer to move the laser across the frame
        timerRunning = true;
        repaint();
    }
    public void lasers(){
        laserY = laserY-1; // function to move the laser 
        if(laserY <= 0){
            laserTimer.cancel();
            laserTimer.purge();
        }
    }
    public class AnimateLasers extends TimerTask {

        public void run() {
            lasers(); 
            repaint();
        }
    }

1 个答案:

答案 0 :(得分:2)

首先看看Concurrency in SwingHow to use Swing Timers,而不是java.util.Timer

Swing Timer使用Swing更安全,因为它在事件调度线程的上下文中执行它滴答

另请查看Painting in AWT and SwingPerforming Custom Painting,了解有关绘画如何运作的详细信息

不要在paint方法之外维护对Graphics上下文的引用。系统会告诉你的组件何时应该由系统自行重新绘制(通过调用paintComponent方法),实际上,你用时间来更新“激光”的位置并调用repaint ,然后在油漆系统调用时将激光绘制在paintComponent