Graphics2D clipping error

that looks very nice. if you are able, i’d really like to have a look at the whole source… also, what’s the problem with the anti-aliasing? is it slow or is it making the edges look funny when in front of the actor?

Its making the edges look funny. I found out that it is caused by Java2D storing the polygon as floating point coordinates. To get around this I started using the Rectangle class, but this is taking to long… I really need a way to use PixelGrabber to create an Area based off of an image’s alpha channel.

Also, is there a way to translate an area?

Juddman: send me an email at: [backwards]moc.liamG AT snikpoh.m.ffej[/backwards] and I’ll email you the source…

well, I would not use PixelGrabber since it destroys performance more or less…

But I wouldn’t be using it every frame. Once I created the area at startup, I could just store it and translate it when needed.

Re: anti-aliasing…

Have you tried setting rendering hints to force OFF anti-aliasing and perhaps LOWER render quality (use SPEED hints instead of QUALITY hints).

Just a shot in the dark…

Yup, both. No success. :frowning:

Thanks though!

anti-aliasing rendering hints do nothing for images. Those only affect Strokes or Shapes being drawn. What you want for your image to retain its anti-aliased quality is to save them as png’s with full translucency. If the space around the isometric tile has a 0 for it’s alpha value, you should never have any need for setting Clips or using Areas because when you draw with the tile, it should only use its colored portion.

I know that when I display my tiles that the alpha is… well alpha. And I know that when drawing without using clipping that it works fine.

What I want to do is make it so that if I want to display an Actor behind a tile that I don’t have to rerender the entire map (I can’t use the standard dirty rect logic because there are layering issues).

So in order to redraw an actor to the background I need to clip out of the actor’s graphic where the tiles are that are over the character. For instance if the character is half visible behind a low wall, you don’t want to render the entire actor, just his top half.

I fixed the antaliasing issue by resorting to a bunch of Rectangles (because they store their coords in int). But the issue with this is that it takes too much cpu to clip with an Area of 20 rectangles per tile.

The solution to my problem would be able to make a pixel acurate Area from a given png.

how bout you buffer layers? Have a BufferedImage for a layer, re-draw the ones you need to, and don’t ever worry about Areas and Clips? Then your render loop looks like this:


for (int i = 0; i < topLayer; i++) {
      layers[i].render(g2d);
      for (int j = 0; j < characters.length; j++)
            if (characters[i].layer == i)
                  characters[i].render(g2d);
}

That would work, right? You could even enhance it to know more about which layers have changed and perhaps combine buffered layers if possible so that fewer have to draw.

I’ve tried that also, the problem again is that because it is isometric the layers are in diagonal lines, causing the BufferedImage for each layer to be the size of the window. This gets increasingly more taxing on the system because you can’t just redraw one of those layers, you have to draw every layer above the one you want to redraw.

Lets say that I have an actor on Y:3. And lets also say that the screen is big enough to handle 20 Y. This means that in order to redraw Y:3 you also have to redraw (to the screen, not the actual tiles) everything between 3 and 20.

I found it more taxing on the system to redraw 17 buffered Images then to just redraw the entire thing tile by tile, actor by actor.

With doing it by clipping and Areas I can make it so that a minimal amount of drawing is going on no matter the screen size. It would all be based on how many actors were being refreshed.

ahh I wasn’t talking about y layers, I was talking z layers, so like in ff tactics the most buffers you would ever have would be perhaps 5 layers. I don’t know why your image shows areas so tall… but hey, it’s your game :wink: If you want to make it this intricate perhaps you could just use a better rendering engine like LWJGL.

Instead of using clipping, how about draw a separate alpha channel based on the foreground/background separation. Then when you blit your player, change the compositing rule to use the alpha that you created.

E.g.: Assuming you only blit one pass to draw the terrain.

  • Clear the screen so the screens alpha is 0
  • Blit background objects with compositing rules that copy the alpha channel to the background image.
  • Blit foreground objects such that the background alpha is left at 0
  • Blit the player so it only shows through where the dest alpha is 1

