Hey Leuts.
Ich hab ein kleines Dirty-One-Class Experiment mit Java2D gebastelt.
Ziel war es quasi durch ein „beleuchtetes Sniper Visier“ auf eine dunkle szene zu schauen.
Dazu hab ich das Hintergrundbild und ein Overlay verwendet. Auf das overlay male ich nur einen
nur schwach transparenten schwarzen kasten, und eben das je nach sightFog transparente „Visier“,
also der Kreis durch den man auf den Hintergrund schaut. (Alles auch aus dem Code entnehmbar.)
Nun. Ich habe 2 Fragen.
Da ich momentan nur auf einem Laptop von… (1990?) „arbeiten“ kann, bin ich nicht wirklich in der lage
das objektiv zu testen. Wären vielleicht ein paar leute so freundlich das einzufügen, die beiden Bilder reinzupacken,
(blood.png und scene.jpg) und es mal zu testen, also zu sagen ob es lagt? (bei mir lagt es nur.)
Ich habe ja das java2d AlphaComposite benutzt. Und in jedem Frame, in jedem pixel des „Visierkreises“ mache ich
AlphaComposite.getInstance(). Geht das nicht auch irgendwie anders?
Gibt es weitere Dinge die man java2d performance mäßig verändern könnte?
Controls:
F11 - Vollbild an, aus
Mauslinksklick - „schiessen“
bewegen - visier bewegen
mausrad - visier größe
mausrad + strg - viesier transparenz
Die zweite Frage. Wie könnte man das in opengl implementieren? Wie könnte ich es schaffen,
(hier ja mit alpha composite und 2 bufferedimages) den hintergrund und das overlay zu trennen,
und das overlay quasi „separat zu verändern“, abgesehen davon das ich da ja nicht jedesmal die textur
ändern würde sondern es irgendwie im shader berechnen müsste… Jemand ne idee? ^^
Danke fürs lesen und eventuell ausprobieren!
Der code:
[SPOILER]
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel implements Runnable {
private BufferedImage rawSceneImage, sceneImage, overlay, blood;
private float imageAspect1, imageAspect2;
private float sniperx, snipery;
private float hiddenSceneAlpha = 0.99f;
private float sightFog = 0.0f;
private float sightValueChangeSpeed = 5.5f;
private int sightRadius = 300;
private int bloodx, bloody;
private int lastFrameWidth, lastFrameHeight, lastFramex, lastFramey;
private boolean drawBlood, ctrlPressed, fullscreen;
private Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public Main() throws Exception {
rawSceneImage = ImageIO.read(getClass().getClassLoader().getResourceAsStream("scene.jpg"));
blood = ImageIO.read(getClass().getClassLoader().getResourceAsStream("blood.png"));
imageAspect1 = (float) rawSceneImage.getWidth() / (float) rawSceneImage.getHeight();
imageAspect2 = (float) rawSceneImage.getHeight() / (float) rawSceneImage.getWidth();
sceneImage = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
overlay = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
final JFrame f = new JFrame();
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
addMouseMotionListener(new MouseMotionListener(){
public void mouseMoved(MouseEvent e){
sniperx = e.getX();
snipery = e.getY();
}
public void mouseDragged(MouseEvent e){
mouseMoved(e);
}
});
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
if(e.getButton() == MouseEvent.BUTTON1){
bloodx = e.getX();
bloody = e.getY();
drawBlood = true;
}
}
});
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_CONTROL:
ctrlPressed = true;
break;
case KeyEvent.VK_F11:
if((fullscreen = !fullscreen)){
lastFrameWidth = f.getWidth();
lastFrameHeight = f.getHeight();
lastFramex = f.getX();
lastFramey = f.getY();
f.dispose();
f.setLocation(0, 0);
f.setUndecorated(true);
f.setSize(screenSize.width, screenSize.height);
f.setVisible(true);
f.requestFocus();
requestFocus();
}
else{
f.dispose();
f.setUndecorated(false);
f.setSize(lastFrameWidth, lastFrameHeight);
f.setLocation(lastFramex, lastFramey);
f.setVisible(true);
System.out.println("reset");
}
break;
}
}
public void keyReleased(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_CONTROL:
ctrlPressed = false;
break;
}
}
});
addMouseWheelListener(new MouseWheelListener(){
public void mouseWheelMoved(MouseWheelEvent e){
if(ctrlPressed){
if((sightFog = sightFog -= (float) e.getWheelRotation() * sightValueChangeSpeed * 10) < 0){
sightFog = 0;
}
}
else{
if((sightRadius = sightRadius -= (float) e.getWheelRotation() * sightValueChangeSpeed) < 50){
sightRadius = 50;
}
}
}
});
f.addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e){
overlay = new BufferedImage(e.getComponent().getWidth(), e.getComponent().getHeight(), BufferedImage.TYPE_INT_ARGB);
sceneImage = new BufferedImage(e.getComponent().getWidth(), e.getComponent().getHeight(), BufferedImage.TYPE_INT_ARGB);
createSceneImage();
}
});
setFocusable(true);
f.add(this);
f.setVisible(true);
requestFocus();
new Thread(this).start();
}
private void createSceneImage(){
int drawWidth = (int) ((float) getHeight() * imageAspect1);
int drawHeight = getHeight();
if(drawWidth < getWidth()){
drawWidth = getWidth();
drawHeight = (int) ((float) getWidth() * imageAspect2);
}
Graphics sceneImageGraphics = sceneImage.getGraphics();
sceneImageGraphics.drawImage(rawSceneImage, 0, 0, drawWidth, drawHeight, null);
}
private void drawBlood(){
Graphics g = sceneImage.getGraphics();
g.drawImage(blood, bloodx - blood.getWidth() / 2, bloody - blood.getHeight() / 2, null);
}
public void run(){
long lastFrame = System.nanoTime();
double delta;
long thisFrame;
while(true){
thisFrame = System.nanoTime();
delta = thisFrame - lastFrame;
lastFrame = thisFrame;
repaint();
try{Thread.sleep(1);}catch(Exception e){}
}
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if(drawBlood){
drawBlood = false;
drawBlood();
}
Graphics2D overlayGraphics = (Graphics2D) overlay.getGraphics();
overlayGraphics.setComposite(AlphaComposite.Src);
overlayGraphics.setColor(new Color(0, 0, 0, 0));
overlayGraphics.fillRect(0, 0, overlay.getWidth(), overlay.getHeight());
overlayGraphics.setColor(new Color(0, 0, 0, hiddenSceneAlpha));
overlayGraphics.fillRect(0, 0, overlay.getWidth(), overlay.getHeight());
for(int i = (int) sniperx - sightRadius; i < (int) sniperx + sightRadius; i++){
for(int j = (int) snipery - sightRadius; j < (int) snipery + sightRadius; j++){
float distance = (float) new Point(i, j).distance(sniperx, snipery);
if(distance <= sightRadius){
float alpha = hiddenSceneAlpha / (sightFog + sightRadius) * (distance + sightFog);
overlayGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, alpha));
overlayGraphics.setColor(new Color(0, 0, 0, 255));
overlayGraphics.drawLine(i, j, i, j);
}
}
}
overlayGraphics.setColor(new Color(100, 0, 0, 255));
int sniperxi = (int) sniperx;
int sniperyi = (int) snipery;
overlayGraphics.drawLine(sniperxi, sniperyi - 20, sniperxi, sniperyi - 50);
overlayGraphics.drawLine(sniperxi, sniperyi + 20, sniperxi, sniperyi + 50);
overlayGraphics.drawLine(sniperxi - 20, sniperyi, sniperxi - 50, sniperyi);
overlayGraphics.drawLine(sniperxi + 20, sniperyi, sniperxi + 50, sniperyi);
for(int i = 20; i <= 50; i += 5){
int diff = (int) ((float) i * (float) i * 0.01f);
overlayGraphics.drawLine(sniperxi - diff, sniperyi - i, sniperxi + diff, sniperyi - i);
overlayGraphics.drawLine(sniperxi - diff, sniperyi + i, sniperxi + diff, sniperyi + i);
overlayGraphics.drawLine(sniperxi - i, sniperyi - diff, sniperxi - i, sniperyi + diff);
overlayGraphics.drawLine(sniperxi + i, sniperyi - diff, sniperxi + i, sniperyi + diff);
}
g2d.drawImage(sceneImage, 0, 0, null);
g2d.drawImage(overlay, 0, 0, null);
}
public static void main(String[] args) throws Exception {
new Main();
}
}
[/SPOILER]
Die Bilder die ich benutzt hab im Anhang.