Java 在屏幕上放置块第2部分

Java 在屏幕上放置块第2部分,java,events,mouse,Java,Events,Mouse,好的,我已经发布了一个类似的问题,问我如何在点击鼠标时在屏幕上放置块。我已经让它工作了。这是通过一些答案的帮助以及制作一个列表来实现的,当按下鼠标按钮时,一个特定的磁贴被添加到此列表中(每个磁贴都有一个图像),然后重新绘制。现在,由于我在游戏中有多个瓷砖,我显然制作了一张草瓷砖地图。我有一个问题,当我放置一个块时,事件会注册,但它不会显示在地图上,但会显示在默认屏幕上(正常的JFrame窗口上没有任何内容)。这将允许完美的块放置,因此它们不会相互重叠 我的想法不是说当按下鼠标按钮并在鼠标坐标处绘

好的,我已经发布了一个类似的问题,问我如何在点击鼠标时在屏幕上放置块。我已经让它工作了。这是通过一些答案的帮助以及制作一个列表来实现的,当按下鼠标按钮时,一个特定的磁贴被添加到此列表中(每个磁贴都有一个图像),然后重新绘制。现在,由于我在游戏中有多个瓷砖,我显然制作了一张草瓷砖地图。我有一个问题,当我放置一个块时,事件会注册,但它不会显示在地图上,但会显示在默认屏幕上(正常的JFrame窗口上没有任何内容)。这将允许完美的块放置,因此它们不会相互重叠

我的想法不是说当按下鼠标按钮并在鼠标坐标处绘制块时,我想找到一种方法来替换瓷砖。例如,如果我运行我的游戏,我有一个10 x 10的瓷砖地图,它由草瓷砖填充,当我单击草瓷砖时,其中一个草瓷砖将被石头瓷砖替换

我想这样做的方式是-

public void mousePressed(MouseEvent e) {
            if(MouseEvent.BUTTON1 == Tile.grassTile.id) {
                tiles.add(new StoneTile(e.getX() - 16, e.getY() - 16,0));

            }

        }
我之所以想到这样做,是因为我已经为所有的tile分配了一个id,当e.getX()和e.getY()(鼠标坐标)遇到具有特定id的tile时,然后执行上面if语句中的代码。显然,这不起作用,但它是有意义的,我仍然认为这可能起作用,但我很可能错过了一些东西。我知道这不是唯一的方法,我愿意接受所有比我更好的想法

多谢各位

这是一个模拟我的游戏的可运行程序

游戏框架-

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GameFrame extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private static final String TITLE = "Tile Game"; // Game Frame Window Title

    private final JPanel gamePanel;


    public GameFrame(int width, int height) {
        gamePanel = new GamePanel(width, height);
    }


    public void createAndShow() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle(TITLE);
        add(gamePanel);
        pack();
        setVisible(true);
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GameFrame gameFrame = new GameFrame(640, 480);
                gameFrame.createAndShow();
            }
        });
    }

}
import java.awt.Rectangle;

public abstract class stoneTileAdder {

private int x, y, width, height,id;


public stoneTileAdder(int x, int y, int width, int height,int id) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.id = id;
}


public Rectangle getBounds() {
    return new Rectangle(x, y, width, height);
}
游戏面板

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList
import java.util.List;
import javax.swing.JPanel;

public class GamePanel extends JPanel {

private List<stoneTileAdder> tiles; // Stores the Tile objects to be displayed


public GamePanel(int width, int height) {
    tiles = new ArrayList<>();

    setPreferredSize(new Dimension(width, height));

    addMouseListener(new MouseListener() {

        @Override
        public void mouseReleased(MouseEvent e) {

        }

        @Override
        public void mouseClicked(MouseEvent e) {
            // Do nothing
        }

        @Override
        public void mousePressed(MouseEvent e) {
             tiles.add(new StoneTile(e.getX(), e.getY(),0));

             // Repaint the JPanel, calling paint, paintComponent, etc.
             repaint();
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // Do nothing
        }

        @Override
        public void mouseExited(MouseEvent e) {
            // Do nothing
        }
    });
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g); // Make sure you do this

    // For this example, using black as the color to draw
    g.setColor(Color.BLACK);

    // Iterate over the tile list and draw them to the JPanel
    for (stoneTileAdder tile : tiles) {
        Rectangle tileRect = tile.getBounds();
        g.fillRect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
    }
}
}
石头头像-

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GameFrame extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private static final String TITLE = "Tile Game"; // Game Frame Window Title

    private final JPanel gamePanel;


    public GameFrame(int width, int height) {
        gamePanel = new GamePanel(width, height);
    }


    public void createAndShow() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle(TITLE);
        add(gamePanel);
        pack();
        setVisible(true);
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GameFrame gameFrame = new GameFrame(640, 480);
                gameFrame.createAndShow();
            }
        });
    }

}
import java.awt.Rectangle;

