代码之家  ›  专栏  ›  技术社区  ›  Spencer Lutz

Java中BuffereImage的问题

  •  0
  • Spencer Lutz  · 技术社区  · 7 年前

    我正在制作一个游戏(就像文明一样),它有不同的瓷砖类型,我想将其渲染为图像。我有9个不同的16x16 png图像要加载(称为Con1、Con2等),下面是我的图像加载代码:(img[]是我的BuffereImage数组)

    public void loadImages(){
            for(int i = 0; i < 9; i++){
                try {
                    img[i] = ImageIO.read(this.getClass().getResource("Con"+i+".png"));
                }catch (Exception ex) {
                    System.out.println("Missing Image");
                    ex.printStackTrace();
                }
            }
        }
    

    然后,我用以下代码绘制这些图像:(t[][]是我的平铺类型数组)

    public void paint(Graphics g){
            if(loop){
                BufferedImage B = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
                Graphics r = B.getGraphics();
                for (int x = 0; x < WIDTH; x++){
                    for (int y = 0; y < HEIGHT; y++){
                        if(i[x][y] == 0){
                            if (t[x][y] == 0){
                                g.drawImage(img[0], x, y, this);
                            }
                            else if(t[x][y] == 1){
                                g.drawImage(img[1], x, y, this);
                            }
                            else if(t[x][y] == 3){
                                g.drawImage(img[3], x, y, this);
                            }
                            else if(t[x][y] == 4){
                                g.drawImage(img[4], x, y, this);
                            }
                            else if(t[x][y] == 5){
                                g.drawImage(img[5], x, y, this);
                            }
                        }
                        r.fillRect(x*SCALE, y*SCALE, SCALE, SCALE);
                    }
                }
    
                g.drawImage(B, 0, 22, this);
            }
        }
    

    enter image description here

    //imports
    import java.awt.Graphics;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    
    public class MCVCon extends JFrame implements KeyListener, MouseListener{
        //setting up variables
        public BufferedImage[] img = new BufferedImage[9];
        private final int WIDTH = 50, HEIGHT = 50;
        private boolean loop = false;
        private int SCALE = 16;
        int t[][] = new int[WIDTH][HEIGHT]; //terrain type (since I took out the terrain generation it is set to 0 or ocean)
        public MCVCon(){
            //creating the window
            super("Conqueror");
            setSize(SCALE*WIDTH, SCALE*HEIGHT+22);
            setVisible(true);
            requestFocusInWindow();
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            loadImages();
            loop = true;
            while(true){
                this.repaint();
                //delay for repaint
                try{
                    Thread.sleep(50);
                }
                catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }
        //load images
        public void loadImages(){
            for(int i = 0; i < 9; i++){
                try {
                    img[i] = ImageIO.read(this.getClass().getResource("Con"+i+".png"));
                }catch (Exception ex) {
                    System.out.println("Missing Image");
                    ex.printStackTrace();
                }
            }
        }
        //paint the images
        public void paint(Graphics g){
            if(loop){
                BufferedImage B = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
                Graphics r = B.getGraphics();
                for (int x = 0; x < WIDTH; x++){
                    for (int y = 0; y < HEIGHT; y++){
                        if (t[x][y] == 0){
                            g.drawImage(img[0], x, y, this);
                        }
                        else if(t[x][y] == 1){
                            g.drawImage(img[1], x, y, this);
                        }
                        r.fillRect(x*SCALE, y*SCALE, SCALE, SCALE);
                    }
                }
    
                g.drawImage(B, 0, 22, this);
            }
        }
        //run the program
        public static void main(String[] args) {
            new MCVCon();
        }
        //necessary overrides
        @Override
        public void keyTyped(KeyEvent e) {
        }
    
        @Override
        public void keyPressed(KeyEvent e) {
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
        }
    
        @Override
        public void mouseEntered(MouseEvent e) {
        }
    
        @Override
        public void mouseExited(MouseEvent e) {
        }
    }
    

    我想知道可能是什么问题。提前谢谢。

    1 回复  |  直到 7 年前
        1
  •  3
  •   MadProgrammer    7 年前

    所以,我看了一下你的代码,没有简单的方法可以说,但这是一个混乱的局面,复杂的问题使得很难找出任何一个问题的根源,除了说,它们都相互影响。

    让我们从这幅画开始。。。

    你直接在画框上画画。由于许多原因,通常不鼓励这样做。

    JFrame 不是一个单一的成分,它是由许多复合成分组成的

    JRootPane

    这使得直接绘制具有固有的危险性,因为任何一个子组件都可以在没有框架的情况下绘制 paint

    setSize(SCALE*WIDTH, SCALE*HEIGHT+22);
    

    建议您尝试对此进行补偿,但这是“猜测”工作,因为根据系统的配置,装饰可能会占用更多或更少的空间

    您创建了一个 BufferdImage 并将其指定为 Graphics 上下文t r

    BufferedImage B = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics r = B.getGraphics();
    

    g ,这是 图样 传递给的上下文 油漆

    g.drawImage(img[0], x, y, this);
    

    BufferedImage 油漆

    甚至不要让我开始“主绘制循环”

    t

    最后,我认为这实际上是你的问题,关于缩放。有很多方法可以应用缩放,可以在加载瓷砖时预缩放瓷砖,这使您可以控制瓷砖的缩放方式,但会将您锁定在单个比例中。

    或者你可以简单地扩展 直接连接上下文。

    现在,我根据您的代码创建了一个简单的示例,对上述大部分内容进行了更正。它创建了一系列10x10像素的随机彩色矩形,而不是平铺,但概念是相同的。

    import java.awt.Color;
    import java.awt.Dimension;
    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.geom.AffineTransform;
    import java.awt.image.BufferedImage;
    import java.util.Random;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class MCVCon extends JFrame {
        //setting up variables
    
        public MCVCon() {
            //creating the window
            super("Conqueror");
            add(new GamePane());
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    MCVCon frame = new MCVCon();
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
        //necessary overrides
    
        public class GamePane extends JPanel {
    
            public BufferedImage[] img = new BufferedImage[9];
            private final int width = 5, height = 5;
            private int scale = 16;
            int t[][] = new int[width][height]; //terrain type (since I took out the terrain generation it is set to 0 or ocean)
            Color[] colors = new Color[]{
                Color.RED,
                Color.BLUE,
                Color.CYAN,
                Color.DARK_GRAY,
                Color.GRAY,
                Color.GREEN,
                Color.LIGHT_GRAY,
                Color.MAGENTA,
                Color.ORANGE,
                Color.PINK,
                Color.YELLOW
            };
            int tileHeight = 10;
            int tileWidth = 10;
    
            public GamePane() {
                loadImages();
    
                Random rnd = new Random();
                for (int y = 0; y < height; y++) {
                    for (int x = 0; x < width; x++) {
                        int value = rnd.nextInt(9);
                        System.out.println(value + "- " + colors[value]);
                        t[x][y] = value;
                    }
                }
    
                Timer timer = new Timer(50, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        repaint();
                    }
                });
                timer.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(width * tileWidth * scale, height * tileHeight * scale);
            }
    
            public void loadImages() {
                for (int i = 0; i < 9; i++) {
                    try {
                        img[i] = new BufferedImage(tileWidth, tileHeight, BufferedImage.TYPE_INT_RGB);
                        Graphics2D g2d = img[i].createGraphics();
                        g2d.setColor(colors[i]);
                        g2d.fill(new Rectangle(0, 0, tileWidth, tileHeight));
                        g2d.dispose();
                    } catch (Exception ex) {
                        System.out.println("Missing Image");
                        ex.printStackTrace();
                    }
                }
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setTransform(AffineTransform.getScaleInstance(scale, scale));
                for (int x = 0; x < width; x++) {
                    for (int y = 0; y < height; y++) {
                        g2d.drawImage(img[t[x][y]], x * tileWidth, y * tileHeight, this);
                    }
                }
                g2d.dispose();
            }
    
        }
    }