setTransform to rotate Images produces unexpected results - java

I looked everywhere to see with anyone had the same problem than me but it seems I'm the only one getting this error.
So I'm in Java with Swing. I have a class Player that draws an image of the player. However, each time I tried to use setTransform to rotate my image, the second instance of player is scaled down by two.
Here is my code for the draw method:
AffineTransform transform = new AffineTransform();
transform.rotate(this.getOrientationRadians(), getX()+getWidth()/2,getY()+getHeight()/2);
g.setTransform(transform);
g.drawImage(image, (int)(getX()), (int)(getY()), null);
g.setTransform(new AffineTransform());

By overwriting the transform of the Graphics object you are also overwriting the scaling imposed by your system scale (which I suppose is set to 200%).
Either restrict to using Graphics2D::rotate or pass the transform the drawImage call.
AffineTransform transform = new AffineTransform();
transform.translate(getX(), getY());
transform.rotate(getOrientationRadians());
g.setTransform(transform);
g.drawImage(image, transform, null);

Related

Alternative to using Graphics2D Area?

I'm making a game where you start by drawing your map. At the moment it works by having an Area instance variable and then when the player clicks/drags the mouse it adds Ellipse2Ds to it. Here's what I mean:
Area land = new Area();
And then in the MouseDragged method
Point2D mouse = e.getPoint();
Ellipse2D ter = new Ellipse2D.Double(mouse.getX() - drawRad, mouse.getY() - drawRad, drawRad*2, drawRad*2);
land.add(new Area(ter));
And then basically the same except land.subtract(new Area(ter)) for erasing.
My problem with this is that after doing a lot of drawing it becomes very slow to draw the Area. the other problem is that I would like to be able to easily get the outline of the drawing, and I haven't found a good way of doing that using Areas. Using area.getPathIterator is not nearly accurate enough.
So I'm wondering what other ways of saving drawings are? I can't just have an array of Ellipses because then erasing wouldn't work.
Thanks!
If you are drawing the same thing over and over it may be worth while to draw it to an image once or load it from a file at start up and then just paint the image rather than painting all the individual shapes.
To load from a file, put your picture file in the same directory as your .java file and load:
BufferedImage img = ImageIO.read(this.getClass().getResource("picture.png"));
To draw on the image once:
BufferedImage img = new BufferedImage(width,height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = img.createGraphics();
In your paintComponent method you draw the image somewhere.
g.drawImage(img, 0, 0, this);
If you have something moving over a background, instead of adding and subtracting the moving item. Just draw the background and then draw the thing that moves, drawing the background will effectively erase the old position with less computation.

How to detect mouse over on drawn image with awt.Graphics.drawImage() when transformed

In a Java Swing panel I draw an image with arbitrary transfomation e.g.:
public void paintComponent(Graphics g){
AffineTransform transform = AffineTransform.getTranslateInstance(x, y);
AffineTransform rotateInstance AffineTransform.getRotateInstance(rotX, rotY);
transform.concatenate(rotateInstance);
g.setTransform(transform);
g.drawImage(image, 0, 0 , null);
}
What is the best way to detect mouse over on such an image?
Even better: the best way to detect mouse over only on non-transparent pixels?
Construct a Shape that encloses the image, and use the AffineTransform method createTransformedShape() to rotate the Shape along with the image. The Shape method contains() will allow for position testing in Component relative coordinates. Complete examples are seen here and here. Two approaches to inverse coordinate transformation are cited here.

How to scale only one object on JPanel using affine transform?

I have a Canvas class, which is an extension of JPanel. I need to draw multiple custom shapes on it and be able to resize them. I finished drawing all the elements, I did the logic for selecting those elements and drawing a section rectangle, but I can't resize them. I tried using affine transformation and the scale() method, but when I scale using those methods, it scales all elements on the canvas, not just one. Any idea how could I make it scale only one element, without scaling others?
Assuming your painting your elements within the paintComponent method...
Create a new copy of the Graphics context...
Graphics2D g2d = (Graphics2D)g.create();
Create and apply you affine transformation...
AffineTransform at = anew AffineTransform();
at.translate(...);
at.scale(...);
g2d.setTransform(at);
Paint your element(s) and dispose of the Graphics context you have created...
//... Paint...
g2d.dispose();
Repeat as required.
The other method might be to get the current transformation and re-apply it when your done...
AffineTransform currenrAT = g2d.getTransform();
// Apply new transform and paint...
g2d.setTransform(currentAT);

Drawing specific parts of Graphics2D

I have written a game, and now I would like to learn how to manipulate camera.
My drawing consists of this:
private void render()
{
// CREATE THE GRAPHICS
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
// MAKE THE PICTURE WHERE WE WILL PAINT EVERYTHING AT ONCE
g.clearRect(0, 0, WIDTH, HEIGHT);
// PAINT ANYTHING WE NEED HERE
render(g);
g.dispose();
// SHOW THE WHOLE IMAGE RATHER THAN PAININT ONE OBJECT AT A TIME
bufferStrategy.show();
}
My BufferStrategy is created like so:
canvas = new Canvas();
// once again I add 1 because java is stupid that's why
canvas.setBounds(0, 0, WIDTH+1, HEIGHT+1);
//canvas.setBounds(bounds);
canvas.setIgnoreRepaint(true);
// SET GRAPHICS DEVICE
canvas.createBufferStrategy(2);
bufferStrategy = canvas.getBufferStrategy();
In the render function I draw my game world with all the platforms where they should be. Now if the game world is bigger than the window size, and I would like to be able to focus on the character and draw the part of the world where character is, how would I do that? So let's say my window is 300 x 300, and my game world is 900 x 900, and my character is located in the middle so that I would like to display the part of the graphics where x is 150 y is 150 and the width and height is 300 x 300.
So how would I go about taking that Graphics2D and shifting it over by specified values? I am very sorry if this question has been answered or is easy, but I am new to this and really would like some help.
Thanks for any help in advance.
I have tried all I know to no avail.
So how would I go about taking that Graphics2D and shifting it over by specified values?
Why must you shift the Graphics2D? Why not create an image that extends beyond the viewport and simply shift the viewport. Then if the user gets close to the edge of the viewport, add an image to the leading edge and lop off a portion on the trailing edge.
This is what affine transformations are for.
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/geom/AffineTransform.html
Shift the character to the center of the screen by applying a shift.
In your paint component, save the current transformation.
Create a new transformation that will then shift the screen to where you would like it to be.
Set Graphics2D to use your new transformation.
Draw the character at the original coordinates
Set Graphics2D to use the original transformation.

Rotational Pixel-Perfect Collision Detection

So I am working on an Android game and I have two images on the screen. I currently have the pixel-perfect collision detection working great. My problem is when I rotate one of the images and I check the pixels for a collision. The pixels are still oriented in the original way the image was loaded, so it is not as perfect as it was... I can get all of the pixels in an array, or a 2d array. But I am currently just accessing them by the getPixel(x, y) method in the Bitmap class.
Does anyone know of an algorithm to rotate the values in an array based on an arbitrary number of degrees? Or any other way of solving this problem?
Have you looked at AffineTransform?
It's what I have used to rotate sprites and images in the past.
I used this code to rotate and get a pixel value from an image:
Image rotatedImage = new BufferedImage(imageToRotate.getHeight(null), imageToRotate.getWidth(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) rotatedImage.getGraphics();
// Set rotation here
g2d.rotate(Math.toRadians(90.0));
g2d.drawImage(imageToRotate, 0, -rotatedImage.getWidth(null), null);
g2d.dispose();
int pixelColor = ((BufferedImage)rotatedImage).getRGB(x, y);

Categories

Resources