【问题标题】:How to drop a ball when clicked with mouse?用鼠标点击时如何丢球?
【发布时间】:2014-05-24 17:43:44
【问题描述】:

我正在开发一个游戏项目。目标是点击球并将它们放入JPanel下方的篮子中。我创造了一些方法来做到这一点,但我无法实现。在我看来,当用户在有误差的情况下单击球的中心时(因为程序无法捕捉到球的真实点),程序会理解动作并运行此问题的功能。点击球后,它应该直接落下,但其他球应该继续。我使用MouseListener#mousePressed 方法,但它不起作用或者我缺少一些部分。另外,我对源代码做了一些修改,但是我想听听大家的建议,所以我写了这个话题。

我写了一个查找鼠标和球坐标的方法。因此,当我对其进行一些更改时,我可以实现我的项目目标。你可以看到图片中的编辑。

这是我的源代码;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Game {

public Game() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager
                        .getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException
                    | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            JFrame frame = new JFrame("MultipleBallApp");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new BallControl());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

public class BallControl extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private BallPanel ballPanel = new BallPanel();
    private JButton Suspend = new JButton("Suspend");
    private JButton Resume = new JButton("Resume");
    private JButton Add = new JButton("+1");
    private JButton Subtract = new JButton("-1");
    private JScrollBar Delay = new JScrollBar();

    public BallControl() {
        // Group buttons in a panel
        JPanel panel = new JPanel();
        panel.add(Suspend);
        panel.add(Resume);
        panel.add(Add);
        panel.add(Subtract);

        // Add ball and buttons to the panel
        ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
        Delay.setOrientation(JScrollBar.HORIZONTAL);
        ballPanel.setDelay(Delay.getMaximum());
        setLayout(new BorderLayout());
        add(Delay, BorderLayout.NORTH);
        add(ballPanel, BorderLayout.CENTER);
        add(panel, BorderLayout.SOUTH);

        this.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mousePressed(MouseEvent clickEvent) {
                // TODO Auto-generated method stub

                System.out.println("X coordinate =" + clickEvent.getX());
                System.out.println("Y coordinate = " + clickEvent.getY());

                double radius1;
                int x = 0;
                double y = 0;
                int radius = 15;
                double xM = clickEvent.getX();
                double yM = clickEvent.getY();

                radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y)
                        * (yM - y));
                System.out.println("Radius1 =" + radius1);
                // ballPanel.list.get(0).setD
            }

            @Override
            public void mouseExited(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseClicked(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }
        });
        // Register listeners
        Suspend.addActionListener(new Listener());
        Resume.addActionListener(new Listener());
        Add.addActionListener(new Listener());
        Subtract.addActionListener(new Listener());
        Delay.addAdjustmentListener(new AdjustmentListener() {

            public void adjustmentValueChanged(AdjustmentEvent e) {
                ballPanel.setDelay(Delay.getMaximum() - e.getValue());
            }
        });
    }

    class Listener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == Suspend) {
                ballPanel.suspend();
            } else if (e.getSource() == Resume) {
                ballPanel.resume();
            } else if (e.getSource() == Add) {
                ballPanel.add();
            } else if (e.getSource() == Subtract) {
                ballPanel.subtract();
            }
        }
    }
}

