我在Java Swing中遇到了一些crush事件的问题

时间:2015-12-05 18:17:34

标签: java multithreading swing crush

我使用Java Swing创建了一个简单的程序。

如果你开始,从左到右穿过画布的导弹,当你点击画布时,就会制作气球。

我在两个标签之间制作粉碎事件。但是,它不能很好地工作。 有时它运作良好,但有些气球并不认识导弹。

(对不起,我是韩国小男孩。我不太懂英语语法..)

这是我的源文件

Game2.java

public class Game2 {
public Game2(){
    JFrame jF = new JFrame();
    jF.setTitle("게임");
    jF.setDefaultCloseOperation(jF.EXIT_ON_CLOSE);
    jF.setSize(500, 500);
    jF.setVisible(true);
    MyPanel myPanel = new MyPanel();
    jF.setContentPane(myPanel);
}

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

MyPanel.java

public class MyPanel extends JPanel implements Runnable {
private ArrayList<Balloon> ballList = new ArrayList<Balloon>();
private ArrayList<Missile> misList = new ArrayList<Missile>();

public MyPanel() {
    setLayout(null);

    Thread setMissileThread = new Thread(this);
    setMissileThread.start();

}

@Override
public void run() {

    // 마우스 클릭 이벤트 처리(풍선)
    addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            super.mouseClicked(e);
            ballList.add(new Balloon(e.getX(), e.getY()));
            // System.out.println("풍선 생성");
        }
    });
    // 자동 처리(미사일)
    while (true) {
    //  synchronized(ballList){
        Missile mis;
        misList.add(mis = new Missile());
        mis.start();
        // System.out.println("미사일생성");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            return;
        }

        // 미사일 충돌

        if (!misList.isEmpty() && !ballList.isEmpty()) {
            for (Missile misArr : misList) {
                for (Balloon ballArr : ballList) {

                    Point ballPos = ballArr.getPosition();
                    Point misPos = misArr.getPosition();
                    if(ballArr.visible){System.out.println("살아있더"+ballPos.x+", "+ballPos.y);}
                    if (ballPos.x - 10 <= misPos.x + 60
                            && misPos.x + 60 <= ballPos.x + 40
                            && ballPos.y - 20 <= misPos.y + 15
                            && misPos.y + 25 <= ballPos.y + 50) {


                        //visible을 따져서 충돌 파괴모션을 설정한다.
                        if (ballArr.visible == true) {
                            ballArr.visible = false;
                            // 라벨 삭제
                            remove(misArr.missile);
                            remove(ballArr.ball);
                            repaint();
                            System.out.println("Bomb!");
                        }

                        /*
                         * //ArrayList 인덱스 삭제 misList.remove(misArr);
                         * ballList.remove(ballArr);
                         */

                    }

                }
            //}
        }

    }
    }

}

public boolean intersects(JLabel testa, JLabel testb)
{
    boolean b3 = false;
    if(testa.contains(testb.getX(), testb.getY()))
    {
        b3 = true;
    }
    return b3;
}

class Missile extends Thread {
    JLabel missile;
    int xPos, yPos;
    Random r = new Random();

    public Missile() {
        imgSetting();
        setLoc();
        repaint();

    }

    void imgSetting() {
        ImageIcon img = new ImageIcon(
                "C:/Users/JS_UbSE/Desktop/missile.png");
        Image reImg = img.getImage();
        Image changedImg = reImg.getScaledInstance(60, 30,
                java.awt.Image.SCALE_SMOOTH);
        ImageIcon IMG = new ImageIcon(changedImg);
        missile = new JLabel(IMG);
        missile.setSize(IMG.getIconWidth(), IMG.getIconHeight());
    }

    void setLoc() {
        int xPos = 0;
        int yPos = r.nextInt(500);
        missile.setLocation(xPos, yPos);
        add(missile);
        this.xPos = xPos;
        this.yPos = yPos;
        repaint();
    }

    public Point getPosition() {
        Point p = new Point();
        p.x = xPos;
        p.y = yPos;

        return p;
    }

    public void run() {

        while (xPos < 500) {
            int nextXPos = xPos + 5;
            missile.setLocation(nextXPos, yPos);
            xPos = nextXPos;
            repaint();
            try {
                Thread.sleep(25);
            } catch (InterruptedException e) {
                return;
            }
        }
        remove(missile);
        return;

    }
}

class Balloon extends Thread {
    JLabel ball;
    int xPos, yPos;
    private boolean visible;

    public Balloon(int x, int y) {
        visible = true;
        imgSetting();
        setLoc(x, y);
        repaint();
    }

    void imgSetting() {
        ImageIcon img = new ImageIcon(
                "C:/Users/JS_UbSE/Desktop/balloon.png");
        Image reImg = img.getImage();
        Image changedImg = reImg.getScaledInstance(30, 40,
                java.awt.Image.SCALE_SMOOTH);
        ImageIcon IMG = new ImageIcon(changedImg);
        ball = new JLabel(IMG);
    }

    void setLoc(int mouseX, int mouseY) {
        ball.setSize(30, 40);
        ball.setLocation(mouseX, mouseY);
        xPos = mouseX;
        yPos = mouseY;
        add(ball);
    }

    public Point getPosition() {
        Point p = new Point();
        p.x = xPos;
        p.y = yPos;
        //System.out.println(xPos + ", " + yPos);
        return p;
    }
}
}

1 个答案:

答案 0 :(得分:2)

你应该在导弹的每次移动中检测到碰撞,而不是在不同的线程上。由于您的碰撞检测线程每500毫秒运行一次,因此在此期间碰撞检测线程处于休眠状态时,一些导弹会直接穿过气球。

