Think about it like this: would it make sense to draw in between pixels?
Sometimes, it might look like a line is drawn between two pixels, however that is done using Anti-Aliasing.
I have a rectangle2d moving on the screen with double precision using vectors and I want to draw an image on top of the rectangle. When the rectangle is moving the image just does not stay on top of it all the time because its drawn with double precision and the image with integer.
No need for code. Zushii is right, Rectangle2D.Double is basically rounded to the nearest integer and drawn there because there are no fractional pixels.
Yes, if anti-aliasing is turned on, then it may seem as if the lines are drawn between 2 pixels when it actually just spreads it over both in some specific way that tricks your eye into thinking it is smooth.
Hello again. I use this code to draw a rectangle and then a 32x32 image on top of it. The problem is that when x and y change the coordinates of the rectangle and image are not always rounded to the same number, sometimes the image is 1 pixel further than the rectangle. When I round the x and y before this code they are drawn in the same position, but I can’t do that, I have to create the rectangle giving it the x and y in double precision.
g2d.setPaint(Color.red);
Rectangle2D f = new Rectangle2D.Double(100 + x, 250 + y, 32, 32);
g2d.fill(f);
g2d.drawImage(boxTexture, (int)Math.round(100 + x), (int)Math.round(250 + y), null);
I also tried this code but again I got the same result:
g2d.setPaint(new TexturePaint(boxTexture, new Rectangle.Double(100 + x, 250 + y, boxTexture.getWidth(), boxTexture.getHeight())));
Rectangle2D f = new Rectangle2D.Double(100 + x, 250 + y, 32, 32);
g2d.fill(f);
I tried it without using Math.round() and it didn’t help. This code doesn’t even use Math.round() but it still causes the same problem. Image and rectangle coordinates don’t match
g2d.setPaint(new TexturePaint(boxTexture, new Rectangle.Double(100 + x, 250 + y, boxTexture.getWidth(), boxTexture.getHeight())));
Rectangle2D f = new Rectangle2D.Double(100 + x, 250 + y, 32, 32);
g2d.fill(f);
Yes I tried that, didn’t solve the problem. But then have a look at the second code which uses TexturePaint. It doesn’t use Math.round() so I think it must be something else…
g2d.setPaint(Color.red);
Rectangle2D f = new Rectangle2D.Double(100 + x, 250 + y, 32, 32);
g2d.fill(f);
g2d.drawImage(boxTexture, (int)Math.round(100 + x), (int)Math.round(250 + y), null);
planC
instead of g2d.fill(f)
could you try
g2d.fillrect(f.x, f.y, f.width, f.height);
It may require you to cast (int) and use the same method as you do for your drawImage
either just leave “both (int) with no round”, or both “drawimage and fillrect with (int)math.round”
plan D
g2d.setPaint(Color.red);
Rectangle2D f = new Rectangle2D.Double(100 + x, 250 + y, 32, 32);
g2d.fillrect((int)f.x, (int)f.y, f.width, f.height);
g2d.drawImage(boxTexture, (int)f.x, (int)f.y, null);
This should allow both the filled rect and image to be the same pixel locations
While maintaining the rectangles double precision(for collision detection or other “high resolution/ sub pixel accuracy”
edit:
Could I inquire to why you need both an image and a filled red rectangle occupying the same location? Will the image or red rect not just obstruct the other from sight?
Because although I’d like to continue to help you solve your problem the method you’d like to. Perhaps there is another underlying better solution to the whole thing?
As primitives use antialiasing for sub-pixel accuracy, and images use interpolation for sub-pixel accuracy I fear you are asking for the impossible.
However, the difference might not be noticable - and it’ll certainly make an animated image moving through floating point coordinates appear smoother.
So, set the necessary rendering hint for sub-pixel interpolation (RenderingHints.KEY_INTERPOLATION, to either VALUE_INTERPOLATION_BICUBIC or VALUE_INTERPOLATION_BILINEAR) and then use SimonH’s ‘plan B’ of using an AffineTransform to supply the drawing coordinates in floating point form.
I don’t know what the state of hardware acceleration is for the various interpolation & antialiasing rendering hints, so if performance is a concern you might want to rethink your strategy.
Such a rethink might involve moving away from Java2D entirely.
This is working just fine. The rectangle and image now are drawn at the same x and y pixel location. I use I high precision collision detection so the drawback of this approach is that a collision is detected before the two rectangles touch (there is one pixel gap between them or one box is 1 pixel on top of the other because double precision coordinates for collision detection are used). But this is not very noticeble and it solves my problem. The image doesn’t move from left to right anymore (when the rectangle was moving fast it seemed like the image was shaking).
Yes, the image will obstruct the rectangle and the reason it was painted in red is just for debugging…
Thank you!