2

I have make a Simple program using Java Swing.

If you start, the missiles across canvas from left to right, when you click canvas the balloon is made.

I make crush event between two labels. But, It doesn't work well. Sometime It's worked well, But some Balloon doesn't cognize missile.

(..sorry i'm little the south korean boy. I don't know english grammar well..)

This is my source file


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;
    }
}
}
Claies
  • 22,124
  • 4
  • 53
  • 77
임종식
  • 21
  • 1

1 Answers1

2

You should be detecting for collision on every move of a missile not on a different thread. Since your collision detection thread runs every 500ms, some missiles just pass right through balloons as collision detection thread is sleeping during that time.

Also make your lists synchronized using

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

Also user iterator to remove as list can throw ConcurrentModificatoinException.

Balloon class doesn't need to be a thread.

*Edit

Working code

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!");
                        }   
                    }
                }

            }

        }
    }
}
11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • `private static final String MISSILE_IMAGE_PATH = "C:/Users/JS_UbSE/Desktop/missile.png";` One way to get image(s) for an example that works for everybody is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). +1 for your answer. – Andrew Thompson Dec 06 '15 at 02:34
  • Thank you so much! everybody!! I solve the problem!! – 임종식 Dec 06 '15 at 06:21