首页 > 解决方案 > 在背景上设置对象/图像的位置

问题描述

我目前正在开发 Ludo/Dude 不要生气的游戏版本,我遇到了一些问题,其中一个较大的问题是我无法将令牌放置在我想要的位置。我需要在开始时将标记设置在某些位置,并且需要一种方法来计算它们在屏幕上的移动位置,代码如下:

public class Ludo extends JFrame{

   private BackgroundPanel imagePanel=null;
   private JLabel jlTokenBlue1=null;
   private JLabel jlTokenBlue2=null;
   ...

   public Ludo(){
          try{         
         //Creating background panel  
         imagePanel = new BackgroundPanel("ludoBoard.png");
         add(imagePanel);

         //create tokens for play
         BufferedImage imageTokenBlue1 = ImageIO.read(new File("blue1.png"));
         jlTokenBlue1 = new JLabel(new ImageIcon(imageTokenBlue1));

         BufferedImage imageTokenBlue2 = ImageIO.read(new File("blue2.png"));
         jlTokenBlue2 = new JLabel(new ImageIcon(imageTokenBlue2));

         BufferedImage imageTokenBlue3 = ImageIO.read(new File("blue3.png"));
         jlTokenBlue3 = new JLabel(new ImageIcon(imageTokenBlue3));

         BufferedImage imageTokenBlue4 = ImageIO.read(new File("blue4.png"));
         jlTokenBlue4 = new JLabel(new ImageIcon(imageTokenBlue4));

         BufferedImage imageTokenRed1 = ImageIO.read(new File("red1.png"));
         jlTokenRed1 = new JLabel(new ImageIcon(imageTokenRed1));

         BufferedImage imageTokenRed2 = ImageIO.read(new File("red2.png"));
         jlTokenRed2 = new JLabel(new ImageIcon(imageTokenRed2));

         BufferedImage imageTokenRed3 = ImageIO.read(new File("red3.png"));
         jlTokenRed3 = new JLabel(new ImageIcon(imageTokenRed3));

         BufferedImage imageTokenRed4 = ImageIO.read(new File("red4.png"));
         jlTokenRed4 = new JLabel(new ImageIcon(imageTokenRed4));

         imagePanel.add(jlTokenBlue1);
         imagePanel.add(jlTokenBlue2);
         imagePanel.add(jlTokenBlue3);
         imagePanel.add(jlTokenBlue4);
         imagePanel.add(jlTokenRed1);
         imagePanel.add(jlTokenRed2);
         imagePanel.add(jlTokenRed3);
         imagePanel.add(jlTokenRed4);

         jlTokenRed1.setLocation(250,500);
         }//End of try
      catch(IOException ioe){
         System.out.println("The background image cannot be loaded...");
      }catch(NullPointerException npe){
         npe.getMessage();
      }
.
.
.
class BackgroundPanel extends JPanel
{
  Image image;
  public BackgroundPanel(String imageName)
  {
    try
    {
      image = javax.imageio.ImageIO.read(new java.net.URL(getClass().getResource(imageName), imageName));
    }
    catch (Exception e) { /*handled in paintComponent()*/ }
  }

  @Override
  protected void paintComponent(Graphics g)
  {
    super.paintComponent(g); 
    if (image != null)
      g.drawImage(image, 0,0,this.getWidth(),this.getHeight(),this);
  }
}

我尝试使用 setLocation 和 repaint,但无法将令牌设置为我想要的位置。我想将令牌以各自的颜色放入白色字段中,非常感谢任何帮助和/或建议。下面是它现在的样子的图片。如果您想自己检查文件,这里是包含所有内容的驱动器的链接。drive.google.com/open?id=1xap_xz2K3SF37XQfRN3Y_LHoTHg0HNox !

图片

标签: javauser-interfacegraphics

解决方案


我已经为你的游戏开始了一些代码。您必须完成代码。

这是我创建的 GUI。

卢多板

我做的第一件事是使用模型/视图/控制器模式。通过分离游戏的逻辑功能,我可以一次专注于一个部分。

这是我创建的模型。它不完整,但我想你可以看到我想要做的事情。我把他的类放在它自己的模型包中。

package com.ggl.ludo.model;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

public class LudoModel {

    private final BufferedImage gameBoard;

    private final BufferedImage[] imageTokenBlue;

    public LudoModel() {
        imageTokenBlue = new BufferedImage[4];
        imageTokenBlue[0] = getImage("blue1.png");
        imageTokenBlue[1] = getImage("blue2.png");
        imageTokenBlue[2] = getImage("blue3.png");
        imageTokenBlue[3] = getImage("blue4.png");
        gameBoard = getImage("ludoBoard.png");
    }

    public BufferedImage getGameBoard() {
        return gameBoard;
    }

    public BufferedImage[] getImageTokenBlue() {
        return imageTokenBlue;
    }

    private BufferedImage getImage(String fileName) {
        try {
            return ImageIO.read(getClass().getResourceAsStream("/" + fileName));
        } catch (IOException e) {
            return null;
        }
    }

}

所有这些代码都会读取图像,并最终创建游戏的逻辑模型。它根本不关心视图或控制器代码。

我创建的下一个类是 DrawingPanel 类。此类绘制游戏板,并最终在板上绘制棋子。零件信息的位置进入模型。

package com.ggl.ludo.view;

import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

import com.ggl.ludo.model.LudoModel;

public class DrawingPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private LudoFrame frame;

    private LudoModel model;

    public DrawingPanel(LudoFrame frame, LudoModel model) {
        this.frame = frame;
        this.model = model;
        int width = model.getGameBoard().getWidth();
        int height = model.getGameBoard().getHeight();
        this.setPreferredSize(new Dimension(width, height));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(model.getGameBoard(), 0, 0, this);
        // Your piece drawing code goes here
    }

}

接下来,我创建了一个类来保存 JFrame。可以删除 JScrollPane 代码。我的旧笔记本电脑无法显示和你一样大的游戏板。如果您希望其他人玩此游戏,请记住一些事情。

我把菜单代码放在它自己的方法中。我喜欢把不同的东西分开。我虚弱的头脑无法同时处理太多的进程。

package com.ggl.ludo.view;

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;

import com.ggl.ludo.model.LudoModel;

public class LudoFrame {

