Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (538)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (600)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  2D-sprites and screen resolution  (Read 7528 times)
0 Members and 1 Guest are viewing this topic.
Offline CuriousBob

Junior Newbie





« Posted 2011-02-14 03:15:19 »

Hi,
i'm currently starting a new 2D game project and so far i've always had a fixed 1024x768 screen resolution and fixed locations of things on the screen, but this time i want to make it a bit more dynamic. The user should be able to change it to a resolution that he wants and everything should scale to the wanted size.

Is there a simple way to scale the 2D sprites to another size? Let's say i have a few 1024x768 Jpegs that should now get scaled to a 1920x1080 resolution as soon as the level starts. What's the best way to do that?

As i said, i've always had fixed starting locations like x=256, y=252. How can i adjust these values to the resolution? Should i just work with something like x=frameWidth*(1/4) y=frameHeight*(1/3)  or is there some kind of factor that i could multiply my coordinates with? For example x=256*widthResolutionFactor, y=252*heightResolutionFactor.
Offline IronclawsBt

Junior Devvie


Medals: 1



« Reply #1 - Posted 2011-02-14 03:36:33 »

If all you want to do is draw the exact same scene, just scaled to the users screen resolution, use an AffineTransform. The most direct way is just to call Graphics2D g.scale(double sx, double sy) with appropriate scaling parameters to scale your original scene dimensions to the screen dimensions. If you want to scale individual sprites you can get a Graphics2D object for a buffered image and use the same method to draw a scaled version of your original sprite to this new sprite.

It's not what you know, it's what other people think you know.
Just hope you don't get quizzed on it.
Game engine design tutorials
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #2 - Posted 2011-02-14 07:19:17 »

The best way to do this is to draw each frame into a BufferedImage with the default width and height of a window.
Then you can just call this non-static method:
1  
Graphics.drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer);

where dx1 and dy1 are your destination top left points, hence (0,0); dx2 and dy2 are your destination bottom right points, (1920,1080)
sx1 and sy1 are you source top left points, (0,0); sx2 and sy2 are your source bottom right points (1024,768)
And you can just ignore the observer parameter by supplying null if you do not need to use it.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline CuriousBob

Junior Newbie





« Reply #3 - Posted 2011-02-14 18:24:34 »

Thanks to both of you.

The Graphics.drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer); function works perfectly Smiley.
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #4 - Posted 2011-02-14 23:43:17 »

Glad to help Smiley

Offline GustavXIII

Junior Devvie


Projects: 1



« Reply #5 - Posted 2011-02-18 13:13:07 »

I had the same Problem.
I know how I scale the graphics to the screen dimension.
But what I didnt know was how I have to change the Coordinates like Player_X/Y or the Position from the NPCs?

Like the NPC "Bob" is on X=200,Y=220. I take this position on a 800x600 Dimension. But now if I change the screen resulution then the coordinates are wrong. Is there a formular to fix all Coordinates and Collisions on the Screen Resolution?
Offline refri89

Senior Newbie





« Reply #6 - Posted 2011-02-18 20:11:03 »

for new coordinates in new resolution:

x_new  =  positionOld_X / resolutionOld_X * resolutionNew_X;
y_new  =  positionOld_Y / resolutionOld_Y * resolutionNew_Y;

in your example (use double, not int):

positionOld_X = 200.0;
positionOld_Y = 220.0;
resolutionOld_X = 800.0;
resolutionOld_Y = 600.0;
resolutionNew_X = 1024.0;
resolutionNew_Y = 768.0;
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #7 - Posted 2011-02-18 20:35:00 »

You can do everything a lot more easily.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scale;

public void calculateScale()
{
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scale = Math.min( (float)d.getWidth() / NORMAL_WIDTH, (float)d.getHeight() / NORMAL_HEIGHT );
}

public void draw(Graphics g)
{
    ((Graphics2D)g).scale(scale,scale);

    drawAllMyCrap(g);

    ((Graphics2D)g).scale(1/scale,1/scale);
}


Then in drawAllMyCrap() just draw everything on a screen as if it were NORMAL_WIDTH x NORMAL_HEIGHT.

See my work:
OTC Software
Offline fletchergames

Senior Devvie





« Reply #8 - Posted 2011-02-20 04:45:53 »

If you're using mouse controls, your mouse coordinates will no longer match the coordinates of objects on the screen after you stretch the graphics.  You'll have to take that into account.
Offline Abuse

JGO Knight


Medals: 14


falling into the abyss of reality


« Reply #9 - Posted 2011-02-20 09:38:41 »

You can do everything a lot more easily.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scale;

public void calculateScale()
{
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scale = Math.min( (float)d.getWidth() / NORMAL_WIDTH, (float)d.getHeight() / NORMAL_HEIGHT );
}

public void draw(Graphics g)
{
    ((Graphics2D)g).scale(scale,scale);

    drawAllMyCrap(g);

    ((Graphics2D)g).scale(1/scale,1/scale);
}


Then in drawAllMyCrap() just draw everything on a screen as if it were NORMAL_WIDTH x NORMAL_HEIGHT.

Don't concatenate inverse transforms or you'll end up with rounding errors.
Store, and then restore the AffineTransform.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #10 - Posted 2011-02-20 19:37:46 »

You can do everything a lot more easily.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scale;

public void calculateScale()
{
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scale = Math.min( (float)d.getWidth() / NORMAL_WIDTH, (float)d.getHeight() / NORMAL_HEIGHT );
}

public void draw(Graphics g)
{
    ((Graphics2D)g).scale(scale,scale);

    drawAllMyCrap(g);

    ((Graphics2D)g).scale(1/scale,1/scale);
}


Then in drawAllMyCrap() just draw everything on a screen as if it were NORMAL_WIDTH x NORMAL_HEIGHT.

Don't concatenate inverse transforms or you'll end up with rounding errors.
Store, and then restore the AffineTransform.
Ooh, there's a way to do that? I do it in OpenGL with push and pop but I couldn't find any equivalent functions in Java2D. Do you need to do with with getTranform() setTransform() or what?

Also @fletchergames, good point about the mouse transformation that must also be applied.

See my work:
OTC Software
Offline onlytoine

Senior Newbie





« Reply #11 - Posted 2011-03-16 16:07:43 »

I'm wondering is this kind ox processing (image scaling) to fit with another resolution might not be uggly in some case?

Like a pixelisation effect and performance loose...

Toine
Offline IronclawsBt

Junior Devvie


Medals: 1



« Reply #12 - Posted 2011-03-16 16:48:09 »

I depends on what method is used to scale, but yes it can look ugly. The faster the interpolation method is the worse it generally looks. One way you can get around this is to scale the images once when the game starts up. Performance is less of an issue then so you can use the best looking interpolation available.

It's not what you know, it's what other people think you know.
Just hope you don't get quizzed on it.
Game engine design tutorials
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #13 - Posted 2011-03-23 23:37:52 »

I'm wondering is this kind ox processing (image scaling) to fit with another resolution might not be uggly in some case?

Like a pixelisation effect and performance loose...

Toine
Generally you'd see this issue in whatever scenario. If your images are at the maximum size and you always scale down, typically things are good.

See my work:
OTC Software
Offline GustavXIII

Junior Devvie


Projects: 1



« Reply #14 - Posted 2011-03-24 11:53:14 »

Do you think it is better to set the Resolution on the Users Resolution.
 AppGameContainer app = new AppGameContainer(new Spiel());
app.setDisplayMode(d.width,d.height, false);

Or should I put a fix Resolution like
AppGameContainer app = new AppGameContainer(new Spiel());
app.setDisplayMode(800,600, false);

Quote
Don't concatenate inverse transforms or you'll end up with rounding errors.
Store, and then restore the AffineTransform.

What does that mean? I used the Code from Eli Delventhal and it seem to work. ô.o

EDIT. Ah and if its important Im using Slick and LWJGL.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #15 - Posted 2011-04-07 17:34:50 »

Do you think it is better to set the Resolution on the Users Resolution.
 AppGameContainer app = new AppGameContainer(new Spiel());
app.setDisplayMode(d.width,d.height, false);

Or should I put a fix Resolution like
AppGameContainer app = new AppGameContainer(new Spiel());
app.setDisplayMode(800,600, false);

Quote
Don't concatenate inverse transforms or you'll end up with rounding errors.
Store, and then restore the AffineTransform.

What does that mean? I used the Code from Eli Delventhal and it seem to work. ô.o

EDIT. Ah and if its important Im using Slick and LWJGL.

He's saying don't do the opposite transform to scale back (1.0f/scale) because it causes rounding errors. Instead, you want to store the previous transform and then restore it.

So that would be like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scale;
 
public void calculateScale()
{
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scale = Math.min( (float)d.getWidth() / NORMAL_WIDTH, (float)d.getHeight() / NORMAL_HEIGHT );
}
 
public void draw(Graphics g)
{
    AffineTransform transform = ((Graphics2D)g).getTransform();

    ((Graphics2D)g).scale(scale,scale);
 
    drawAllMyCrap(g);
 
    ((Graphics2D)g).setTransform(transform);
}


Oh. You're using LWJGL.

1  
2  
3  
4  
5  
6  
7  
8  
9  
public void draw()
{
    GL11.glPushMatrix();
    GL11.glScalef(scale,scale,1.0f);

    drawAllMyCrap();

    GL11.glPopMatrix();
}

See my work:
OTC Software
Offline The Cure

Senior Newbie





« Reply #16 - Posted 2012-07-31 21:12:40 »


....

So that would be like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scale;
 
public void calculateScale()
{
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scale = Math.min( (float)d.getWidth() / NORMAL_WIDTH, (float)d.getHeight() / NORMAL_HEIGHT );
}
 
public void draw(Graphics g)
{
    AffineTransform transform = ((Graphics2D)g).getTransform();

    ((Graphics2D)g).scale(scale,scale);
 
    drawAllMyCrap(g);
 
    ((Graphics2D)g).setTransform(transform);
}


Thank you very much Eli Delventhal, that code helped me a lot.

For those who don't want to keep the same scale for width and height, just change the code a little bit. Like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public static final int NORMAL_WIDTH = 1024;
public static final int NORMAL_HEIGHT = 768;
private float scaleWidth, scaleHeight;
 
public void calculateScale()
{
    scaleWidth = (float)Toolkit.getDefaultToolkit().getScreenSize().width / NORMAL_WIDTH;
    scaleHeight = (float)Toolkit.getDefaultToolkit().getScreenSize().height / NORMAL_HEIGHT;
}
 
public void draw(Graphics g)
{
    AffineTransform transform = ((Graphics2D)g).getTransform();

    ((Graphics2D)g).scale(scaleWidth, scaleHeight);
 
    drawAllMyCrap(g);
 
    ((Graphics2D)g).setTransform(transform);
}


You can also implement a HierarchyBoundsListener to the JFrame, and realize some tests changing the size of it to see what happens with all the drawing stuff. Like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
    //JFrame class implementing the HierarchyBoundsListener interface (to detect when the jframe resizes).

    ....

    @Override
    public void ancestorResized(HierarchyEvent e) {
        //'game' is the object to access a class extending Canvas or JPanel (where you're drawing the stuff).
        game.setSize(getWidth(), getHeight()); //just resizing a JPanel or Canvas to the same JFrame size.
        game.scaleWidth = (float)this.getWidth() / NORMAL_WIDTH;
        game.scaleHeight = (float)this.getHeight() / NORMAL_HEIGHT;
    }


    // and then the Game class extending Canvas (or Jpanel)

    ...

    //The Game class draw method using Canvas and BufferStrategy
    public void draw()
   {
        Graphics2D g2d = (Graphics2D) bufferStrategy.getDrawGraphics();
        AffineTransform transform = g2d.getTransform();
        g2d.scale(scaleWidth, scaleHeight);
        g2d.clearRect(0, 0, getWidth(), getHeight());
        //Draw all the stuff
        ...
       
        g2d.setTransform(transform);
        g2d.dispose();
        bufferStrategy.show();
    }
   


Really simple and newbie, but i hope it may help someone...

"A candle loses nothing by lighting another candle" - Erin Majors
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #17 - Posted 2012-08-05 17:01:19 »

You probably want to find the minimum scale between width and height and use that in uniform, then letterbox the rest. Otherwise you can end up with weird proportions on widescreen monitors and the like.

See my work:
OTC Software
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (29 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (40 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (50 views)
2014-12-03 16:27:13

CopyableCougar4 (47 views)
2014-11-29 21:32:03

toopeicgaming1999 (114 views)
2014-11-26 15:22:04

toopeicgaming1999 (102 views)
2014-11-26 15:20:36

toopeicgaming1999 (30 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!