Java 2D Scrolling - фон не отображается

1

Я пытаюсь создать прокручивающую игру - где игрок (в пространстве) постоянно находится в центре экрана. Когда он перемещается слева направо вверх и вниз, фоновый спрайт будет случайным образом генерировать цветные звезды, поэтому движущиеся звезды будут индикацией того, в каком направлении движется игрок.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что звезды не отображаются, когда я запускаю игру. Каждая плитка должна быть 32x32, каждая из которых содержит по крайней мере одну звезду, а плитка "nostars" пуста. Когда я запускаю игру, я просто получаю черный экран.

RandomLevel.java:

protected void generateLevel() {
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            bgtiles[x + y * width] = random.nextInt(4);
        }
    }
}

Level.java

public void render(int xScroll, int yScroll, Screen screen) {
    screen.setOffset(xScroll, yScroll);

    int x0 = xScroll >> 5;
    int x1 = (xScroll + screen.width + 32) >> 5;
    int y0 = yScroll >> 5;
    int y1 = (yScroll + screen.height + 32) >> 5;

    for(int y = y0; y < y1; y++) {
        for(int x = x0; x < x1; x++) {
            getTile(x, y).render(x, y, screen);
        }
    }
}
public Tile getTile(int x, int y) {
if(x < 0 || y < 0 || x >= width || y >= height) return Tile.nostars;
    if(bgtiles[x + y * width] == 0) return Tile.stars1;
    if(bgtiles[x + y * width] == 1) return Tile.stars2;
    if(bgtiles[x + y * width] == 2) return Tile.stars3;
    if(bgtiles[x + y * width] == 3) return Tile.stars4;

    else return Tile.nostars;
}

SpaceTile.java

public class SpaceTile extends Tile {

   public SpaceTile(Sprite sprite) {
    super(sprite);
}

public void render(int x, int y, Screen screen) {
    screen.renderTile(x << 5, y << 5, this);
}

}

SpriteSheet.java

public static SpriteSheet bgtiles = new SpriteSheet("/textures/bgsheet.png", 256);

Sprite.java

public static Sprite spaceSprite = new Sprite(32, 0, 0, SpriteSheet.bgtiles);
public static Sprite stars1 = new Sprite(64, 0, 0, SpriteSheet.bgtiles);
public static Sprite stars2 = new Sprite(96, 0, 0, SpriteSheet.bgtiles);
public static Sprite stars3 = new Sprite(128, 0, 0, SpriteSheet.bgtiles);
public static Sprite stars4 = new Sprite(160, 0, 0, SpriteSheet.bgtiles);

Tile.java

public class Tile {

public int x, y;
public Sprite sprite;

public static Tile nostars = new SpaceTile(Sprite.spaceSprite);
public static Tile stars1 = new SpaceTile(Sprite.stars1);
public static Tile stars2 = new SpaceTile(Sprite.stars2);
public static Tile stars3 = new SpaceTile(Sprite.stars3);
public static Tile stars4 = new SpaceTile(Sprite.stars4);

public Tile(Sprite sprite) {
    this.sprite = sprite;
}

public void render(int x, int y, Screen screen) {   
}

public boolean solid() {
    return false;
}

}

Game.java