    private DrawingPanel drawingPanel;

    private LudoModel ludoModel;

    public LudoFrame(LudoModel ludoModel) {
        this.ludoModel = ludoModel;
        generateGUIControl();
    }

    private void generateGUIControl() {
        JFrame frame = new JFrame("Ludo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenu());

        drawingPanel = new DrawingPanel(this, ludoModel);
        JScrollPane scrollPane = new JScrollPane(drawingPanel);
        scrollPane.setPreferredSize(new Dimension(400, 400));

        frame.add(scrollPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JMenuBar createMenu() {
        JMenuBar ludoMenuBar = new JMenuBar();
        JMenu ludoMenuFirst = new JMenu("Information");
        ludoMenuBar.add(ludoMenuFirst);

        JMenuItem jmiDescription = new JMenuItem("Description");
        JMenuItem jmiHelp = new JMenuItem("Help");
        JMenuItem jmiRestart = new JMenuItem("Restart");
        JMenuItem jmiExit = new JMenuItem("Exit");

        ludoMenuFirst.add(jmiDescription);
        ludoMenuFirst.add(jmiHelp);
        ludoMenuFirst.add(jmiRestart);
        ludoMenuFirst.add(jmiExit);
        ludoMenuBar.add(ludoMenuFirst);
        return ludoMenuBar;
    }
}

最后是启动整个过程的驱动类。您必须在事件调度线程 (EDT) 上启动 Swing 应用程序。对 SwingUtilities invokeLater 的调用可确保您的应用程序在 EDT 上启动。

package com.ggl.ludo;

import javax.swing.SwingUtilities;

import com.ggl.ludo.model.LudoModel;
import com.ggl.ludo.view.LudoFrame;

public class Ludo implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Ludo());
    }

    @Override
    public void run() {
        new LudoFrame(new LudoModel());
    }
}

我希望这对你有所帮助。至于控制器,我建议您使用鼠标监听器并在游戏板上绘制游戏块。

请记住,有关游戏棋子位置的信息会进入模型。视图绘制代码从模型中的信息中提取。


推荐阅读