【问题标题】:Mouse Collision with JComponent and AWT MouseEvent Problem与 JComponent 和 AWT MouseEvent 问题的鼠标碰撞问题
【发布时间】:2022-01-17 02:35:07
【问题描述】:

所以我使用继承 JComponent 的名为 Ornament 的对象检测鼠标时遇到问题,并且我使用 java.awt.event.MouseEvent 获得鼠标点击。

我和我的团队最好的解决方案是比较每个饰品到鼠标的距离,如果它小于 50(这是饰品的半径),它会做一些事情。

private class ME implements MouseListener {
        @Override
        public void mouseClicked(MouseEvent e) {
            for(int i = 0; i < ORNAMENT_AMOUNT; i++) {
                Ornament current = oh.getOrnament(i);

                int distance = (int)(Math.sqrt(((e.getX() - current.getX()) * (e.getX() - current.getX())) + ((e.getY() - current.getY()) * (e.getY() - current.getY()))));
                
                if(distance <= 50) {
                    System.out.println("CIRCLE CLICKED!");
                    current.reset();
                }
            }
        }

我遇到的问题是它无法正常工作。我在同一个地方点击了很多次,最终它会在其中一个装饰品上触发事件。它随机且令人困惑。

这里是装饰类

//ornament class to define the game object ornament
public class Ornament extends JComponent{
    private int xPos;
    private int yPos;
    private int velocity;
    private int screenWidth;
    private int screenHeight;

    private Random rand;


    public Ornament(int screenWidth, int screenHeight, int velocity) {....}

    public int getY() { return yPos; }
    public int getX() { return xPos; }

    @Override
    public void paintComponent(Graphics graphics) {

        float r = rand.nextFloat();
        float g = rand.nextFloat();
        float b = rand.nextFloat();

        super.paintComponent(graphics);
        graphics.setColor(new Color(r, g, b));
        graphics.fillOval(0, 0, 50, 50);
    }

    ....

    public void reset() {
        this.yPos = -(int)(Math.random()*500);
        this.xPos = (int)(Math.random()*screenWidth);
        this.velocity += 1;
        update();
    }
}

我对此的整个方法可能是错误的,但在我的脑海中似乎是正确的,因此我们将不胜感激! :)

*note oh 是我创建的一个 objecthandler 类,用于在具有一系列装饰品的不同线程中运行游戏循环

public class ObjectHandler implements Runnable {

    private int size; 
    private Ornament[] list;

    private GUI game;

    public ObjectHandler(int size, GUI game) {
        ....
        list = new Ornament[size];

        //init object list
        for(int i = 0; i < size; i++) {
            list[i] = new Ornament(game.getFrameX(), game.getFrameY(), game.getStartingVel());
            game.add(list[i]);
        }
    }

    public Ornament getOrnament(int index) { return list[index]; }

    public void run() {
        while(true) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) { e.printStackTrace(); }

            game.loadBackground();
            for(int i = 0; i < size; i++) {

                if(list[i].getY() >= game.getFrameY())
                    list[i].reset();
                else
                    list[i].update();
            }
        }
    }
}

【问题讨论】:

  • 你在哪里添加你的MouseListener
  • Ornament 应该是一个普通的 Java getter/setter 类。你创建了一张JPanel 并在JPanel 上绘制你所有的精灵。 Oracle 教程Performing Custom Painting 将向您展示 Swing 绘图的工作原理。
  • @hfontanez 鼠标监听器在 JFrame 的构造函数中 addMouseListener(new ME());
  • 绘画方法不应该使用随机逻辑。您无法控制 Swing 何时重新绘制组件,因此您不希望绘制随机更改。您在绘画方法之外设置组件的状态。查看:stackoverflow.com/questions/67443343/drag-a-painted-shape 的示例,该示例在使用鼠标时绘制形状并支持命中检测。
  • 此外,我认为您不希望JFrame 有一个MouseListener,然后必须询问事件对象以确定哪个组件触发了事件。每个Ornament 是一个JComponent(这是一个Container),因此,每个MouseListener 都可以拥有自己的MouseListener。在我看来,这是最好的方法。每个产生的MouseEvent 都会告诉你它属于哪个Ornament 实例。

标签: java swing awt collision-detection collision


【解决方案1】:

感谢大家的帮助! 我使用 Gilbert Le Blanc 的方法来实现这一点。

我从 Ornament 类中删除了 JComponent,而是创建了一个继承 JPanel 的类

ublic class GamePanel extends JPanel{
    
    private Ornament[] objectList;
    ......
    public GamePanel(GUI game) {
        ....
        MouseListener ml = new MouseListener();
        addMouseListener(ml);
        this.setBounds(0, 0, 500, 500);
    }

然后我添加了一个绘制组件并使用 for 循环渲染 objectList 数组中的每个装饰

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

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            .....
            for(int i = 0; i < objectList.length; i++) {
                Color c = new Color(objectList[i].r, objectList[i].g, objectList[i].b);
                g2.setColor(c);
                g2.fillOval(objectList[i].getX(), objectList[i].getY(), 50, 50);
            }
        }
    }

此外,我将鼠标侦听器添加到 JPanel 组件中。使用相同的技术进行鼠标与对象的碰撞,并且成功了!

class MouseListener extends MouseAdapter
    {
        @Override
        public void mousePressed(MouseEvent e)
        {
            if(!gameOver) {
                for(int i = 0; i < objectList.length; i++) {
                    int distance = (int)(Math.sqrt(((e.getX() - objectList[i].getX()) * (e.getX() - objectList[i].getX())) + ((e.getY() - objectList[i].getY()) * (e.getY() - objectList[i].getY()))));
                    
                    if(distance <= 50) {
                        game.incScore();
                        objectList[i].reset();
                    }
                }
            ...
        }
    }

向 hfontanez 和 Gilbert Le Blanc 大声呼救! :)

【讨论】:

    猜你喜欢
    • 2012-01-20
    • 2011-01-11
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多