public abstract class stoneTileAdder {

private int x, y, width, height,id;


public stoneTileAdder(int x, int y, int width, int height,int id) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.id = id;
}


public Rectangle getBounds() {
    return new Rectangle(x, y, width, height);
}

}

添加瓷砖的更简单方法是找到鼠标按下的组件,如下所示:

@Override
public void mousePressed(MouseEvent e) {
    Component selectedTile = findComponentAt(e.getPoint());
    if(MouseEvent.BUTTON1 == Tile.grassTile.id && selectedTile instanceof Tile) { 
        tiles.add(new StoneTile(selectedTile.getX(), selectedTile.getY(), 0));
    }
}

这将获得单击的平铺的坐标,并将一个
石头平铺放置在其正上方。

添加平铺的更简单方法是找到鼠标按下的组件,如下所示:

@Override
public void mousePressed(MouseEvent e) {
    Component selectedTile = findComponentAt(e.getPoint());
    if(MouseEvent.BUTTON1 == Tile.grassTile.id && selectedTile instanceof Tile) { 
        tiles.add(new StoneTile(selectedTile.getX(), selectedTile.getY(), 0));
    }
}


这将获取单击的平铺的坐标,并将一个
石头平铺放置在其正上方。

只获取单击的平铺位置,而不是鼠标位置,然后将其替换为石头平铺,不是更好吗?另外,请给出一个可编译的示例。不是你的整个程序,只是一个我们可以修复的可运行示例。在你的鼠标压缩方法中:if(MouseEvent.BUTTON1){if(鼠标位置在块的边界内){tiles.add(new StoneTile();}}}}或者更好,只需更改已经存在的块的ID。@KylonTyner我喜欢简单地获取块的边界的想法,但我该如何在if声明中说明这一点。因为获取边界是一个矩形。@CodeLife如果网格大小固定,只需除以网格大小(使用整数除法)。因此,如果网格位于位置(1,2)且网格大小为16,则网格的“像素角点”将位于(16,32)、(16,47)、(31,47)和(31,32)。如果您单击点(18,35)并将两者除以16,您将得到(1,2)。我希望这是有意义的。@CodeLife你能发布你的Tile类吗?这是我唯一能解决你问题的方法。点击瓷砖的位置,而不是鼠标位置,然后用石头瓷砖替换,不是更好吗?另外,请给出一个可编译的示例。不是你的整个程序,只是一个我们可以修复的可运行示例。在你的鼠标压缩方法中:if(MouseEvent.BUTTON1){if(鼠标位置在块的边界内){tiles.add(new StoneTile();}}}}或者更好,只需更改已经存在的块的ID。@KylonTyner我喜欢简单地获取块的边界的想法,但我该如何在if声明中说明这一点。因为获取边界是一个矩形。@CodeLife如果网格大小固定,只需除以网格大小(使用整数除法)。因此,如果网格位于位置(1,2)且网格大小为16,则网格的“像素角点”将位于(16,32)、(16,47)、(31,47)和(31,32)。如果您单击点(18,35)并将两者除以16,您将得到(1,2)。我希望这是有意义的。@CodeLife你能发布你的Tile类吗?这是我解决您问题的唯一方法。“0”指的是互动程序id。我可以问一下centerPanel的功能和功能吗?我测试了你的代码,中心面板用红色下划线。如果我给您一个可运行的示例,您将需要许多类(如果不是全部的话),仅仅提供一个或两个类来运行是不可能的。如果这就是你的意思,对不起,如果我误解了。@CodeLife嘿CodeLife!谢谢你的反馈<代码>中心面板
仅指您将瓷砖放入的任何面板。它是父对象(平铺是子对象)。只需将centerPanel更改为添加瓷砖的位置即可。我刚刚意识到面板名称是
tiles
,如果我是正确的话。我已经编辑了我的帖子,现在应该可以了。您可能仍然需要修改它。@CodeLife(cont.)“可运行示例”我不是指程序的缩短版本,只是尝试制作一个针对您的问题的示例程序。只需制作一个可以添加瓷砖且尽可能简单的。要获得更多帮助,请访问:我已经添加了一个可运行的示例,我希望它足够了!谢谢你的帮助@CodeLife表示此行中有错误:
Tile selectedfile=(Tile)findComponentAt(e.getPoint())尝试将其更改为
Tile selectedTile=findComponentAt(e.getPoint())我还编辑了我的帖子。“0”指的是互动程序id。我可以问一下centerPanel的功能和功能吗?我测试了你的代码,中心面板用红色下划线。如果我给您一个可运行的示例,您将需要许多类(如果不是全部的话),仅仅提供一个或两个类来运行是不可能的。如果这就是你的意思,对不起,如果我误解了。@CodeLife嘿CodeLife!谢谢你的反馈<代码>中心面板
仅指