2015-05-13 9 views
4

Я пытаюсь создать небольшую игру в java, но у меня проблемы.JLabel и JLayeredPane - Как отобразить изображение поверх другого изображения?

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

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

Как я могу отобразить изображение на другом изображении?

Как я могу объяснить java, что мне нужно отображать это изображение на другом изображении или под другим изображением?

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

import javax.swing.JFrame; 
import javax.swing.ImageIcon; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 


public class Window extends Thread 
{ 
    private static JFrame window = new JFrame("game"); 

    public void run() 
    { 
     Map map = new Map(); 
     Characters characters = new Characters(); 

     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     window.setSize(Settings.sizeX, Settings.sizeY); 
     window.setLocationRelativeTo(null); 
     window.setResizable(false); 
     window.setVisible(true); 

     map.start(); 
     characters.start(); 
    } 

    private static void reload() throws Exception 
    { 
     SwingUtilities.updateComponentTreeUI(window); 
    } 

    private static class Map extends Thread 
    { 
     private int numberSquareX = Settings.sizeX/20 + 1; 
     private int numberSquareY = Settings.sizeY/20 + 1; 
     private JLabel square[][] = new JLabel[numberSquareX][numberSquareY]; 

     public void run() 
     { 
      for (int x = 0, y = 0; y < numberSquareY; x++) 
      { 
       square[x][y] = new JLabel(new ImageIcon("grass_1.png")); 
       square[x][y].setBounds(x * 20, y * 20, 20, 20); 
       window.add(square[x][y]); 
       if (x == numberSquareX - 1) 
       { 
        y++; 
        x = -1; 
       } 
      } 
      square[numberSquareX - 1][numberSquareY - 1] = new JLabel(new ImageIcon("grass_1.png")); 
      square[numberSquareX - 1][numberSquareY - 1].setBounds(numberSquareX * 20, numberSquareY * 20, 20, 20); 
      window.add(square[numberSquareX - 1][numberSquareY - 1]); 
      try 
      { 
       reload(); 
      } 
      catch (Exception e) 
      { 

      } 
      return; 
     } 
    } 

    private class Characters extends Thread 
    { 
     private JLabel square[][] = new JLabel[1][1]; 

     public void run() 
     { 
      square[0][0] = new JLabel(new ImageIcon("character_1.png")); 
      square[0][0].setBounds(Test.posX, Test.posX, 20, 20); 
      window.add(square[0][0]); 
      try 
      { 
       reload(); 
      } 
      catch (Exception e) 
      { 

      } 
      return; 
     } 
    } 
} 

Я уже нашел эти предметы: How to use JLayered Pane to display an image on top of another image? и это один Best practice for creating a composite image output for Java Swing, но они на самом деле не помогут мне ...

Я продолжаю искать ответ. Если я найду это, я вернусь для публикации здесь.

+1

Рендер в заголовке карты в «BufferedImage», e ither в полном объеме или на основе доступной видимой области, которая когда-либо более эффективна. Покрасьте это на экран, а затем нарисуйте своего персонажа сверху – MadProgrammer

+1

В 15 лет профессиональной разработки Java/Swing мне никогда не приходилось использовать 'SwingUtilities.updateComponentTreeUI (window);' вместо этого просто называть 'repaint 'на компоненте, который отвечает за вывод обработчика, я уверен, вы найдете это более эффективным. – MadProgrammer

+1

Swing также является однопоточной средой И не является потокобезопасной, вы НЕ должны обновлять пользовательский интерфейс вне контекста Event Dispatching Thread, так как это установит условие гонки и может привести к нежелательным и трудным для решения графических проблем , – MadProgrammer

ответ

2

Решено.

Благодаря MadProgrammer за его комментарии.

Измените карту названия на BufferedImage, либо в полном объеме, либо на основе доступной видимой области, которая когда-либо более эффективна. Покрасьте это на экран, а затем нарисуйте своего персонажа сверху - MadProgrammer

В 15 лет профессиональной разработки Java/Swing мне никогда не приходилось использовать SwingUtilities.updateComponentTreeUI (window) ;, вместо этого просто вызовите repaint на компоненте, который отвечает за вывод рендерера, я уверен, вы найдете это более эффективным. - MadProgrammer

Swing также представляет собой однопоточную среду И не является потокобезопасной, вы НЕ должны обновлять пользовательский интерфейс вне контекста Event Dispatching Thread, поскольку это установит условие гонки и может привести к нежелательным и трудно решить графические проблемы. - MadProgrammer

Подсказка. JLabel является потомком Container, что означает, что он может содержать другие компоненты;) - MadProgrammer

Большое спасибо MadProgrammer! Поэтому я заменил SwingUtilities.updateComponentTreeUI (window) на window.repaint(). У вас была правильная версия Thread, у моей карты были некоторые ошибки, но я не смог найти, откуда они. А как насчет BufferedImage? Если я создам два BufferedImage, последний может быть автоматически в верхней части первого? Или я просто хочу отобразить карту названия в BufferedImage (так что я ограничен двумя слоями)? - Celine

Это будет зависеть от того, чего вы хотите достичь.Использование BufferedImages дает вам полный контроль над размещением изображений и да, их можно визуализировать над другим, картина похожа на холст художников, поскольку вы добавляете к нему что-то, они добавляются поверх того, что уже существует, НО, вы можете найти его проще добавить JLabel к другому JLabel - просто помните, JLabel не имеет менеджер компоновки по умолчанию - MadProgrammer пример

код: захват

import javax.swing.JFrame; 
import javax.swing.ImageIcon; 
import javax.swing.JLabel; 


public class Window extends Thread 
{ 
    private static JFrame window = new JFrame("game"); 
    private int numberSquareX = Settings.sizeX/20 + 1; 
    private int numberSquareY = Settings.sizeY/20 + 1; 
    private JLabel titlesetLayer1[][] = new JLabel[numberSquareX][numberSquareY]; 
    private JLabel titlesetLayer2[] = new JLabel[1]; 
    private JLabel titlesetLayer3[] = new JLabel[1]; 
    private JLabel titlesetLayer4[] = new JLabel[0]; 
    private JLabel titlesetLayer5[] = new JLabel[0]; 
    private JLabel characters[] = new JLabel[2]; 

    public void run() 
    { 
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     window.setSize(Settings.sizeX, Settings.sizeY); 
     window.setLocationRelativeTo(null); 
     window.setResizable(false); 

     // draw layer5 (on the layer4) 

     // draw layer4 (on the layer3) 

     // draw layer3 (on the characters) 
     titlesetLayer3[0] = new JLabel(new ImageIcon("tree_1.png")); 
     titlesetLayer3[0].setBounds(130, 120, 126, 160); 
     window.add(titlesetLayer3[0]); 

     // draw the charaters 
     characters[1] = new JLabel(new ImageIcon("character_1.png")); 
     characters[1].setBounds(600, 500, 100, 100); 
     window.add(characters[1]); 

     characters[0] = new JLabel(new ImageIcon("character_1.png")); 
     characters[0].setBounds(100, 100, 100, 100); 
     window.add(characters[0]); 

     // draw layer2 (under the characters) 
     titlesetLayer2[0] = new JLabel(new ImageIcon("tree_1.png")); 
     titlesetLayer2[0].setBounds(570, 400, 126, 160); 
     window.add(titlesetLayer2[0]); 

     // draw layer1 (under the layer2) 
     for (int x = 0, y = 0; y < numberSquareY; x++) 
     { 
      titlesetLayer1[x][y] = new JLabel(new ImageIcon("grass_1.png")); 
      titlesetLayer1[x][y].setBounds(x * 20, y * 20, 20, 20); 
      window.add(titlesetLayer1[x][y]); 
      if (x == numberSquareX - 1) 
      { 
       y++; 
       x = -1; 
      } 
     } 
     titlesetLayer1[numberSquareX - 1][numberSquareY - 1] = new JLabel(new ImageIcon("grass_1.png")); 
     titlesetLayer1[numberSquareX - 1][numberSquareY - 1].setBounds(numberSquareX * 20, numberSquareY * 20, 20, 20); 
     window.add(titlesetLayer1[numberSquareX - 1][numberSquareY - 1]); 

     window.setVisible(true); 
     // window.repaint(); 
    } 
} 

экрана :

Example1

Другим решением является использование JLayeredPane! Пример

