2D Java Game. Moving sprite above tiled images
->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.drawI开发者_StackOverflow社区mage(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.
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);
}
}
精彩评论