Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (480)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (547)
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  
  [Fixed] Scaling a whole game x2 correctly  (Read 2843 times)
0 Members and 1 Guest are viewing this topic.
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Posted 2011-06-19 09:56:41 »

Hello!

Please consider these to pictures of my current WIP:
Unscaled:


Scaled x2 in super render method:



I'm using Slick2D by the way. The upper image shows the game, and it's working as it should.
The second image, shows the result when I'm doing a g.scale(2,2); in the upper-most rendering method (the one in the "main" class).

I'm obviously missing something because that wasn't quite the result I was looking for.

I've tried to multiply various different variables in the world-rendering, but it all just gave me wrong (though rahter interresting results).
Here it is, as it is when I am not trying to scale it:
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  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
@Override
   public void render(GameContainer container, Graphics g)
         throws SlickException {

     
      // Draw the current tile map, and the actors in it
     
      final TileMap map = model.getCurrentMap(); // Get the currently active (displayed) map from the game state
     final SpriteSheet graphics = RessourceManager.getRessourceManager().getGraphics(); // Get the sprite sheet

      Actor player = model.getPlayer();
      int px = player.getWorldX();
      int py = player.getWorldY();

      // Sets the offset of the viewport, depending on the players location and the fact that
     // the player is always the center of the viewport.
     int viewportOffsetX = CENTER_OFFSET_X-(px);
      int viewportOffsetY = CENTER_OFFSET_Y-(py);

      // Check boundaries for viewport (for cropping purposes - we do not want to loop through and draw tiles
     // which are outside the currently visible part of the map)
     int firstVisibleX = ((int)-viewportOffsetX)/RessourceManager.TILE_WIDTH;
      int lastVisibleX = Math.min(firstVisibleX+fitsInViewX+1, map.getWidth());
     
      int firstVisibleY = ((int)-viewportOffsetY)/RessourceManager.TILE_HEIGHT;
      int lastVisibleY = Math.min(firstVisibleY+fitsInViewY+1, map.getHeight());
     
      graphics.startUse(); // Until released by endUse, only graphics from this sprite sheet will be drawn, but they will be drawn faster.

      // Draw all visible tiles (with contents, if any)
     for (int x = firstVisibleX; x<lastVisibleX; x++)
      {
         int currentXOffset = x*RessourceManager.TILE_WIDTH;
         for (int y = firstVisibleY; y<lastVisibleY; y++)
         {
            int currentYOffset = y*RessourceManager.TILE_HEIGHT;
            if (x >= 0 && y >=0)
            {
                                        // Rendering the first layer - raw tiles
              Tile tile = map.getTile(x, y);
               if (tile != null)
               {
                  // Using the image reference key from the tile's type, retrieve and draw the terrain image
                 TILE_TYPE type = map.getTile(x, y).getType();
                  RessourceManager.IMAGE image = type.getImage();
                  Image imageToDraw = graphics.getSubImage(image.getSheetColumn(), image.getSheetRow());
                  imageToDraw.drawEmbedded(viewportOffsetX+currentXOffset, viewportOffsetY+currentYOffset, RessourceManager.TILE_WIDTH, RessourceManager.TILE_HEIGHT); // Note that the drawEmbedded method is used to make use of the enhanced drawing speed.
              }
            }
         }
      }

                // Draw all characters
     for (int x = firstVisibleX; x<lastVisibleX; x++)
      {
         for (int y = firstVisibleY; y<lastVisibleY; y++)
         {
            if (x >= 0 && y >=0)
            {
                                        // Rendering second layer - characters
                                       Actor actor = model.getCharacterManager().getCharacter(x, y);
                                        if (actor != null)
                                        {
                                            Animation currentAnimation1 = actor.getCurrentAnimation();
                                            currentAnimation1.getCurrentFrame().drawEmbedded(viewportOffsetX+actor.getWorldX(),
                                                    viewportOffsetY+actor.getWorldY(), RessourceManager.TILE_WIDTH, RessourceManager.TILE_HEIGHT);
                                        }
            }
         }
      }
     
      // Draw the player's current animation
     Animation currentAnimation = player.getCurrentAnimation();
      currentAnimation.getCurrentFrame().drawEmbedded(viewportOffsetX+player.getWorldX(), viewportOffsetY+player.getWorldY(), RessourceManager.TILE_WIDTH, RessourceManager.TILE_HEIGHT);
     
      graphics.endUse(); // Release, so that graphics that are not in the sprite sheet can be used again.
  }


