Решено.
Благодаря 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();
}
}
экрана :
1
Другим решением является использование 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:
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/
Рендер в заголовке карты в «BufferedImage», e ither в полном объеме или на основе доступной видимой области, которая когда-либо более эффективна. Покрасьте это на экран, а затем нарисуйте своего персонажа сверху – MadProgrammer
В 15 лет профессиональной разработки Java/Swing мне никогда не приходилось использовать 'SwingUtilities.updateComponentTreeUI (window);' вместо этого просто называть 'repaint 'на компоненте, который отвечает за вывод обработчика, я уверен, вы найдете это более эффективным. – MadProgrammer
Swing также является однопоточной средой И не является потокобезопасной, вы НЕ должны обновлять пользовательский интерфейс вне контекста Event Dispatching Thread, так как это установит условие гонки и может привести к нежелательным и трудным для решения графических проблем , – MadProgrammer