Рисование слоистых фигур

1

Я пытаюсь создать графический интерфейс для подключения четырех игр, и я хочу, чтобы чипы оживлялись по мере их падения. Я хочу, чтобы чип выглядел так, как будто он проходит за частями платы, которые не вырезаны. Проблема, с которой я сталкиваюсь, заключается в том, что, если я распечатаю доску (часть с отверстиями в ней), сначала падающий чип будет поверх нее, и если я распечатаю чип сначала, доска покроет его (так как это просто прямоугольник). Есть ли способ сделать это без создания сложных многоугольников для фонового изображения?

Вот код, который у меня есть до сих пор:

public class ConnectFourGrid extends JPanel
{
ConnectFour game;

boolean animate = false;
int animateRow = 0;
int animateCol = 0;
int dropYPos = -30;
Timer dropTimer = new Timer(2, new animateListener());

ConnectFourGrid()
{
    this.setPreferredSize(new Dimension(ConnectFour.NUM_OF_COLUMNS * 100, ConnectFour.NUM_OF_ROWS * 100));
}

class animateListener implements ActionListener
{

    @Override
    public void actionPerformed(ActionEvent arg0) 
    {
        dropYPos += 5;

        if (dropYPos == (animateRow * 100) + 10)
        {
            dropTimer.stop();
            dropYPos = -30;
            animate = false;
        }
        repaint();
    }

}

public void setGame(ConnectFour game) { this.game = game; }
public ConnectFour getGame() { return game; }

public void animate(int row, int col)
{
    animate = true;
    animateRow = row;
    animateCol = col;
    dropTimer.start();
}

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

    for (int row = 0; row < ConnectFour.NUM_OF_ROWS; row++)
    {
        for (int col = 0; col < ConnectFour.NUM_OF_COLUMNS; col++)
        {
            g.setColor(Color.BLUE);
            g.fillRect(col * 100, row * 100, 100, 100);

            if (game.getCurrentGameState()[row][col] == 0)
                g.setColor(Color.WHITE);
            else if (game.getCurrentGameState()[row][col] == 1)
                g.setColor(Color.RED);
            else 
                g.setColor(Color.YELLOW);

            g.fillOval( col * 100 + 5, row * 100 + 10, 80, 80);

        }
    }

    if (animate)
    {
        if (game.getCurrentPlayer() == 1)
            g.setColor(Color.YELLOW);
        else
            g.setColor(Color.RED);

        g.fillOval(animateCol * 100 + 5, dropYPos, 80, 80);

    }

}

}
Теги:
user-interface
swing
paint

2 ответа

3
Лучший ответ

Хорошо, есть, по крайней мере, два способа, я могу придумать это, нужно создать BufferedImage и использовать AlphaComposite для " AlphaComposite " отверстий в нем, а другой - использовать Area и вычесть из нее отверстия...

Подход BufferedImage может быть более эффективным, так как вам нужно только создать изображение, когда оно вам нужно, но также может быть немного сложным.

Использование Area

Этот пример демонстрирует использование Area которой есть отверстия, "выбитые" из нее...

Изображение 174551

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setBackground(Color.RED);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int width = getWidth() - 20;
            int height = getHeight() - 20;

            Area area = new Area(new Rectangle(10, 10, width, height));

            int cellWidth = width / 4;
            int cellHeight = height / 4;

            for (int row = 0; row < 4; row++) {
                int yPos = 10 + (row * cellHeight);
                for (int col = 0; col < 4; col++) {
                    int xPos = 10 + (col * cellWidth);
                    area.subtract(new Area(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4)));
                }
            }

            g2d.setColor(Color.BLUE);
            g2d.fill(area);
            g2d.dispose();
        }

    }

}

Использование BufferedImage и AlphaComposite