JLayeredPane layers = new JLayeredPane(); 
layers.add(tilesetsUnderCharacter, 0); // Layer 0 
layers.add(character, 1); // Layer 1 
layers.add(tilesetsOnCharacter, 2); // Layer 2 
frame.setContentPane(layers); 

Код:

private void init() 
{ 
    frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); 
    frame.setSize(Settings.getX(), Settings.getY()); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 

    for (int i = 0; i < y ; i++) 
    { 
     for (int j = 0; j < x; j++) 
     { 
      for (int k = 0; k < tilesetsOnCharactersSize; k++) 
      { 
       tilesetsOnCharacters[i][j][k] = new javax.swing.JLabel(new javax.swing.ImageIcon(Resources.getTileset(Maps.getMapTileset(mapNumber, 1, k, i, j)))); 
       tilesetsOnCharacters[i][j][k].setBounds(j * tilesetX, i * tilesetY, tilesetX, tilesetY); 
       map.add(tilesetsOnCharacters[i][j][k], 4); 
      } 
      for (int k = 0; k < tilesetsUnderCharactersSize; k++) 
      { 
       tilesetsUnderCharacters[i][j][k] = new javax.swing.JLabel(new javax.swing.ImageIcon(Resources.getTileset(Maps.getMapTileset(mapNumber, 0, k, i, j)))); 
       tilesetsUnderCharacters[i][j][k].setBounds(j * tilesetX, i * tilesetY, tilesetX, tilesetY); 
       map.add(tilesetsUnderCharacters[i][j][k], 0); 
      } 
      for (int k = 0; k < mapAttributeSize; k++) 
      { 
       if (Maps.getMapTileset(mapNumber, 2, k, i, j) == 1) 
       { 
        blocked[i][j] = true; 
       } 
      } 
     } 
    } 
    for (int i = 0; i < charactersNumber; i++) 
    { 
     characters[i] = new Character(0, 0, 64, 64, 0, 0, 0, 0, 5); 
     tilesetsCharacters[i] = new javax.swing.JLabel(new javax.swing.ImageIcon(Characters.getCharacter(characters[i].getCharacterSkin(), characters[i].getDirection()))); 
     tilesetsCharacters[i].setBounds(characters[i].getX(), characters[i].getY(), characters[i].getSizeX(), characters[i].getSizeY()); 
     map.add(tilesetsCharacters[i], 1); 
     charactersRender[i] = false; 
    } 

    frame.addKeyListener(new java.awt.event.KeyAdapter() 
    { 
     @Override 
     public void keyTyped(java.awt.event.KeyEvent keyEvent) 
     { 

     } 

     @Override 
     public void keyPressed(java.awt.event.KeyEvent keyEvent) 
     { 
      if((keyEventInt = keyEvent.getKeyCode()) == java.awt.event.KeyEvent.VK_F) 
      { 
       right = true; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_S) 
      { 
       left = true; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_E) 
      { 
       up = true; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_D) 
      { 
       down = true; 
      } 
     } 

     @Override 
     public void keyReleased(java.awt.event.KeyEvent keyEvent) 
     { 
      if((keyEventInt = keyEvent.getKeyCode()) == java.awt.event.KeyEvent.VK_F) 
      { 
       right = false; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_S) 
      { 
       left = false; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_E) 
      { 
       up = false; 
      } 
      else if(keyEventInt == java.awt.event.KeyEvent.VK_D) 
      { 
       down = false; 
      } 
     } 
    }); 

    frame.setContentPane(map); 
    frame.setVisible(true); 
} 

