Estoy intentando crear un ciclo día / noche en un simple juego de estilo RPG con Java. He llegado a un punto en el que he incluido una superposición de color bajo alfa va a cambiar el tono con el tiempo para simular la siguiente:
// Render the overlay rectangle.
public void render(Graphics2D g) {
// Set the color to yellow with ~50% opacity.
g.setColor(new Color(255, 255, 0, 125));
// Draw the rectangle.
g.fillRect(0, 0, handler.getWidth(), handler.getHeight());
g.dispose();
}
Aunque esto funciona, me gustaría introducir los modos de fusión (es decir, sumar, restar, pantalla, luz suave) en mi código para aumentar el realismo de la / del ciclo de la noche día.
Esto es lo que he intentado, pero fue en vano:
- Investigando de JavaFX opciones de modo de fusión . No quiero cambiar a JavaFX.
- La creación de una imagen totalmente blanca que recubre la pantalla y los usos
setComposite()
ysetXORMode()
de una respuesta StackOverflow diferente . - El uso de una imagen con una
BlendingMode
ysetComposite()
del paquete org.jdesktop.swingx.graphics.BlendComposite .
Mi código deseado es algo similar a lo que sigue, pero voy a tomar lo que pueda conseguir.
public void render(Graphics2D g) {
g.setColor(new Color(255, 255, 0, 125));
g.setBlendMode(ADD);
g.fillRect(0, 0, handler.getWidth(), handler.getHeight());
g.dispose();
}
Una posibilidad para resolver esto sería para amortiguar su pantalla en un BufferedImage y luego poner en práctica sus propios métodos de dibujo (Esto definitivamente no es una forma rápida de hacer esto, ya que tira a la basura todo el hardware de aceleración. Si necesita hacer una gran pantalla esto puede ser perezoso en función de su sistema y su aplicación).:
class MyGraphics {
public enum BlendingMode {
NORMAL, ADD, …
}
public BufferedImage buffer;
private BlendingMode bm = BlendingMode.NORMAL;
private int color = 0;
public MyGraphics(BufferedImage buf) {
buffer = buf; // Initialize it with a bufferedImage of your panel size.
}
public void setBlendMode(BlendingMode b) {
bm = b;
}
private int applyBlendingMode(int imgColor1, int newColor) {
int rImg, rNew, gImg, gNew, bImg, bNew, alphaImg, alphaNew; // You can intialize those using bitshifts from the color integers.
switch(bm) {
// Implement all your blending modes here.
}
// And don't forget to return the result!
}
public void setColor(int c) {
color = c;
}
public void fillRect(int x0, int y0, int width, int height) {
for(int x = x0; x < x0+width; x++) {
for(int y = y0; y < y0+height; y++) {
buffer.setRGB(x, y, applyBlendingMode(buffer.getRGB(x, y), color));
}
}
}
}
Si el setRGB
y getRGB
están trabajando para reducir la velocidad para usted, es posible acelerarlo al trabajar directamente en la BufferedImage
matriz de datos 's ( ver aquí para más información ).
También hay que tener en cuenta, que si desea utilizar el modo de fusión normal, todavía se puede hacer de la manera normal usando buffer.getGraphics()
para conseguir su Graphics
objeto. Esto debería ser más rápido en la mayoría de los casos.
Después de que haya terminado con la implementación de sus modos de mezcla-y tal vez algunas funciones más para dibujar un rectángulo más que simplemente puede señalar a la que subyace BufferedImage
en la pantalla usandoGraphics.drawImage(buffer, 0, 0);