Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不喜欢直线的区域生成_Java_Image_Awt_Java 2d - Fatal编程技术网

Java 不喜欢直线的区域生成

Java 不喜欢直线的区域生成,java,image,awt,java-2d,Java,Image,Awt,Java 2d,我在用java制作的JRPG游戏中使用区域生成和绘图代码为瓷砖精灵创建碰撞区域——这不是一个主要的成熟游戏,更多的只是一个概念证明供我学习 除直线外,区域生成工作正常: 这些图像是在photoshop中打开的碰撞轮廓(背景)和java代码基于红色生成的区域(前景)。如图所示,第一幅图中的大红线不会被画出来,除非每2个像素下有一个红色像素,如第二幅图所示 我没有对代码做任何更改(除了添加注释以更好地理解它),除了删除 Graphics2D g = imageOutline.createGrap

我在用java制作的JRPG游戏中使用区域生成和绘图代码为瓷砖精灵创建碰撞区域——这不是一个主要的成熟游戏,更多的只是一个概念证明供我学习

除直线外,区域生成工作正常:

这些图像是在photoshop中打开的碰撞轮廓(背景)和java代码基于红色生成的区域(前景)。如图所示,第一幅图中的大红线不会被画出来,除非每2个像素下有一个红色像素,如第二幅图所示


我没有对代码做任何更改(除了添加注释以更好地理解它),除了删除

Graphics2D g = imageOutline.createGraphics();
//...
g.dispose();
从areaOutline绘制代码中,将其替换为我自己的Graphics2D变量。我测试了这两行代码和没有这两行代码,我看不出有什么区别

我有点纠结于是什么导致了这个问题——这不是一个重大的破坏游戏的问题,因为我可以用几种方法解决它,但这确实意味着我必须向任何人解释这个问题,当我向他们展示如何使用他们自己的精灵纹理时


我已经为这个问题创建了一个SSCCE,它显示了生成的区域有很好的垂直线,但水平线没有。它拍摄两幅图像——都是一个30x30像素的正方形,但其中一幅每2秒有一个内部像素,从而生成更精确的区域

当您按键时,程序将在两个图像(及其区域)之间切换,以便进行直接比较

以下两个图像必须放在程序的根文件夹中

您可以通过运行“main”方法启动程序