class BallPanel extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int delay = 30;
    public ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
    private AnimatedRectange rectangle;

    public BallPanel() {
        this.rectangle = new AnimatedRectange(-25, 373, 50, 25, Color.BLACK);

        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    // Create a timer with the initial delay
    protected Timer timer = new Timer(delay, new ActionListener() {
        /**
         * Handle the action event
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            for (AnimatedShape ball : list) {
                ball.update(getBounds());
            }
            rectangle.update(getBounds());
            repaint();
        }
    });

    public void add() {
        int radius = 15;
        // Randomised position
        int x = (int) (Math.random() * (getWidth() - (radius * 2)))
                + radius;
        int y = (int) (Math.random() * (getHeight() - (radius * 2)))
                + radius;
        Color color = new Color((int) (Math.random() * 256),
                (int) (Math.random() * 256), (int) (Math.random() * 256));

        AnimatedBall ball = new AnimatedBall(x, y, radius, color);

        list.add(ball);
    }

    // public void formula(MouseEvent clickEvent) {
    // double radius1;
    // int x = 0;
    // double y = 0;
    // int radius = 15;
    // double xM = clickEvent.getX();
    // double yM = clickEvent.getY();

    // radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y) * (yM - y));
    // System.out.println("Radius1 =" + radius1);

    // }

    public void subtract() {
        if (list.size() > 0) {
            list.remove(list.size() - 1); // Remove the last ball
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        for (AnimatedShape ball : list) {
            ball.paint(this, g2d);
        }
        rectangle.paint(this, g2d);
    }

    public void suspend() {
        timer.stop();
    }

    public void resume() {
        timer.start();
    }

    public void setDelay(int delay) {
        this.delay = delay;
        timer.setDelay(delay);
    }
}

public interface AnimatedShape {

    public void update(Rectangle bounds);

    public void paint(JComponent parent, Graphics2D g2d);
}

public abstract class AbstractAnimatedShape implements AnimatedShape {

    private Rectangle bounds;
    private int dx, dy;

    public AbstractAnimatedShape() {
    }

    public void setBounds(Rectangle bounds) {
        this.bounds = bounds;
    }

    public Rectangle getBounds() {
        return bounds;
    }

    public int getDx() {
        return dx;
    }

    public int getDy() {
        return dy;
    }

    public void setDx(int dx) {
        this.dx = dx;
    }

    public void setDy(int dy) {
        this.dy = dy;
    }

    @Override
    public void update(Rectangle parentBounds) {// ball
        Rectangle bounds = getBounds();
        int dx = getDx();
        int dy = getDy();
        bounds.x += dx;
        bounds.y += dy;
        if (bounds.x < parentBounds.x) {
            bounds.x = parentBounds.x;
            setDx(dx *= -1);
        } else if (bounds.x + bounds.width > parentBounds.x
                + parentBounds.width) {
            bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
            setDx(dx *= -1);
        }
        if (bounds.y < parentBounds.y) {
            bounds.y = parentBounds.y;
            setDy(dy *= -1);
        } else if (bounds.y + bounds.height > parentBounds.y
                + parentBounds.height) {
            bounds.y = parentBounds.y
                    + (parentBounds.height - bounds.height);
            setDy(dy *= -1);
        }
    }
}

public class AnimatedBall extends AbstractAnimatedShape {

    private Color color;

    public AnimatedBall(int x, int y, int radius, Color color) {
        setBounds(new Rectangle(x, y / 2, radius * 2, radius * 2));
        this.color = color;
        setDx(Math.random() > 0.5 ? 2 : -2);
        // setDy(Math.random() > 0.5 ? 2 : -2);
    }

    public Color getColor() {
        return color;
    }

    @Override
    public void paint(JComponent parent, Graphics2D g2d) {
        Rectangle bounds = getBounds();
        g2d.setColor(getColor());
        g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
    }
}

public class AnimatedRectange extends AbstractAnimatedShape {

    private Color color;

    public AnimatedRectange(int x, int y, int width, int height, Color color) {
        setBounds(new Rectangle(x, y, width, height));
        this.color = color;
        setDx(2);
    }

    // Don't want to adjust the vertical speed
    @Override
    public void setDy(int dy) {
    }

    @Override
    public void paint(JComponent parent, Graphics2D g2d) {
        Rectangle bounds = getBounds();
        g2d.setColor(color);
        g2d.fill(bounds);
    }

}

/**
 * Main method
 */
public static void main(String[] args) {
    new Game();
}
}

【问题讨论】:

  • @MadProgrammer 你对此有什么想法吗?
  • @usama8800 你对这个问题有什么想法吗?
  • 这里没有人可以帮助我吗?
  • 遵循 Java 命名约定。变量名不应以大写字符开头。顺便说一句,人们在有时间的时候会回答问题。期望在您发布问题后几分钟内得到答复是不合理的。
  • 好的,我明白@camickr。谢谢。

标签: java swing actionlistener graphics2d


【解决方案1】:

在你的mousePressed方法结束时,你可以遍历所有AnimatedShape对象,检查它们是否是AnimatedBall。当物体为球时,可以测试鼠标点击是否击中球。当球中心与鼠标位置之间的距离小于球半径时,鼠标点击击中球。当球被击中时,可以设置它的水平速度为0,垂直速度为5左右。

for (AnimatedShape as : ballPanel.list)
{
    if (as instanceof AnimatedBall)
    {
        AnimatedBall ball = (AnimatedBall)as;
        Rectangle b = ball.getBounds();
        int ballCenterX = b.x + b.width / 2;
        int ballCenterY = b.y + b.height / 2;
        Point p = new Point(ballCenterX, ballCenterY);
        double d = p.distance(clickEvent.getPoint());
        if (d < radius)
        {
            ball.setDx(0);
            ball.setDy(5);
        }
    }
}

注意

为了使其正常工作,您必须将此侦听器附加到 ballPanel。原来,你有这条线

this.addMouseListener(new MouseListener() {

在您的代码中。您必须将其更改为

ballPanel.addMouseListener(new MouseListener() {

否则鼠标坐标会引用错误的组件!


关于评论中的问题

当 clickedball 崩溃时,我如何停止和消除它们

您可能会插入方法来检查这一点,并在您的timeractionPerformed 方法中调用此方法。进一步的解释可能超出了问答网站上分析器的范围。 Stackoverflow 不是家庭作业解决方案生成器。

【讨论】:

  • 我阅读了你对代码的解释。我根据你的建议编辑了我的代码。但我不明白我将如何处理你的“注释”部分。你能更广泛地解释一下吗?代码方式?顺便说一句,当他们崩溃绑定时,我怎样才能停止和消除clickedball?我可以使用新的 stop 方法和 dissapper 方法吗?
  • 我知道 StackoverFlow 不是家庭作业解决方案生成器,但我提出了一些想法来找到解决方案,但我无法翻译成代码。顺便说一句,谢谢您的建议。
猜你喜欢
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 2011-11-21
  • 1970-01-01
相关资源
最近更新 更多