BufferedImage,int []像素和渲染。他们如何一起工作?

时间:2013-12-31 06:08:09

标签: java rendering game-engine bufferedimage

以下代码中有一些我无法理解的内容。经过谷歌挖掘一段时间后,我觉得最好问别人。 我在youtube上关注游戏编程教程,我觉得我(在某种程度上)理解了我写的所有内容,除了涉及程序渲染部分的一些行。

package com.thomas.game;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.thomas.game.graphics.Screen;
import com.thomas.game.input.Keyboard;

public class Game extends Canvas implements Runnable {

private static final int WIDTH = 300;
private static final int HEIGHT = (WIDTH / 16) * 9;
private static final int SCALE = 3;
private static final String TITLE = "Game";

private JFrame frame;
private Thread thread;
private Screen screen;
private BufferedImage image;
private Keyboard key;

private int[] pixels;
private boolean running = false;

private int x = 0, y = 0;

public Game() {
    setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
    screen = new Screen(WIDTH, HEIGHT);
    frame = new JFrame();
    initializeFrame();
    image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

这是我不明白的。我得到了图像栅格,从中我获得了数据库。我将数据缓冲区转换为(DatabufferInt),这允许我通过int[]方法检索getData()。完成此操作后,pixel.length的值为48600,并且每个索引都包含int值0.使用此int[]进行操作会使程序按照预期进行渲染。但是,如果我没有以上述方式进行类型转换并检索int[],而是说pixels = new int[48600],我最终会出现黑屏。 我想我想知道的是:这两个int[]之间有什么区别,或者更确切地说,是什么使第一个工作?它是如何工作的?

    key = new Keyboard();
    addKeyListener(key);
    setFocusable(true);
}

public void run() {

    long lastTime = System.nanoTime();
    double nsPerTick = 1E9/60;
    double delta = 0;
    long now;
    int ticks = 0;
    int frames = 0;
    long timer = System.currentTimeMillis();

    while(running) {
        now = System.nanoTime();
        delta += (now - lastTime) / nsPerTick;
        lastTime = now;

        while(delta >= 1) {
            tick();
            ticks++;
            delta--;
        }

        render();
        frames++;

        if(System.currentTimeMillis() - timer >= 1000) {
            timer += 1000;
            frame.setTitle(TITLE + " | ups: " + ticks + " fps: " + frames);
            ticks = 0;
            frames = 0;
        }
    }
}

private void render() {

    BufferStrategy bs = getBufferStrategy(); // retrieves the bufferstrategy from the current component (the instance of Game that calls this method)
    if(bs == null) {
        createBufferStrategy(3);
        return;
    }

    screen.clear();
    screen.render(x, y);
    getPixels();
    Graphics g = bs.getDrawGraphics(); // retrieves a graphics object from the next in line buffer in the bufferstrategy, this graphics object draws to that buffer
    g.drawImage(image, 0, 0, getWidth(), getHeight(), null); // draws the bufferedimage to the available buffer
    g.dispose();
    bs.show(); // orders the next in line buffer (which the graphics object g is tied to) to show its contents on the canvas
}

private void tick() {
    key.update();
    if(key.up)
        y--;
    if(key.down)
        y++;
    if(key.left)
        x--;
    if(key.right)
        x++;
}

public void initializeFrame() {
    frame.setTitle(TITLE);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.add(this);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

public synchronized void start() {
    running = true;
    thread = new Thread(this);
    thread.start();
}

public synchronized void stop() {
    running = false;
    try {
        thread.join();
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    Game game = new Game();
    game.start();
}

public void getPixels() {
    for(int i = 0; i < pixels.length; i++)
        pixels[i] = screen.pixels[i];
}
}

似乎bufferedimage从像素数组中获取值。但我不明白这两者是如何沟通的,或者它们是如何联系的。我没有明确告诉bufferedimage从像素数组中获取像素,所以它是如何知道的? 我还将附加Screen类,它负责更新像素阵列。

package com.thomas.game.graphics;

import java.util.Random;

public class Screen {

private int width, height;
public int[] pixels;
private final int MAP_SIZE = 64;
private final int MAP_SIZE_MASK = MAP_SIZE - 1;
private int[] tiles;
private int tileIndex;
private int xx, yy;

private Random r;

public Screen(int w, int h) {

    width = w;
    height = h;
    pixels = new int[width * height];
    tiles = new int[MAP_SIZE * MAP_SIZE];
    r = new Random(0xffffff);

    for(int i = 0; i < tiles.length; i++) {
        tiles[i] = r.nextInt();
    }
    tiles[0] = 0;
}

public void clear() {
    for(int i = 0; i < pixels.length; i++)
        pixels[i] = 0;
}

public void render(int xOffset, int yOffset) {
    for(int y = 0; y < height; y++) {
        yy = y + yOffset;
        for(int x = 0; x < width; x++) {
            xx = x + xOffset;
            tileIndex = (yy >> 4 & MAP_SIZE_MASK) * MAP_SIZE + (xx >> 4 & MAP_SIZE_MASK);
            pixels[y * width + x] = tiles[tileIndex];
        }
    }
}
}

我真的希望有人可以向我解释一下,我们将不胜感激。该程序正在按照预期的方式工作,但在我掌握这一点之前,我不觉得继续学习本教程。

2 个答案:

答案 0 :(得分:1)

short,int,long等基本类型不是Objects。

但是,int []是一个数组。数组是java中的对象。 Java通过引用操作对象,而不是值。

在此行中,您不是要创建新对象。您正在变量pixels中存储对象int []的引用。您在pixels中更改的任何内容都会在image中的int []对象内更改:

pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

我创建了一个示例,尝试运行此代码:

public class Data {
    private int[] values = {25,14};

    public int[] getValues() {
        return values;
    }

    public static void main(String[] args) {
        Data d = new Data();
        System.out.println(d.getValues()[0]);

        int[] values = d.getValues();
        values[0] = 15;

        System.out.println(d.getValues()[0]);

    }
}

输出:

25
15

答案 1 :(得分:0)

请注意,您有此代码......

pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

虽然它应该是这样的......

pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();

image更改为img

希望它有效!