I think it's pretty self-explainatory what it does, so I wont go into greater detail about that.

I have never scaled anything successfully, so if you could provide me with a little info on what I got to look out for, that would be really nice  Smiley

Thanks for the help guys!

Offline ra4king

JGO Kernel


Medals: 345
Projects: 2
Exp: 5 years


I'm the King!


« Reply #1 - Posted 2011-06-19 23:21:00 »

Slick2D scales the screen from (0,0). Imagine the window as an image, double its width and height, then make sure the top left corner of the image is at the top left corner of the window. That's how things are scaled. If you want to center it, you should add a call to translate somewhere in there.

Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #2 - Posted 2011-06-20 11:53:32 »

Slick2D scales the screen from (0,0). Imagine the window as an image, double its width and height, then make sure the top left corner of the image is at the top left corner of the window. That's how things are scaled. If you want to center it, you should add a call to translate somewhere in there.

Well, that makes sence. Though not enough to apply it  Undecided

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

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #3 - Posted 2011-06-20 11:57:28 »

Although I haven't used Slick2D in a while
You should be able to do something like
1  
2  
3  
g.translate(someVar1, someVar2) //(move it to "center it" around 0,0)
g.scale2D( 2.0, 2.0 ) //scale up 2.0
g.translate( -someVar1, -someVar2)//move it back


or something like that, I think.


I found this, see if you can refactor it to work with your game
http://slick.javaunlimited.net/viewtopic.php?t=755

"Experience is what you get when you did not get what you wanted"
Offline ra4king

JGO Kernel


Medals: 345
Projects: 2
Exp: 5 years


I'm the King!


« Reply #4 - Posted 2011-06-20 16:33:26 »

Yeah as namrog showed, you should translate your rendering to 0,0, scale it, then translate it back to the original position.
Slick2D always scales from 0,0 so you should do this translate, scale, translate pattern everytime you want to scale one specific rendering. Then just set the the scale back at 1,1 when you're done.

Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #5 - Posted 2011-06-20 19:34:20 »

So by how much would I want to transform per scale?

Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #6 - Posted 2011-06-20 19:55:16 »

The specific value would depend upon on how everything is setup,

I would recommend just setting up the transform to some keys on keyboard and try to manipulate it ingame and see around/about what type of numbers you need for your setup.

It should be independent(separate) from the scale value itself,  it doesn't need to be a dependent upon a particular scale.

"Experience is what you get when you did not get what you wanted"
Offline pitbuller
« Reply #7 - Posted 2011-06-20 21:24:34 »

So by how much would I want to transform per scale?

Edit: My method didn't worked on all setups so I snipped it away.
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #8 - Posted 2011-06-21 11:19:03 »

Alright, so I can now align it manually until I feel the screen is where it should be. But, I actually want to be able to calculate it based on a zoom-factor in-game. How much would I want to translate, per scale? It's definately not the same amount.
Is there any way I can calculate this or something?

Offline pitbuller
« Reply #9 - Posted 2011-06-21 11:53:44 »

Alright, so I can now align it manually until I feel the screen is where it should be. But, I actually want to be able to calculate it based on a zoom-factor in-game. How much would I want to translate, per scale? It's definately not the same amount.
Is there any way I can calculate this or something?
Try dividing amount of translate by scalefactor.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #10 - Posted 2011-06-21 12:02:52 »

Alright, so I can now align it manually until I feel the screen is where it should be. But, I actually want to be able to calculate it based on a zoom-factor in-game. How much would I want to translate, per scale? It's definately not the same amount.
Is there any way I can calculate this or something?

Yes I was wrong in my original statement,  if you wanted a dynamic zoom then youd need a scaling factor

Id suggest trying something like
1  
translateX = -screenWidth + screenWidth / scale; 


Or use whatever number you found in place of screenwidth to work

What type of numbers does it take when you align manually? 

"Experience is what you get when you did not get what you wanted"
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #11 - Posted 2011-06-26 08:21:03 »

I just tried appying this:
1  
2  
g.scale(2,2);
g.translate(-800 +800/2, -600+600/2);

In the start of my render loop. It makes what's supposed to be the middle of the screen, lie in the 0,0 coordinates.
So it moves 800/2, 600/2 to the upper left corner of the screen. I'll try a manual align and post the results now.

Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #12 - Posted 2011-06-26 08:23:14 »

1  
g.translate(-800/2+800/2, -600/2+600/2);

Gives the exact opposite result. The middle is now @ the downer right corner.

Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #13 - Posted 2011-06-26 08:29:56 »

1  
g.translate(-800+1200/2, -600+900/2);


Appears to work, where my window width = 800 and height = 600.

Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #14 - Posted 2011-06-26 10:32:11 »

Be aware translate(double,double) behaves differently to translate(int,int).

The former concatenates the Graphics context's AffineTransformation with a translation matrix.
The latter just translates the origin of the current coordinate system (and in so doing creates a new coordinate system centered @ x/y)

For clean code (and your own sanity) I recommend you avoid using translate(int,int) as it becomes unintuitive when used in conjunction with the AffineTransforms. (rotate, translate, scale & shear)

To eliminate your apparent confusion, and improve your understanding I suggest you recode your program to use just get/setTransform.
Doing this will make the code dealing with the transformation concatenations much more verbose, and easier to understand.
It'll also highlight to you when you are performing inverse transformations that run the risk of accruing rounding errors.
In short the transformation process should always be:
STORE, TRANSFORM, RENDER, RESTORE; not TRANSFORM, RENDER, INVERSE TRANSFORM

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #15 - Posted 2011-06-28 07:51:12 »

Be aware translate(double,double) behaves differently to translate(int,int).

The former concatenates the Graphics context's AffineTransformation with a translation matrix.
The latter just translates the origin of the current coordinate system (and in so doing creates a new coordinate system centered @ x/y)

For clean code (and your own sanity) I recommend you avoid using translate(int,int) as it becomes unintuitive when used in conjunction with the AffineTransforms. (rotate, translate, scale & shear)

To eliminate your apparent confusion, and improve your understanding I suggest you recode your program to use just get/setTransform.
Doing this will make the code dealing with the transformation concatenations much more verbose, and easier to understand.
It'll also highlight to you when you are performing inverse transformations that run the risk of accruing rounding errors.
In short the transformation process should always be:
STORE, TRANSFORM, RENDER, RESTORE; not TRANSFORM, RENDER, INVERSE TRANSFORM

I'm a bit left off here, but you're saying that translate(double, double) will benefit me when transforming right? I don't get the store, transform, render, restore-praxis. What's the store/restore states?

Offline pitbuller
« Reply #16 - Posted 2011-06-28 09:02:33 »

Be aware translate(double,double) behaves differently to translate(int,int).

The former concatenates the Graphics context's AffineTransformation with a translation matrix.
The latter just translates the origin of the current coordinate system (and in so doing creates a new coordinate system centered @ x/y)

For clean code (and your own sanity) I recommend you avoid using translate(int,int) as it becomes unintuitive when used in conjunction with the AffineTransforms. (rotate, translate, scale & shear)

To eliminate your apparent confusion, and improve your understanding I suggest you recode your program to use just get/setTransform.
Doing this will make the code dealing with the transformation concatenations much more verbose, and easier to understand.
It'll also highlight to you when you are performing inverse transformations that run the risk of accruing rounding errors.
In short the transformation process should always be:
STORE, TRANSFORM, RENDER, RESTORE; not TRANSFORM, RENDER, INVERSE TRANSFORM

I'm a bit left off here, but you're saying that translate(double, double) will benefit me when transforming right? I don't get the store, transform, render, restore-praxis. What's the store/restore states?
At slick there is Graphics.push() and Graphics.pop().
You put current transform to stack and then you can restore it later. Just like at assembly when storing registers.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #17 - Posted 2011-06-28 17:21:16 »

Yes, applying the inverse transform can end up with rounding errors that will degrade your game over time. It also is an extra operation you don't need.

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.

atombrot (24 views)
2014-08-19 09:29:53

Tekkerue (24 views)
2014-08-16 06:45:27

Tekkerue (23 views)
2014-08-16 06:22:17

Tekkerue (13 views)
2014-08-16 06:20:21

Tekkerue (20 views)
2014-08-16 06:12:11

Rayexar (58 views)
2014-08-11 02:49:23

BurntPizza (38 views)
2014-08-09 21:09:32

BurntPizza (30 views)
2014-08-08 02:01:56

Norakomi (37 views)
2014-08-06 19:49:38

BurntPizza (67 views)
2014-08-03 02:57:17
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

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!