I’m not certain the rules on AlphaComposite cover all the needed cases… but it might be an approach that works out.

[quote]Instead of using clipping, how about draw a separate alpha channel based on the foreground/background separation.
[/quote]
The problem comes with actually generating the alpha channels… if I could generate seperate alpha channels I could just apply the clippings this way also…

Okay, I have a quick question that might solve all of this…

I have an object called a Sprite_Cache. His job is to store all the graphics as Images and provide keys in String format. In order to store these Images he uses a HashMap, and put()s the image in there…

This way when I want the Sprite named “Actor_001_d_1” I just go:
Image AnImage = (Image)sprites.get(“Actor_001_d_1”); Is this accelerated? Because I store my tiles in there, and for every tile being drawn it gets its image this way…

well first off, I don’t think Image’s are accelerated period. If you’re asking about the .get() and the type cast, I don’t think any optimization happens there. Even Generics which make it look better don’t even optimize (my biggest peeve) it. What I do with my stuff is something like this:


private static final int
      Actor_001_d_1 = 0,
      Actor_002_d_1 = 1,
      Actor_003_d_1 = 2,
      Actor_004_d_1 = 3;
public void loadImages() {
      images = new BufferedImage[4];
      for (int i = 0; i < images.length; i++)
            images[i] = getResource("Actor_00" + (i+1) + "_d_1.png");
}
public void render(Graphics2D g2d) {
      g2d.drawImage(images[index], x, y, null);
}

kinda like that :slight_smile:
so that I can load them by ints from an array, but still have a uniqueness about them that’s easy for me to read.

EDIT: forgot a curly brace :wink: Coding in here is tough!

i would perhaps try clipping the sprite graphic when you draw it rather than clipping the terrain. then you could use just one large buffer for the entire background / foreground. the tricky part might be making the formula that generates a polygon to use as the clip bounds.

i’m not sure how this would affect performance but i think calculating a polygon that represents the area that is in front of the player sprite and clipping just the sprite(s) when you draw it (or them) should be faster as its a much smaller image you’re clipping, and the anti-aliasing shouldn’t be as much of a problem, and in fact might look nice. as they say, logic is 1000 times cheaper than rendering in games, so adding complexity to the logic in order to reduce the amount of rendering done almost always pays off in performance.

i’m just throwing ideas around now, and i’ll probably even test a couple when i get your source, but one way to do it would be to calculate a polygon for each layer and clip the sprite based on a combination of all layers in front of it when you draw it.

Just to clarify, I meant BufferedImage not Image. :wink:

So I went through and changed it over to using a BufferedImage[], and there wasn’t any change between the two as far as the performance… I was rather hoping that this would speed everthing up… Thanks though!

oh yeah the difference definitely isn’t going to be significant. Accessor methods from your list was never your bottleneck obviously, it’s the rendering that’s your bottleneck.

Its kind of funny, I used something like this:


HashMap array_keys = new HashMap()
BufferedImage[] images = new BufferedImage[1000];
int current_index = 0;

public void addImage(String filename, String sck) {
   array_keys.put(filename, new String(""+current_index));
   images[current_index] = //IMAGE FROM RESOURCES
   current_index++;
}

public BufferedImage getImage(String sck) {
   return images[Integer.parseInt(array_keys.get(sck))];
}

This way I would have the speed of taking it from a BufferedImage[], and also the ability to have better naming…

But my hope of putting it into a BufferedImage[] was that it wasn’t getting accelerated in the HashMap…

Objects that have references to BufferedImages don’t affect how it gets accelerated. Having it stored in an array or Hashtable don’t make a bit of difference in that department. Am I understanding you correctly? I don’t think I know what it is you’re asking now.

Yeah, thats what I figured out. I was hoping that storing the reference in a hashtable was causing the BufferedImages to not be accelerated…

But any way I think I can say that you for all your guys’s input! This thread keeps going on and on, and I don’t see any point to continue it. If I have more questions I’ll post in a new thread.

Thanks!