import java.awt.*;
导入javax.swing.*;
导入java.awt.event.*;
导入java.awt.image.*;
导入java.awt.geom.*;
导入java.io.*;
导入javax.imageio.*;
公共类AreaOutlineCanvas扩展JFrame实现KeyListener
{
私人图像面板图像面板;
/**
*类骨架对象的构造函数
*/
公共区域大纲
{
//初始化实例变量
addKeyListener(此);
initUI();
}
公共静态void main(字符串[]args)
{
for(字符串s:args)
{
系统输出打印项次;
}
SwingUtilities.invokeLater(新的Runnable()
{
@凌驾
公开募捐
{
AreaOutlineCanvas aOC=新的AreaOutlineCanvas();
aOC.pack();
aOC.setVisible(真);
aOC.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
} );
}
私有void initUI()
{
imagePanel=新的imagePanel();
setPreferredSize(新尺寸(100100));
setLocationRelativeTo(空);
添加(图像面板);
imagePanel.setDoubleBuffered(真);
包装();
}
@凌驾
public void keyTyped(KeyEvent e)
{
}
@凌驾
按下公共无效键(按键事件e)
{
//@TODO:切换状态检查菜单框架是否在(当前菜单)
如果(imagePanel!=null)
{
imagePanel.bDrawingFirstArea=!imagePanel.bDrawingFirstArea;
imagePanel.repaint();
}
}
@凌驾
公共无效密钥已释放(密钥事件e)
{
//System.out.println(“密钥释放:“+e.getKeyChar()+”(“+e.getKeyCode()+”));
}
公共类ImagePanel扩展了JPanel
{
/**此角色精灵表位置的路径*/
私有字符串firstPath=“square1.png”;
私有字符串secondPath=“square2.png”;
私有缓冲区映像firstImage;
私有缓冲区映像二次映像;
私家区;
私人区域;
公共布尔值bDrawingFirstArea=true;
/**
*类字符对象的构造函数
*/
公众影像小组()
{
loadImages();
generateAreas();
}
私有void loadImages()
{
尝试
{
firstImage=ImageIO.read(新文件(firstPath));
secondImage=ImageIO.read(新文件(secondPath));
}
捕获(IOE异常)
{
e、 printStackTrace();
}
}
私有无效生成器EAS()
{
颜色c=新颜色(255,0,0);
firstImageArea=getOutline(c,firstImage);
secondImageArea=getOutline(c,secondImage);
}
公共区域getOutline(颜色目标、BuffereImage bi){
//构造通用路径
GeneralPath gp=新的GeneralPath();
布尔控制=假;
int targetRGB=target.getRGB();

对于(int xx=0;xx那么上面的图像就是你想要的,而第二个图像就是你得到的?你能把原始图像嵌入问题中吗?@AndrewThompson我不太确定你所说的原始图像是什么意思。上面的图像是我想要的,但只能通过每2个像素在长红线下添加一个像素来获得。第二个图像是我的原始图像没有生成直线的图像。你可能会困惑地认为背景中的红线是放大的-它们是在photoshop中打开的图像,用于与区域生成中概述的内容进行比较-我将更新我的问题以反映that@AndrewThompson经过更多测试和实施碰撞检测后问题似乎只是在于绘制区域——它是以正确的形状生成的,但不是以正确的形状绘制的,这远不是一个简单的问题concern@AndrewThompson我仍然有这个问题,我之前的说法是错误的——没有画出这个区域
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

import java.awt.image.*;
import java.awt.geom.*;

import java.io.*;
import javax.imageio.*;

public class AreaOutlineCanvas extends JFrame implements KeyListener
{
    private ImagePanel imagePanel;

    /**
     * Constructor for objects of class Skeleton
     */
    public AreaOutlineCanvas()
    {
        // initialise instance variables   
        addKeyListener( this );
        initUI();
    }

    public static void main( String[] args )
    {
        for( String s: args )
        {
            System.out.println( s );
        }

        SwingUtilities.invokeLater( new Runnable()
            {
                @Override
                public void run()
                {
                    AreaOutlineCanvas aOC = new AreaOutlineCanvas();
                    aOC.pack();
                    aOC.setVisible( true );
                    aOC.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                }

            } );
    }

    private void initUI()
    {
        imagePanel = new ImagePanel();
        setPreferredSize( new Dimension( 100, 100 ) );

        setLocationRelativeTo( null );        

        add( imagePanel );

        imagePanel.setDoubleBuffered( true );

        pack();
    }

    @Override
    public void keyTyped( KeyEvent e )
    {

    }

    @Override
    public void keyPressed( KeyEvent e )
    {
        //@TODO: switch statment checking the menu Skeleton is in (currentMenu)
        if( imagePanel != null )
        {
            imagePanel.bDrawingFirstArea = !imagePanel.bDrawingFirstArea;
            imagePanel.repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e)
    {
        //System.out.println( "Key released: " + e.getKeyChar() + " (" + e.getKeyCode() + ")" );
    }

    public class ImagePanel extends JPanel
    {
        /** Path for the location of this charactors sprite sheet */
        private String firstPath = "square1.png";
        private String secondPath = "square2.png";

        private BufferedImage firstImage;
        private BufferedImage secondImage;

        private Area firstImageArea;
        private Area secondImageArea;

        public boolean bDrawingFirstArea = true;

        /**
         * Constructor for objects of class Character
         */
        public ImagePanel()
        {
            loadImages();
            generateAreas();
        }

        private void loadImages()
        {
            try
            {
                firstImage = ImageIO.read( new File( firstPath ) );
                secondImage = ImageIO.read( new File( secondPath ) );
            }
            catch( IOException e )
            {
                e.printStackTrace();
            }
        }

        private void generateAreas()
        {
            Color c = new Color( 255, 0, 0 );
            firstImageArea = getOutline( c, firstImage );
            secondImageArea = getOutline( c, secondImage );
        }

        public Area getOutline(Color target, BufferedImage bi) {
            // construct the GeneralPath
            GeneralPath gp = new GeneralPath();

            boolean cont = false;
            int targetRGB = target.getRGB();
            for (int xx=0; xx<bi.getWidth(); xx++) {
                for (int yy=0; yy<bi.getHeight(); yy++) {
                    if (bi.getRGB(xx,yy)==targetRGB) {
                        if (cont) {
                            gp.lineTo(xx,yy);
                            gp.lineTo(xx,yy+1);
                            gp.lineTo(xx+1,yy+1);
                            gp.lineTo(xx+1,yy);
                            gp.lineTo(xx,yy);
                        } else {
                            gp.moveTo(xx,yy);
                        }
                        cont = true;
                    } else {
                        cont = false;
                    }
                }
                cont = false;
            }
            gp.closePath();

            // construct the Area from the GP & return it
            return new Area(gp);
        }

        @Override
        public void paintComponent( Graphics g )
        {                
            super.paintComponent( g );
            drawImages(g);
        }   

        private void drawImages( Graphics g )
        {
            Graphics2D g2d = (Graphics2D) g;

            if( bDrawingFirstArea )
            {
                g2d.drawImage( firstImage, 50, 0, this );
                g2d.draw( firstImageArea );
            }
            else
            {
                g2d.drawImage( secondImage, 50, 0, this );
                g2d.draw( secondImageArea );
            }

            Toolkit.getDefaultToolkit().sync();
        }
    }
}
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

/* Gain the outline of an image for further processing. */
class ImageOutline {

    private BufferedImage image;

    private TwoToneImageFilter twoToneFilter;
    private BufferedImage imageTwoTone;
    private JLabel labelTwoTone;

    private BufferedImage imageOutline;
    private Area areaOutline = null;
    private JLabel labelOutline;

    private JLabel targetColor;
    private JSlider tolerance;

    private JProgressBar progress;
    private SwingWorker sw;

    public ImageOutline(BufferedImage image) {
        this.image = image;
        imageTwoTone = new BufferedImage(
            image.getWidth(),
            image.getHeight(),
            BufferedImage.TYPE_INT_RGB);
    }

    public void drawOutline() {
        if (areaOutline!=null) {
            Graphics2D g = imageOutline.createGraphics();
            g.setColor(Color.WHITE);
            g.fillRect(0,0,imageOutline.getWidth(),imageOutline.getHeight());

            g.setColor(Color.RED);
            g.setClip(areaOutline);
            g.fillRect(0,0,imageOutline.getWidth(),imageOutline.getHeight());
            g.setColor(Color.BLACK);
            g.setClip(null);
            g.draw(areaOutline);

            g.dispose();
        }
    }

    public Area getOutline(Color target, BufferedImage bi) {
        // construct the GeneralPath
        GeneralPath gp = new GeneralPath();

        boolean cont = false;
        int targetRGB = target.getRGB();
        for (int xx=0; xx<bi.getWidth(); xx++) {
            for (int yy=0; yy<bi.getHeight(); yy++) {
                if (bi.getRGB(xx,yy)==targetRGB) {
                    if (cont) {
                        gp.lineTo(xx,yy);
                        gp.lineTo(xx,yy+1);
                        gp.lineTo(xx+1,yy+1);
                        gp.lineTo(xx+1,yy);
                        gp.lineTo(xx,yy);
                    } else {
                        gp.moveTo(xx,yy);
                    }
                    cont = true;
                } else {
                    cont = false;
                }
            }
            cont = false;
        }
        gp.closePath();

        // construct the Area from the GP & return it
        return new Area(gp);
    }

    public JPanel getGui() {
        JPanel images = new JPanel(new GridLayout(2,2,2,2));
        JPanel  gui = new JPanel(new BorderLayout(3,3));

        JPanel originalImage =  new JPanel(new BorderLayout(2,2));
        final JLabel originalLabel = new JLabel(new ImageIcon(image));
        targetColor = new JLabel("Target Color");
        targetColor.setForeground(Color.RED);
        targetColor.setBackground(Color.WHITE);
        targetColor.setBorder(new LineBorder(Color.BLACK));
        targetColor.setOpaque(true);

        JPanel controls = new JPanel(new BorderLayout());
        controls.add(targetColor, BorderLayout.WEST);
        originalLabel.addMouseListener( new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent me) {
                originalLabel.setCursor(
                    Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
            }

            @Override
            public void mouseExited(MouseEvent me) {
                originalLabel.setCursor(Cursor.getDefaultCursor());
            }

            @Override
            public void mouseClicked(MouseEvent me) {
                int x = me.getX();
                int y = me.getY();

                Color c = new Color( image.getRGB(x,y) );
                targetColor.setBackground( c );

                updateImages();
            }
        });
        originalImage.add(originalLabel);

        tolerance = new JSlider(
            JSlider.HORIZONTAL,
            0,
            255,
            104
            );
        tolerance.addChangeListener( new ChangeListener() {
            public void stateChanged(ChangeEvent ce) {
                updateImages();
            }
        });
        controls.add(tolerance, BorderLayout.CENTER);
        gui.add(controls,BorderLayout.NORTH);

        images.add(originalImage);

        labelTwoTone = new JLabel(new ImageIcon(imageTwoTone));

        images.add(labelTwoTone);

        images.add(new JLabel("Smoothed Outline"));

        imageOutline = new BufferedImage(
            image.getWidth(),
            image.getHeight(),
            BufferedImage.TYPE_INT_RGB
            );

        labelOutline = new JLabel(new ImageIcon(imageOutline));
        images.add(labelOutline);

        updateImages();

        progress = new JProgressBar();

        gui.add(images, BorderLayout.CENTER);
        gui.add(progress, BorderLayout.SOUTH);

        return gui;
    }

    private void updateImages() {
        if (sw!=null) {
            sw.cancel(true);
        }
        sw = new SwingWorker() {
            @Override
            public String doInBackground() {
                progress.setIndeterminate(true);
                adjustTwoToneImage();
                labelTwoTone.repaint();
                areaOutline = getOutline(Color.BLACK, imageTwoTone);

                drawOutline();

                return "";
            }

            @Override
            protected void done() {
                labelOutline.repaint();
                progress.setIndeterminate(false);
            }
        };
        sw.execute();
    }

    public void adjustTwoToneImage() {
        twoToneFilter = new TwoToneImageFilter(
            targetColor.getBackground(),
            tolerance.getValue());

        Graphics2D g = imageTwoTone.createGraphics();
        g.drawImage(image, twoToneFilter, 0, 0);

        g.dispose();
    }

    public static void main(String[] args) throws Exception {
        int size = 150;
        final BufferedImage outline =
            new BufferedImage(size,size,BufferedImage.TYPE_INT_RGB);
        Graphics2D g = outline.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0,0,size,size);
        g.setRenderingHint(
            RenderingHints.KEY_DITHERING,
            RenderingHints.VALUE_DITHER_ENABLE);
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        Polygon p = new Polygon();
        p.addPoint(size/2, size/10);
        p.addPoint(size-10, size-10);
        p.addPoint(10, size-10);
        Area a = new Area(p);

        Rectangle r = new Rectangle(size/4, 8*size/10, size/2, 2*size/10);
        a.subtract(new Area(r));

        int radius = size/10;
        Ellipse2D.Double c = new Ellipse2D.Double(
            (size/2)-radius,
            (size/2)-radius,
            2*radius,
            2*radius
            );
        a.subtract(new Area(c));

        g.setColor(Color.BLACK);
        g.fill(a);

        ImageOutline io = new ImageOutline(outline);

        JFrame f = new JFrame("Image Outline");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(io.getGui());
        f.pack();
        f.setResizable(false);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }
}

class TwoToneImageFilter implements BufferedImageOp {

    Color target;
    int tolerance;

    TwoToneImageFilter(Color target, int tolerance) {
        this.target = target;
        this.tolerance = tolerance;
    }

    private boolean isIncluded(Color pixel) {
        int rT = target.getRed();
        int gT = target.getGreen();
        int bT = target.getBlue();
        int rP = pixel.getRed();
        int gP = pixel.getGreen();
        int bP = pixel.getBlue();
        return(
            (rP-tolerance<=rT) && (rT<=rP+tolerance) &&
            (gP-tolerance<=gT) && (gT<=gP+tolerance) &&
            (bP-tolerance<=bT) && (bT<=bP+tolerance) );
    }

    public BufferedImage createCompatibleDestImage(
        BufferedImage src,
        ColorModel destCM) {
        BufferedImage bi = new BufferedImage(
            src.getWidth(),
            src.getHeight(),
            BufferedImage.TYPE_INT_RGB);
        return bi;
    }

    public BufferedImage filter(
        BufferedImage src,
        BufferedImage dest) {

        if (dest==null) {
            dest = createCompatibleDestImage(src, null);
        }

        for (int x=0; x<src.getWidth(); x++) {
            for (int y=0; y<src.getHeight(); y++) {
                Color pixel = new Color(src.getRGB(x,y));
                Color write = Color.BLACK;
                if (isIncluded(pixel)) {
                    write = Color.WHITE;
                }
                dest.setRGB(x,y,write.getRGB());
            }
        }

        return dest;
    }

    public Rectangle2D getBounds2D(BufferedImage src) {
        return new Rectangle2D.Double(0, 0, src.getWidth(), src.getHeight());
    }

    public Point2D getPoint2D(
        Point2D srcPt,
        Point2D dstPt) {
        // no co-ord translation
        return srcPt;
    }

    public RenderingHints getRenderingHints() {
        return null;
    }
}