public class Game extends Canvas implements Runnable { 
private static final long serialVersionUID = 1L;

public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;

public static String title = "Game";

private Thread thread;
private JFrame frame;
private Keyboard key;
private Level level;
private boolean running = false;

private Screen screen;

private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

public Game() {
    Dimension size = new Dimension(width * scale, height * scale);
    setPreferredSize(size);

    screen = new Screen(width, height);
    frame = new JFrame();
    key = new Keyboard();
    level = new RandomLevel(64, 64);

    addKeyListener(key);
}

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

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

public void run() {
    double ns = 1000000000.0 / 60.0;
    double delta = 0;

    int frames = 0;
    int updates = 0;

    long lastTime = System.nanoTime();
    long timer = System.currentTimeMillis();

    requestFocus();

    while (running) {
        long now = System.nanoTime();

        delta += (now - lastTime) / ns;
        lastTime = now;

        while(delta >= 1) {
            update();
            updates++;
            delta--;
        }

        render();
        frames++;

        if(System.currentTimeMillis() - timer >= 1000) {
            timer += 1000;
            frame.setTitle(title + "  |  " + updates + " ups, " + frames + " fps");
            frames = 0;
            updates = 0;
        }
    }

    stop();
}

int x, y = 0;

public void update() {
    key.update();
    if(key.up == true) y--;
    if(key.down == true) y++;
    if(key.left == true) x--;
    if(key.right == true) x++;
}

public void render() {
    BufferStrategy bs = getBufferStrategy();
    if (bs == null) {
        createBufferStrategy(3);
        return;
    }

    screen.clear();
    level.render(x, y, screen);

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

    Graphics g = bs.getDrawGraphics();
    g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
    g.dispose();
    bs.show();
}

public static void main(String[] args) {
    Game game = new Game();
    game.frame.setResizable(false);
      game.frame.setTitle(Game.title);
      game.frame.add(game);
      game.frame.pack();
      game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      game.frame.setLocationRelativeTo(null);
      game.frame.setVisible(true);

    game.start();
}

}

bgsheet.png https://i.imgur.com/0yUKql2.png?1

В generatelevel() я только пробовал его с помощью первых 4 плиток, а не из всех 64-х плит.

Когда я запускаю игру, я ожидаю увидеть 4 разных звезды, разбросанных повсюду, но вместо этого я просто получаю черный экран.

Заранее благодарю за любую помощь !

  • 0
    Можете ли вы добавить контекст? Вы строите это на прямой Java или используете библиотеку? Если только Java, перечислите код для JComponent, который вы используете для рендеринга.
  • 0
    Просто Java - добавили в игру класс
Теги:
scroll

3 ответа

0
Лучший ответ

Проблема оказалась просто в том, что у меня были неправильные координаты для каждого спрайта. Извините за потраченное время и спасибо за помощь в любом случае!

public static Sprite spaceSprite = new Sprite(32, 0, 0, SpriteSheet.bgtiles);
public static Sprite stars1 = new Sprite(32, 1, 0, SpriteSheet.bgtiles);
public static Sprite stars2 = new Sprite(32, 2, 0, SpriteSheet.bgtiles);
public static Sprite stars3 = new Sprite(32, 3, 0, SpriteSheet.bgtiles);
public static Sprite stars4 = new Sprite(32, 4, 0, SpriteSheet.bgtiles);
1

Из отправленного кода кажется, что вы забыли загрузить фон в изображение. Я поместил этот код в новый открытый метод loadAssets(). Вызовите это, прежде чем вы вызовете game.start().

public void loadAssets() {
    try {
        image = ImageIO.read(new URL("https://i.imgur.com/0yUKql2.png?1"));
    } catch (MalformedURLException ex) {
        Logger.getLogger(GameTwo.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(GameTwo.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Я также прокомментировал следующий код в render().

screen.clear();
level.render(x, y, screen);

for(int i = 0; i < pixels.length; i++) {
    pixels[i] = screen.pixels[i];
}
  • 0
    До сих пор мне не повезло с этим - извините, что я нуб, но где именно этот код должен быть размещен?
  • 0
    @Oliver Я разместил весь блок try сразу после вашего вызова addKeyListener. Это не лучшее место для добавления кода, но оно действительно помогло. Я бы добавил метод loadAssets (см. Отредактированный код) и вызвал бы его перед запуском.
Показать ещё 4 комментария
0

Поэтому из того, что я понимаю, вы делаете вызов рисования с использованием изображения BufferedImage, однако вы фактически не загружали данные изображения в переменное изображение. Я дам фрагмент кода, который вам может понадобиться

 File imageFile = new File("/path/to/image.file");
 BufferedImage image = ImageIO.read(imageFile);

Возможно, существует более быстрый способ, который вы уже назвали

private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

Но, как вы можете себе представить, на самом деле это не связывает вашу переменную изображения с файлом изображения. Мое лучшее предположение, что код, который я предоставил, будет работать, но, честно говоря, вам придется попробовать его.

Счастливое кодирование и оставить комментарий, если у вас есть вопросы!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню