我正在尝试为连接四游戏创建GUI,我希望芯片在它们掉落时动画。我希望芯片看起来像是通过板子的部分后面没有被切掉。我遇到的问题是,如果我打印出电路板(带有孔的部分),首先将掉落的芯片放在它上面,如果我先打印出芯片,电路板将覆盖它(因为它是只是一个矩形)。有没有办法在不为背景图像创建复杂多边形的情况下这样做?
这是我到目前为止的代码:
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);
}
}
}
答案 0 :(得分:3)
好的,我至少有两种方法可以考虑这样做,一种方法是创建一个BufferedImage
并使用AlphaComposite
来解决问题&#34;在它的洞,另一个是使用Area
并从中减去洞......
BufferedImage
方法可以更有效,因为您只需要在需要时创建图像,但也可能有点复杂。
Area
这个例子演示了Area
的使用,它有漏洞&#34; pocked&#34;出来......
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
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();
}
}
}
答案 1 :(得分: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;
}
}
单击列以开始动画。