Изображение 174551

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage buffer;

        public TestPane() {
            setBackground(Color.RED);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        public void invalidate() {
            buffer = null;
            super.invalidate();
        }

        protected BufferedImage getBoard() {

            if (buffer == null) {

                int width = getWidth() - 20;
                int height = getHeight() - 20;
                buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = buffer.createGraphics();
                g2d.setColor(Color.BLUE);
                g2d.fillRect(0, 0, width, height);

                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
                g2d.setColor(new Color(0, 0, 0, 0));
                int cellWidth = width / 4;
                int cellHeight = height / 4;

                for (int row = 0; row < 4; row++) {
                    int yPos = (row * cellHeight);
                    for (int col = 0; col < 4; col++) {
                        int xPos = (col * cellWidth);
                        g2d.fill(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4));
                    }
                }
                g2d.dispose();

            }

            return buffer;

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            BufferedImage buffer = getBoard();
            int x = (getWidth() - buffer.getWidth()) / 2;
            int y = (getHeight() - buffer.getHeight()) / 2;
            g2d.drawImage(buffer, x, y, this);
            g2d.dispose();
        }

    }

}
0

Вот несколько кодов, которые я нашел в Интернете несколько лет назад:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class CompositeBoardTest extends JFrame {
    private static int size = 400;
    private static int offset = 10;
    private static int ovalSize = size/4 - offset*2;
    private static int pos = offset/2;
    private static int incr = size/4;

    public static void main( String[] args ) throws Exception {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() { new CompositeBoardTest(); }
        } );
    }

    public CompositeBoardTest() {
        super( "CompositeBoardTest" );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        Board board = new Board();
        getContentPane().add( board );
        setSize( size, size+34 );
        setVisible( true );
    }

    static class Board extends JPanel implements ActionListener {
        private int[][] pieces = new int[4][4];
        private Piece addingPiece = null;
        private Timer pieceDropped = null;

        public Board() {
            setPreferredSize( new Dimension( size, size ) );
            setBounds( 0, 0, size, size );
//          pieceDropped = new Timer( 10, this );
            pieceDropped = new Timer( 20, this );
            addMouseListener( new MouseAdapter() {
                public void mousePressed( MouseEvent e ) {
                    int column = ( e.getPoint().x-pos )/incr;
                    addPiece( column );
                }
            });
        }

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

            Graphics2D g2d = (Graphics2D) g;
            Composite comp = g2d.getComposite();

            Dimension d = getSize();
            int w = d.width;
            int h = d.height;

            BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D gbi = buffImg.createGraphics();

            // Clear area
            g2d.setColor( Color.WHITE );
            g2d.fillRect( 0, 0, w, h );

            // Draw screen
//          gbi.setColor( Color.YELLOW );
            gbi.setColor( Color.BLUE );
            gbi.fillRect( 0, 0, w, h );

            // Draw pieces or holes
            gbi.setColor( Color.RED );
            for ( int row = 0 ; row < 4 ; row++ ) {
                for ( int column = 0 ; column < 4 ; column++ ) {
                    if ( pieces[row][column] == 1 ) {
//                      gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 1.0f ) );
                        gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ) );
                    } else {
                        gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.CLEAR, 1.0f ) );
                    }
                    gbi.fillOval( incr*column+pos, incr*row+pos, ovalSize, ovalSize );
                }
            }

            // Draw adding piece if we have it
            if ( addingPiece != null ) {
                gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_OVER, 1.0f ) );
                gbi.fillOval( addingPiece.x, addingPiece.y, ovalSize, ovalSize );
            }

            // Draws the buffered image.
            g2d.drawImage(buffImg, null, 0, 0);

            g2d.setComposite( comp );
        }

        public void addPiece( int column ) {
            if ( addingPiece == null ) {
                if ( pieces[0][column] == 0 ) {
                    addingPiece = new Piece();
                    addingPiece.row = 0;
                    addingPiece.column = column;
                    addingPiece.x = incr*column+pos;
                    addingPiece.y = 0;
                    pieceDropped.start();
                } else {
                    getToolkit().beep();
                }
            }
        }

        public void actionPerformed( ActionEvent e ) {
            if ( addingPiece != null ) {
                addingPiece.y += 5;
                int row = ( addingPiece.y - pos )/incr + 1;
                if ( row > 3 || pieces[row][addingPiece.column] == 1 ) {
                    pieces[row-1][addingPiece.column] = 1;
                    addingPiece = null;
                    pieceDropped.stop();
                }
            }
            repaint();
        }
    }

    private static class Piece {
        public int row, column, x, y;
    }
}

Нажмите на колонку, чтобы начать анимацию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню