Pixel-Rendering/Animation Performance in BufferedImage

chpn

Neues Mitglied
Hallo,

für den beigefügten Code versuche ich eine möglichst hohe Performance zu erreichen. Gibt es Alternativen für BufferedImage oder Canvas, die mir diesbezüglich helfen würden? Wäre beispielsweise ein JComponent der Canvas vorzuziehen? Oder evtl auf JavaFX umzusteigen?

Ich bin für jegliche Anregungen und Tipps dankbar!

Gruß,

Sven


Java:
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.Canvas;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;

public class Main extends Canvas implements Runnable {

  public static final int WIDTH = 1280;
  public static final int HEIGHT = 800;

  private int xstart;
  private int ystart;
  private int xend;
  private int yend;

  private int xPos;
  private int yPos;

  private Thread thread;
  private boolean isRunning = false;
  private BufferedImage img;
  private int[] pixels;

  private int[] cells;
  private Random r;

  public Main() {
    img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

    pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
    r = new Random();
    cells = new int[pixels.length];

    for (int i = 0; i < cells.length; i++) {
      int num = r.nextInt(2);
      if (num == 0) {
        cells[i] = 0;
      } else if (num == 1) {
        cells[i] = 1;
      }
    }
    addMouseMotionListener(new MouseMotionListener() {
      public void mouseDragged(MouseEvent e) {
        xPos = e.getX();
        yPos = e.getY();
      }

      public void mouseMoved(MouseEvent e) {
      }
    });

    addMouseListener(new MouseListener() {
      public void mouseClicked(MouseEvent e) {
        xPos = e.getX();
        yPos = e.getY();

      }

      public void mousePressed(MouseEvent e) {
        xPos = e.getX();
        yPos = e.getY();

      }

      public void mouseReleased(MouseEvent e) {
        xPos = e.getX();
        yPos = e.getY();
      }

      public void mouseEntered(MouseEvent e) {
      }

      public void mouseExited(MouseEvent e) {
      }
    });
    xPos = WIDTH / 2;
    yPos = HEIGHT / 2;

    xstart = xPos - 300;
    ystart = yPos - 300;
    xend = xPos + 300;
    yend = yPos + 300;
  }

  @Override
  public void run() {
    while (isRunning) {
      render();
    }
  }

  private void start() {
    if (isRunning)
      return;
    isRunning = true;
    thread = new Thread(this);
    thread.start();
  }

  private void stop() {
    if (!isRunning)
      return;
    isRunning = false;
    try {
      thread.join();
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
  }

  private void render() {

    xstart = xPos - 100;
    ystart = yPos - 100;
    xend = xPos + 100;
    yend = yPos + 100;

    if (xstart < 0)
      xstart = 0;
    if (xstart > WIDTH)
      xstart = WIDTH;
    if (ystart < 0)
      ystart = 0;
    if (ystart > HEIGHT)
      ystart = HEIGHT;
    if (xend < 0)
      xend = 0;
    if (xend > WIDTH)
      xend = WIDTH;
    if (yend < 0)
      yend = 0;
    if (yend > HEIGHT)
      yend = HEIGHT;

    BufferStrategy bs = this.getBufferStrategy();
    if (bs == null) {
      createBufferStrategy(3);
      return;
    }
    int[] nextCells = new int[cells.length];
    for (int i = 0; i < cells.length; i++) {
      nextCells[i] = cells[i];
    }

    for (int y = ystart + 1; y < yend - 1; y++) {
      for (int x = xstart + 1; x < xend - 1; x++) {
        int index = x + y * WIDTH;
        int neighbours = 0;
        for (int j = -1; j <= 1; j++) {
          for (int i = -1; i <= 1; i++) {

            neighbours += cells[(x + i) + (y + j) * WIDTH];
          }
        }
        neighbours-=cells[index];
        
        if ((cells[index] == 1) && (neighbours < 2))
          nextCells[index] = 0;
        else if ((cells[index] == 1) && (neighbours > 3))
          nextCells[index] = 0;
        else if ((cells[index] == 0) && (neighbours == 3))
          nextCells[index] = 1;
        else
          nextCells[index] = cells[index];

      }
    }

    for (int i = 0; i < cells.length; i++) {
      if (nextCells[i] == 0) {
        pixels[i] = 0x000000;
      }
      if (nextCells[i] == 1) {
        pixels[i] = 0xffffff;
      }
      cells[i] = nextCells[i];
    }

    Graphics g = bs.getDrawGraphics();
    g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
    g.dispose();
    bs.show();
  }

  public static void main(String[] args) {
    Main main = new Main();
    JFrame frame = new JFrame();
    frame.add(main);
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(WIDTH, HEIGHT);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);
    main.start();
  }
}
 
Die Pixel einzeln setzen ist eher schlecht. Dadurch können die Bilder meist nicht optimiert werden und werden mit der CPU dargestellt.
Ich habe immer Canvas mit Volatile Images benutzt und mit createCompatibleVolatileImage die Images erstellt.
Damit kam ich bei 60 bewegenden Bildern auf über 2000 Bilder pro Sekunde.

Ansonsten kann ich dir nur empfehlen dich in eine fertige Engine einzuarbeiten. Wie zum Beispiel LWJGL, JMonkeyEngine oder Slick2D.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben