Sign in to follow this  
Halsafar

[java] Java2D Scaling/translating -- look same on any resolution

Recommended Posts

Halsafar    205
It seems the Graphic2D object comes with some functions to manipulate all passed in objects for rendering via Graphic2D. g2.translate() g2.scale() g2.transform() I am using the DirectX, especially D3D so having 0,0 in the top-left corner is undesireable. Linux doesn't support resolution changes. I have chosen a Base Resolution of 800x600. Maybe I'm just slow today but I cannot seem to picture how I can work Java2D in an arbitery "unit" space vs screen space. Trying to program Asteroids without resolution change and having it compatible and look the same on all resolutions with 0,0 as the center point seems to be a bit of a beotch.

Share this post


Link to post
Share on other sites
Halsafar    205
Using the functions listed how can I achieve or if it is possible a user defined space vs screen space.

As in, 0,0 = center screen. Units are user defined. Have it look the same on all resolutions while NOT being able to change the resolution.

Share this post


Link to post
Share on other sites
CaptainJester    523
You just need to set the AffineTransform to always move your user coordinates to screen coordinates. Here is an example. This will always draw a rectangle centered on the screen that is half the width and half the height.

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class Test extends JPanel {
private static double USER_SPACE_WIDTH = 200.0;
private static double USER_SPACE_HEIGHT = 200.0;
private int width;
private int height;
Dimension size;
AffineTransform affineTransform;

public Test() {
this(400, 400);
}
public Test(int width, int height) {
this.width = width;
this.height = height;
size = new Dimension(width, height);
//translate the screen so (0, 0) is at the center
affineTransform = AffineTransform.getTranslateInstance(
((double)width) / 2.0,
((double)height) / 2.0);
//scale the screen so user space is always 200 wide by 200 tall
affineTransform.concatenate(AffineTransform.getScaleInstance(
((double)width) / USER_SPACE_WIDTH,
((double)height) / USER_SPACE_HEIGHT));
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setTransform(affineTransform);
g2.fillRect(-50, -50, 100, 100);
}
public Dimension getMinimiumSize() {
return size;
}
public Dimension getMaximiumSize() {
return size;
}
public Dimension getPreferredSize() {
return size;
}
public static void main(String args[]) {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new Test(600, 600));
f.pack();
f.show();
}
}




If you are doing fullscreen mode, then you just need to get the current display size and plug those numbers in to the transform. You also need to try and limit your drawing to one class, because this transform needs to be applied with any custom drawing.

Also the order you build the transform is important. You should make sure you translate (0, 0) to center before you scale. This will make the calculation easier.

Share this post


Link to post
Share on other sites
Halsafar    205
That is very understandable thanks.

But are you positive that calling g2.setTransform() once doesn't have it stick forever?

I know I can call g2.translate() in my init function to center the drawings. I only call it once and render stuff all over.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this