2D Java游戏。在平铺图像上移动精灵。

3

->简介,可以跳过此部分

我很高兴能够在这个平台上发布文章,因为通过这个社区我自己获得了很多知识; 只是通过阅读。所以我想说“大家好,谢谢你们!

实际内容(序言):

虽然我在公司开发Objective-C,但我对JAVA开发非常感兴趣。 我对语法非常熟悉,但在awt / swing / Graphics2D方面有一些主要问题。

概念:

JAVA应用程序具有800 * 600帧。在此帧上,您可以看到16 * 12个大小为50px²的图块(即gras.jpg或tree.jpg)。在此框架上方,.png“player”正在移动。该字段使用二维int数组[16] [12]生成,其中0表示“gras”,1表示“tree”。

-> 这实际上“有效”。

第一次尝试:

添加(frame.add(...))16 * 12个带有imageIcon“gras”或“tree”的JLabel到JLayeredPane
添加(frame.add(...))类“entityLayer”,该类在5ms内使用paint(Graphics g)进行更新
{
g.drawImage(imageIcon.getImage());
}
如果我添加了具有瓦片的字段或实体层,则此版本“有效”。 在其他情况下,entityLayer会将带有灰色背景的字段覆盖,或者“player”在字段下不可见;

第二次尝试:

在entityLayer paint(Graphics g)方法中进行所有绘图。 但这不是我的意图。 我希望该领域被绘制一次,并且“player”与像半透明背景一样绘制在该领域上方。

问题:

如何使自己处于实际上具有两个完全独立的分层位置,而不必使一个重叠另一个? 我几乎99%确定我的尝试在某种程度上是错误的。

谢谢你们。


如果您对此有其他问题,请告诉我。还可以查看Game Dev Stack Exchange网站,http://gamedev.stackexchange.com/。 - Tom Neyland
1个回答

1

不要添加/绘制16*12个JLabel,只需将瓷砖图像绘制16*12次即可?

对于这样的事情,我通常将单个JPanel添加到JFrame中,并覆盖JPanel的paint()方法。 实际上,我不是添加一个JPanel,而是添加了我创建的JPanel子类,你也应该这样做,因为我将向你展示需要向JPanel添加一个字段并覆盖paint方法

您的背景瓷砖绘制代码可能类似于:

int tileWidth = 50;
int tileHeight = 50;
for ( int x = 0; x < 16; x++ )
{
    for ( int y = 0; y < 12; y++ )
    {
        Image tileImage;
        int tileType = fieldArray[x][y];

        switch ( tileType )
        {
            case 0:
            {
                tileImage = myGrassImage;
                break;
            }
            case 2:
            {
                tileImage = myTreeImage;
                break;
            }
        }

        Graphics2D g;
        g.drawImage(tileImage, x * tileWidth, y * tileHeight, null);
    }
}

一个对我来说很有效的技巧是将每个图层的绘制逻辑分离到一个单独的类中,该类实现了Painter接口(或您定义的类似接口)。
public class TilePainter implements Painter
{

    @Override
    public void paint( Graphics2D g, Object thePanel, int width, int height )
    {
        //The tile painting code I posted above would go here
        //Note you may need to add a constructor to this class
        //that provides references to the needed resources
        //Eg: images/arrays/etc
        //Or provides a reference to a object where those resources can be accessed
    }

}

然后对于玩家画家:

public class EntityPainter implements Painter
{

    @Override
    public void paint( Graphics2D g, Object thePanel, int width, int height )
    {
        g.drawImage(player.getImage(), player.getX(), player.getY(), null);
    }

}

如果你想知道为什么我在g.drawImage()函数中传递NULL,那是因为对于这个重载的函数调用,最后一个参数是ImageObserver,而我们不需要它。

好的,一旦你把你的画家分成不同的类,我们需要让JPanel能够使用它们!

这是你需要添加到JPanel的字段:

List<Painter> layerPainters;

你的构造函数应该长这样:

public MyExtendedJPanel()
    {
        //I use an ArrayList because it will keep the Painters in order
        List<Painter> layerPainters = new ArrayList<Painter>();

        TilePainter tilePainter = new TilePainter(Does,This,Need,Args);
        EntityPainter entityPainter = new EntityPainter(Does,This,Need,Args);

        //Layers will be painted IN THE ORDER THEY ARE ADDED
        layerPainters.add(tilePainter);
        layerPainters.add(entityPainter);

    }

现在是最后但也是最重要的部分:
@Override
public void paint( Graphics g )
{
    int width = getWidth();
    int height = getHeight();
    //Loops through all the layers in the order they were added
    //And tells them to paint onto this panels graphic context
    for(Painter painter : layerPainters)
    {
        painter.paint(g,this,width,height);
    }
}

非常感谢您提供的详细支持!一回到家就会尝试。 - Sniffer
个人建议您继承 JComponent 而不是 JPanel,特别是因为您没有调用 super.paint - wchargin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接