还可以使用

同步列表
private volatile List<Balloon> ballList = Collections
        .synchronizedList(new ArrayList<Balloon>());
private volatile List<Missile> misList = Collections
        .synchronizedList(new ArrayList<Missile>());

用户迭代器也可以删除,因为列表可以抛出ConcurrentModificatoinException。

Balloon类不需要是一个线程。

*编辑

工作代码

import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class MyPanel extends JPanel implements Runnable {
    private List<Balloon> ballList = Collections
            .synchronizedList(new ArrayList<Balloon>());
    private List<Missile> misList = Collections
            .synchronizedList(new ArrayList<Missile>());
    private ReentrantLock listLock = new ReentrantLock();

    private static final String MISSILE_IMAGE_PATH = "C:/Users/JS_UbSE/Desktop/missile.png";
    private static final String BALOON_IMAGE_PATH = "C:/Users/JS_UbSE/Desktop/balloon.png";

    public static void main(String[] args) {
        Game2.main(null);
    }

    public MyPanel() {
        setLayout(null);

        Thread setMissileThread = new Thread(this);
        setMissileThread.start();

    }

    @Override
    public void run() {

        // 마우스 클릭 이벤트 처리(풍선)
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                ballList.add(new Balloon(e.getX(), e.getY()));
                // System.out.println("풍선 생성");
            }
        });
        // 자동 처리(미사일)
        while (true) {
            // synchronized(ballList){
            Missile mis;
            listLock.lock();
            try {
                misList.add(mis = new Missile());
            } finally {
                listLock.unlock();
            }
            mis.start();
            // System.out.println("미사일생성");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                return;
            }

            // 미사일 충돌
        }

    }

    public boolean intersects(JLabel testa, JLabel testb) {
        boolean b3 = false;
        if (testa.contains(testb.getX(), testb.getY())) {
            b3 = true;
        }
        return b3;
    }

    class Missile extends Thread {

        JLabel missile;
        int xPos, yPos;
        Random r = new Random();

        public Missile() {
            imgSetting();
            setLoc();
            repaint();

        }

        void imgSetting() {
            ImageIcon img = new ImageIcon(MISSILE_IMAGE_PATH);
            Image reImg = img.getImage();
            Image changedImg = reImg.getScaledInstance(60, 30,
                    java.awt.Image.SCALE_SMOOTH);
            ImageIcon IMG = new ImageIcon(changedImg);
            missile = new JLabel(IMG);
            missile.setSize(IMG.getIconWidth(), IMG.getIconHeight());
        }

        void setLoc() {
            int xPos = 0;
            int yPos = r.nextInt(500);
            missile.setLocation(xPos, yPos);
            add(missile);
            this.xPos = xPos;
            this.yPos = yPos;
            repaint();
        }

        public Point getPosition() {
            Point p = new Point();
            p.x = xPos;
            p.y = yPos;

            return p;
        }

        public void run() {
            repaint();
            while (xPos < 500) {
                int nextXPos = xPos + 5;
                missile.setLocation(nextXPos, yPos);
                xPos = nextXPos;
                repaint();
                listLock.lock();
                try {
                    detectCollision();
                } finally {
                    listLock.unlock();
                }
                try {
                    Thread.sleep(25);
                } catch (InterruptedException e) {
                    return;
                }
            }
            remove(missile);
            listLock.lock();
            try {
                misList.remove(missile);
            } finally {
                listLock.unlock();
            }
            return;

        }
    }

    class Balloon extends Thread {
        JLabel ball;
        int xPos, yPos;
        private boolean visible;

        public Balloon(int x, int y) {
            visible = true;
            imgSetting();
            setLoc(x, y);
            repaint();
        }

        void imgSetting() {
            ImageIcon img = new ImageIcon(BALOON_IMAGE_PATH);
            Image reImg = img.getImage();
            Image changedImg = reImg.getScaledInstance(30, 40,
                    java.awt.Image.SCALE_SMOOTH);
            ImageIcon IMG = new ImageIcon(changedImg);
            ball = new JLabel(IMG);
        }

        void setLoc(int mouseX, int mouseY) {
            ball.setSize(30, 40);
            ball.setLocation(mouseX, mouseY);
            xPos = mouseX;
            yPos = mouseY;
            add(ball);
        }

        public Point getPosition() {
            Point p = new Point();
            p.x = xPos;
            p.y = yPos;
            // System.out.println(xPos + ", " + yPos);
            return p;
        }
    }

    public void detectCollision() {
        if (!misList.isEmpty() && !ballList.isEmpty()) {
            Iterator<Missile> missileIterator = misList.iterator();
            while (missileIterator.hasNext()) {
                Missile misArr = missileIterator.next();
                Iterator<Balloon> ballIterator = ballList.iterator();
                while (ballIterator.hasNext()) {
                    Balloon ballArr = ballIterator.next();
                    Point ballPos = ballArr.getPosition();
                    Point misPos = misArr.getPosition();

                    if (ballPos.x - 10 <= misPos.x + 60
                            && misPos.x + 60 <= ballPos.x + 40
                            && ballPos.y - 20 <= misPos.y + 15
                            && misPos.y + 25 <= ballPos.y + 50) {

                        if (ballArr.visible == true) {
                            ballArr.visible = false;
                            // 라벨 삭제
                            remove(misArr.missile);
                            missileIterator.remove();
                            remove(ballArr.ball);
                            ballIterator.remove();
                            repaint();
                            System.out.println("Bomb!");
                        }   
                    }
                }

            }

        }
    }
}