清晰的图形部分与底层图像

我正在制作各种各样的“游戏”,玩家必须点击在屏幕上弹跳的图像。 问题是屏幕处于黑暗中,鼠标光标是一个“闪光灯”,它“点亮”它周围的一个小圆圈。

我在一个类中有一个JFrame ,包括:

 public class GameFrame { public static void main(String[] args) throws IOException { Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); JFrame jf = new JFrame("Flashlight Game"); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setSize(d); jf.setLocationRelativeTo(null); GamePanel gp = new GamePanel(); jf.add(gp); } 

}

我有另一个extends JPanel类。 以下是与我的问题相关的字段:

 private Point mouse; //location set by a MouseMotionListener private BufferedImage myImage; private int imageX; private int imageY; private int imageSpeedX; private int imageSpeedY; 

我的第一个问题在于手电筒。 在我的paint方法中,我将图形背景颜色设置为面板背景颜色,并使用clearRect方法清除鼠标光标周围的区域。

 public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; super.paint(g2); checkBounce(); move(); g2.drawImage(myImage, imageX, imageY, null); g2.setColor(Color.BLACK); g2.fillRect(0, 0, this.getWidth(), this.getHeight()); g2.setBackground(Color.WHITE); g2.clearRect((int) mouse.getX() - 25, (int) mouse.getY() - 25, 50, 50); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } repaint(); } 

这里实际上有两个问题。 1.)如何创建一个clearOval效果,因为手电筒不会在矩形中发光,以及2.)如何通过手电筒光束显示弹跳图像? 我知道调用g2.setBackground(Color.WHITE)将使用设置颜色作为清除区域的“背景”,但我需要一种方法来清除除最后面的JFrameJPanel背景颜色之外的所有图形。

我的最后一个问题是奇怪的,但偶尔当我更改int的值时,窗口将显示为空白,需要在任何代码执行之前resize。

基本思想是创建一个足以覆盖组件的Rectangle ,创建一个Ellipse2D作为“洞”或“聚光灯”,并从Rectangle减去Ellipse2D ,以便在其中创建一个洞,然后绘制它。

  • 你应该尽可能避免覆盖paint ,而是使用paintComponent ,油漆链中的油漆往往会很高,并且会出现一些最好避免的复杂情况
  • 您应该避免在任何paintXxx方法中更改组件或模型的状态。 可以出于多种原因调用Paint,其中许多原因都不会实例化。 这可能会使您的模型处于不一致状态。 相反,你应该使用类似javax.swing.Timer东西来规范模型何时更新,并简单地调用repaint
  • 不要在Event Dispatching Thread的上下文中调用Thread.sleepThreasd.wait或执行任何类型的长时间运行循环或I / O操作。 Swing是一个单线程环境。 也就是说,UI和事件处理的所有更新都是在单个线程内完成的。 如果您执行任何阻止EDT的操作,它将无法处理这些事件并更新UI,直到您停止阻止…
  • 不要在paintXxx方法中调用repaint或任何可能从内部调用重绘的方法。 这会让你的程序陷入死亡之中,看到它消耗你的CPU ……

有关详细信息,请查看…

  • 执行自定义绘画
  • Swing中的并发性

在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Spotlight { public static void main(String[] args) { new Spotlight(); } public Spotlight() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public static final int RADIUS = 80; private BufferedImage img; private Point mousePoint; public TestPane() { try { img = ImageIO.read(new File("C:\\hold\\thumbnails\\Rampage_Small.png")); } catch (IOException ex) { Logger.getLogger(Spotlight.class.getName()).log(Level.SEVERE, null, ex); } addMouseMotionListener(new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { mousePoint = e.getPoint(); repaint(); } }); } @Override public Dimension getPreferredSize() { return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (img != null) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); int x = (getWidth() - img.getWidth()) / 2; int y = (getHeight() - img.getHeight()) / 2; g2d.drawImage(img, x, y, this); x = mousePoint == null ? getWidth() / 2 : mousePoint.x; y = mousePoint == null ? getHeight() / 2 : mousePoint.y; Rectangle rect = new Rectangle(0, 0, getWidth(), getHeight()); Ellipse2D spot = new Ellipse2D.Float( (float) x - (RADIUS / 2f), (float) y - (RADIUS / 2f), (float) RADIUS, (float) RADIUS); Area area = new Area(rect); area.subtract(new Area(spot)); g2d.setColor(Color.BLACK); g2d.fill(area); g2d.dispose(); } } } }