private void update() 
{ 
    if (exit && characters[0].getX() < x * tilesetX - characters[0].getSizeX() - characters[0].getMovementSpeed() && characters[0].getX() > 0 && characters[0].getY() > 0 && characters[0].getY() < y * tilesetY - characters[0].getSizeY() - characters[0].getMovementSpeed()) 
    { 
     exit = false; 
    } 
    if (right && (exit || (characters[0].getX() < x * tilesetX - characters[0].getSizeX() - characters[0].getMovementSpeed() && !blocked[characters[0].getY()/tilesetY][(characters[0].getX() + characters[0].getSizeX() + characters[0].getMovementSpeed())/tilesetX] && !blocked[(characters[0].getY() + characters[0].getSizeY())/tilesetY][(characters[0].getX() + characters[0].getSizeX() + characters[0].getMovementSpeed())/tilesetX]))) 
    { 
     characters[0].right(); 
     characters[0].setScaleX(5); 
     if (allowExitRight && characters[0].getX() > x * tilesetX - characters[0].getSizeX() - characters[0].getMovementSpeed() - 1) 
      exit = true; 
     charactersRender[0] = true; 
    } 
    if (left && (exit || (characters[0].getX() > 0 && !blocked[characters[0].getY()/tilesetY][(characters[0].getX() - characters[0].getMovementSpeed())/tilesetX] && !blocked[(characters[0].getY() + characters[0].getSizeY())/tilesetY][(characters[0].getX() - characters[0].getMovementSpeed())/tilesetX]))) 
    { 
     characters[0].left(); 
     characters[0].setScaleX(-3); 
     if (allowExitLeft && characters[0].getX() <= 0) 
      exit = true; 
     charactersRender[0] = true; 
    } 
    if (jumped || up && (exit || (characters[0].getY() > 0 && !blocked[(characters[0].getY() - characters[0].getMovementSpeed())/tilesetY][characters[0].getX()/tilesetX] && !blocked[(characters[0].getY() - characters[0].getMovementSpeed())/tilesetY][(characters[0].getX() + characters[0].getSizeX())/tilesetX]))) 
    { 
     if (!jump) 
     { 
      characters[0].up(); 
      characters[0].setScaleY(-3); 
      if (allowExitUp && characters[0].getY() <= 0) 
       exit = true; 
      charactersRender[0] = true; 
     } 
     else if (!jumped && !falling) 
     { 
      jumpCurrentDuration = jumpDuration; 
      jumped = true; 
     } 
     else if (--jumpCurrentDuration > 0) 
     { 
      if (exit || (characters[0].getY() > 0 && !blocked[(characters[0].getY() - characters[0].getMovementSpeed())/tilesetY][characters[0].getX()/tilesetX] && !blocked[(characters[0].getY() - characters[0].getMovementSpeed())/tilesetY][(characters[0].getX() + characters[0].getSizeX())/tilesetX])) 
      { 
       characters[0].up(); 
       characters[0].setScaleY(-3); 
       if (allowExitUp && characters[0].getY() <= 0) 
        exit = true; 
       charactersRender[0] = true; 
      } 
     } 
     else 
     { 
      jumped = false; 
     } 
    } 
    if (((down && !jumped) || (gravity && !jumped)) && (exit || (characters[0].getY() < y * tilesetY - characters[0].getSizeY() - characters[0].getMovementSpeed() && !blocked[(characters[0].getY() + characters[0].getSizeY() + characters[0].getMovementSpeed())/tilesetX][characters[0].getX()/tilesetX] && !blocked[(characters[0].getY() + characters[0].getSizeY() + characters[0].getMovementSpeed())/tilesetY][(characters[0].getX() + characters[0].getSizeX())/tilesetX]))) 
    { 
     characters[0].down(); 
     characters[0].setScaleY(5); 
     if (allowExitDown && characters[0].getY() > y * tilesetY - characters[0].getSizeY() - characters[0].getMovementSpeed()) 
      exit = true; 
     if (jump) 
      falling = true; 
     charactersRender[0] = true; 
    } 
    else if (jump) 
     falling = false; 
} 

private void render() 
{ 
    for (int i = 0; i < charactersNumber; i++) 
    { 
     if (charactersRender[i]) 
     { 
      tilesetsCharacters[i].setIcon(new javax.swing.ImageIcon(Characters.getCharacter(characters[i].getCharacterSkin(), characters[i].getDirection()))); 
      tilesetsCharacters[i].setBounds(characters[i].getX() + characters[i].getScaleX(), characters[i].getY() + characters[i].getScaleY(), characters[i].getSizeX(), characters[i].getSizeY()); 
      charactersRender[i] = false; 
     } 
    } 
} 

Screen Capture:

JLayeredPane

Edit: Я также нашел библиотеку под названием Slick2D, которые работают с TiledMapEditor:

Как настроить Slick2D: How to install Slick2d?

Как использовать Slick2D и TiledMapEditor: Slick2D + Tiled cant load map

Где начал: https://thejavablog.wordpress.com/2008/06/08/using-slick-2d-to-write-a-game/

 Смежные вопросы

  • Нет связанных вопросов^_^