2D Java 游戏。将精灵移动到平铺图像上方

发布于 2024-10-02 05:49:47 字数 958 浏览 1 评论 0原文

->简短的介绍,您可以跳过这一部分

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

实际内容(序言):

虽然我在公司是用 Objective-C 开发的,但我对 JAVA 开发非常感兴趣。 我对语法很满意,但在使用 awt/swing/Graphics2D 时遇到了一些主要问题。

概念:

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

->这实际上是“工作”。

第一次尝试:

将带有 imageIcon“gras”或“tree”的 (frame.add(...)) 16*12 JLabels 添加到 JLayeredPane
添加 (frame.add(...)) 类“entityLayer”,该类使用 Paint(Graphics g) 在 5 毫秒内更新
{
g.drawImage(imageIcon.getImage());
}
如果我添加带有图块的字段实体层,则此版本“有效”。在其他每种情况下,要么实体层用灰色背景覆盖字段,要么“玩家”在字段下不可见;

第二次尝试:

在entityLayer Paint(Graphics g)方法中制作所有绘图。但这不是我的意图。我希望该字段被绘制一次,并且“玩家”像半透明背景一样被绘制在该字段上方。

问题:

我怎样才能让自己真正拥有两个独立的层,它们都同样独立,而不会有一层重叠?我几乎 99% 确信我的尝试在某种程度上是错误的。

马上谢谢你。

->Short Introduction, you can SKIP this part

I'm glad to be able to finally post on this platform, because I for myself have gained so much knowledge through this community; just by reading. So I wanted to say "Hello everybody, and thank you!

Actual Content(prologue):

Though I'm developing in Objective-C in my company, I am utterly interested in JAVA development.
I am quite comfortable with the syntax but have some major troubles with awt/swing/Graphics2D.

The Concept:

JAVA Application with a 800*600 Frame. On this Frame you can see 16*12 tiles (i.e. gras.jpg or tree.jpg) with a size of 50px². Above this Frame a .png "player" is moving. The field is generated with a 2 dimensional int array[16][12] where a 0 symbolizes "gras" and 1 means "tree".

-> This is actually "working".

First Try:

Adding (frame.add(...)) 16*12 JLabels with imageIcon "gras" or "tree" to a JLayeredPane
Adding (frame.add(...)) class "entityLayer" wich is updated at 5ms with paint(Graphics g)
{
g.drawImage(imageIcon.getImage());
}
This Version "works" if I add either the field with tiles or the entity layer. In every case else either the entityLayer overlays the field with a grey background or the "player" is not visible under the field;

Second Try:

Making all the drawings in the entityLayer paint(Graphics g) method. But thats not what I intended. I want the field to be drawn once and the "player" with, like a translucent background, drawn above the field.

Question:

How can I get myself in a position to actually have two seperate layers, that are both equally independent with out having one overlapping the other? Im nearly 99% shure my attempt is wrong in some way.

Thank you right away.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

地狱即天堂 2024-10-09 05:49:47

不是添加/绘制16*12 JLabels,而是绘制平铺图像16*12次?

对于这样的事情,我通常将单个 JPanel 添加到 JFrame 中,并重写 JPanel 的 Paint() 方法。
实际上,我没有添加 JPanel,而是添加了我创建的 JPanel 的子类,您应该执行相同的操作,因为我将向您展示您需要向 JPanel 添加一个字段并重写 Paint 方法< /em>

您的背景图块绘制代码可能类似于:

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);
    }

}

如果您想知道为什么我将 NULL 传递到 g.drawImage() 函数中,这是因为对于该重载函数调用,最后一个参数是 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);
    }
}

Instead of adding/drawing 16*12 JLabels, just draw the tile image 16*12 times?

For things like this, I usually add a single JPanel to a JFrame, and override the JPanel's paint() method.
Actually, I don't add a JPanel, I add a subclass of JPanel that I have created, you should do the same, as I will show you will need to add a field to the JPanel and override the paint method

Your background tile drawing code might look similar to:

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);
    }
}

A technique that works well for me is to separate the drawing logic of each layer into a separate class that implements the Painter interface (or a similar interface you define).

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
    }

}

Then for the player painter:

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);
    }

}

If you are wondering why I am passing NULLs into the g.drawImage() function, its because for that overloaded function call the last parameter is an ImageObserver, which is something we do not need for this purpose.

Ok, so once you have your painters separated into different classes we need to make the JPanel capable of using them!

This is the field that you need to add to your JPanel:

List<Painter> layerPainters;

Your constructor should look something like this:

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);

    }

Now for the last but most important part:

@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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文