我正在尝试为四人连线游戏创建 GUI,我希望筹码在掉落时呈现动画效果。我希望筹码看起来像是从没有被切掉的棋盘部分后面经过。我遇到的问题是,如果我先打印出电路板(上面有孔的那 block ),掉落的芯片就会在上面,如果我先打印出芯片,电路板就会盖住它(因为它是只是一个矩形)。有什么方法可以在不为背景图像创建一些复杂的多边形的情况下做到这一点?
这是我目前的代码:
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);
}
}
}
最佳答案
好吧,我至少可以想到两种方法,一种是创建一个 BufferedImage
并使用 AlphaComposite
在其中“戳”洞,另一种是使用 Area
并从中减去空洞...
BufferedImage
方法可以更高效,因为您只需要在需要时创建图像,但也可能有点复杂。
使用区域
这个例子演示了 Area
的使用,其中有“凹”出来的洞...
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();
}
}
}
关于java - 绘制分层形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29528056/