我正在尝试在2D游戏中制作手电筒效果。我的手电筒被表示为以特定角度从实体延伸的线段。手电筒可以指向任何方向。手电筒的强度也有所不同(手电筒光束的长度)。我应该如何渲染2D手电筒效果?
我有一个问题,试图找出最好(最简单?)和最灵活的方式来呈现手电筒效果。特别是平铺地图。
我能想到两种方法。但我也没办法实现它们:
- 只画平铺地图
- 覆盖屏幕,黑色质感的锥形/圆弧段的一部分,并与代码冲压孔成黑色质感。这样我可以改变洞的属性。
我很无知,从哪里开始/这些被称为/如果libGDX可以做到这一点。
我正在尝试在2D游戏中制作手电筒效果。我的手电筒被表示为以特定角度从实体延伸的线段。手电筒可以指向任何方向。手电筒的强度也有所不同(手电筒光束的长度)。我应该如何渲染2D手电筒效果?
我有一个问题,试图找出最好(最简单?)和最灵活的方式来呈现手电筒效果。特别是平铺地图。
我能想到两种方法。但我也没办法实现它们:
我很无知,从哪里开始/这些被称为/如果libGDX可以做到这一点。
第一个称为模板缓冲区。但是你会发现很难达到软效果。 - 简单。
第二个:你只需要一个光的纹理。可以绘制完全黑色的区域,重复出现在精灵周围的一个黑色精灵(左,右,上,下)。或者你可以将它与模板缓冲区混合使用。或者您可以仔细计算您的纹理坐标,并使用GL.clamp_to_edge传播所有黑色像素。根据渲染场景的方式,可以先用alpha信息渲染灯光,然后混合场景(根据dst_alpha变暗)。 - 不难实现。
第三个将着色器(GLES 2.0)的研究。您可以渲染网格来填充孔屏幕并使用一些着色器计算将其变暗。 - 这是最灵活的选择,也是最困难的(无论如何都不是火箭科学)。
有些选项比其他选项听起来更好,但是提供了您提供的信息,除此之外,我无法告诉您。从哪里开始研究,你有一个很好的起点。
**如果您选择使用纹理,请根据电池情况考虑使用几种不同的纹理。您可以稍微调整它们或调整它们,但使用不同的纹理更加灵活。
好的谢谢!我不知道模板缓冲区的东西太简单了!我决定走这条路线,并简单地绘制一个渐变黑色矩形的淡出效果。 – yahfree
如果图形元素是BufferedImage
或Graphics2D
实例,则可以这样处理它。
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class FlashLight {
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
int w = 500, h = 200;
Rectangle rect = new Rectangle(0, 0, w, h);
final BufferedImage bi = robot.createScreenCapture(rect);
final BufferedImage bi2 = FlashLight.draw(
bi, 10, 180, 420, 90, .3,
new Color(255, 255, 120, 15), new Color(0, 0, 0, 220));
final BufferedImage bi3 = FlashLight.draw(
bi, 10, 180, 420, 90, .3,
new Color(180, 250, 255, 15), new Color(0, 0, 0, 220));
Runnable r = new Runnable() {
@Override
public void run() {
JPanel gui = new JPanel(new GridLayout(3,0,2,2));
gui.add(new JLabel(new ImageIcon(bi2)));
gui.add(new JLabel(new ImageIcon(bi)));
gui.add(new JLabel(new ImageIcon(bi3)));
JOptionPane.showMessageDialog(null,gui);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
public static BufferedImage draw(
BufferedImage source,
double x1, double y1, double x2, double y2,
double beamWidth,
Color beamColor, Color darknessColor) {
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
BufferedImage bi = new BufferedImage(
source.getWidth(), source.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setRenderingHints(hints);
g.drawImage(source, 0, 0, null);
// Create a conical shape to constrain the beam
double distance = Math.sqrt(Math.pow(x1 - x2, 2d) + Math.pow(y1 - y2, 2d));
double tangent = (y2 - y1)/(x2 - x1);
double theta = Math.atan(tangent);
System.out.println(
"distance: " + distance
+ " tangent: " + tangent
+ " theta: " + theta);
double minTheta = theta + beamWidth/2;
double maxTheta = theta - beamWidth/2;
double xMin = x1 + distance * Math.cos(minTheta);
double yMin = y1 + distance * Math.sin(minTheta);
double xMax = x1 + distance * Math.cos(maxTheta);
double yMax = y1 + distance * Math.sin(maxTheta);
Polygon beam = new Polygon();
beam.addPoint((int) x1, (int) y1);
beam.addPoint((int) xMax, (int) yMax);
beam.addPoint((int) xMin, (int) yMin);
g.setColor(beamColor);
GradientPaint gp = new GradientPaint(
(int)x1,(int)y1, beamColor,
(int)x2,(int)y2, darknessColor);
g.setClip(beam);
g.setPaint(gp);
g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
// create an area the size of the image, but lacking the beam area
Area darknessArea = new Area(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
darknessArea.subtract(new Area(beam));
g.setColor(darknessColor);
g.setClip(darknessArea);
g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
// fill in the beam edges with black (mostly to smooth lines)
g.setClip(null);
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(2));
g.draw(new Line2D.Double(x1,y1,xMin,yMin));
g.draw(new Line2D.Double(x1,y1,xMax,yMax));
g.dispose();
return bi;
}
}
请[accept](http://meta.stackexchange。com/a/65088/155831)一个答案,如果它有助于解决问题。 –
你的意思是这样的吗? http://piledriverengine.com/images/flashlightBeam.png –
是的,但我想在闪光灯的“电池”死亡时加长/缩短光束。显而易见的方法是缩放图像,但在某些时候会显示地图。加上是否是一个巨大的黑色质地不好的做法? – yahfree