libGDX Example Code : Experimenting Viewports with Text and Shape Animation for multiple screen Resolutions
I have already written a similar example to do text and line animation but I am writing this post to show how to animate text and Shape i.e. a line just below the text using viewports and cameras of LibGDX and the rendering is same on multiple screen resolutions .
The output of what we are doing will be as below :
If you are interested , lets start to code . While setup I have checked in Freetype,Tools and Box2D and have selected both Eclipse and IDEA from Advanced menu .
We will be using screens interface .
Once your libGDX setup is done . Open your code Game class and put in following :
package com.versionpb.viewports; import com.badlogic.gdx.Game; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class Viewportstrial extends Game { Texture img; private SpriteBatch batch; @Override public void create () { batch = new SpriteBatch(); setScreen(new VPBSplashScreen(this)); } @Override public void render () { super.render(); } public Batch getBatch(){ return this.batch; } }
We have basically removed ApplicationAdapter and have used Game to extend it , created a batch which can be used by all screens of our program .
Lets create VPBSplashScreen class which is the screen where we will be rending the Text and creating a line underneath only text is written completely . Once we create the class implement Screen Interface to it and implement all methods . it should be as below :
public class VPBSplashScreen implements Screen { public VPBSplashScreen(final Viewportstrial game){ this.game = game; } @Override public void show() { } @Override public void render(float delta) { } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } @Override public void hide() { } @Override public void dispose() { } }
Lets add below variables which we will be using in a while . comments are placed on each variable :
private Viewportstrial game; // to get the real game object to //access spritebatch private Sprite splashBGImage; //background Image private OrthographicCamera cam; //orthographic camera private Viewport viewport; //viewport private float Screen_Width,Screen_Height; // Virtual screen Width and Height private String str; // String to be displayed on screen private float w, h , pixelsToScreen_Width_Ratio,pixelsToScreen_Height_Ratio; private float widthofLine; // to get width of Line which will be drawn below Text private GlyphLayout glyphLayout; // Glyph layout private ShapeRenderer srend; //Shape Renderer private static final float TIMEPERCHAR = 0.1f; // play with this for dif speeds private float ctimeperchar = 0; // time per character for draw private int numchars = 0; // for parsing all chars in string float delta; private BitmapFont font; // Bitmap font private FreeTypeFontGenerator generator; //font generator private FreeTypeFontGenerator.FreeTypeFontParameter parameter; // Parameter
Lets now create the constructor of our Screen and initialize following :
- Shape Renderer
- generator for freetype fonts
- Background Image
- Orthographic Camera
- viewport
- glyphlayout to get height and width of fonts so rendering can be done
Comments is done after each line for understanding in below code and some explanation is done right after the code .
public VPBSplashScreen(final Viewportstrial game){ this.game = game; // getting the object of our Game Class srend = new ShapeRenderer(); // initializing the Shape Renderer . We are using //this to draw line , basically line will be a filled rectangle // Below Lines are generating font from free type i.e. .ttf generator = new FreeTypeFontGenerator(Gdx.files.internal("AlexBrush-Regular.ttf")); parameter = new FreeTypeFontGenerator.FreeTypeFontParameter(); parameter.size = 80; parameter.color = Color.WHITE; parameter.borderWidth = 2; parameter.borderColor = Color.FIREBRICK; parameter.borderStraight= true; parameter.shadowOffsetX= 10; parameter.shadowOffsetY= 10; parameter.shadowColor= new Color(0, 0, 0.1f, 0.75f); parameter.flip = false; font = generator.generateFont(parameter); //initializing background Image splashBGImage = new Sprite(new Texture(Gdx.files.internal("NiceGameBg.png"))); // Here we are defining of preferred screen width and height . //GameInfo is a class which keeps our constants . I will show it after a while Screen_Width = GameInfo.GAME_WIDTH; Screen_Height = GameInfo.GAME_HEIGHT; /* below 2 lines are most important . What we are doing here is getting the Ratio of Screen Width to our preferred Screen width I am calling this variable as pixelsToScreen_Width_Ratio . Lets say width X Height of Samsung S3 Mobile is 720 X 1280 and I am keeping my preferred screen width and height as 480 X 800 on Desktop . To render it properly and relatively we need these ratio s . width x height of nexus 5 is 1080 X 1776 . We can experiment this after full tutorial by changing values of DESKTOP_Game_Width and DESKTOP_Game_Height*/ pixelsToScreen_Width_Ratio = (float) Gdx.graphics.getWidth() / Screen_Width ; pixelsToScreen_Height_Ratio = (float) Gdx.graphics.getHeight() / Screen_Height ; // initializing the Orthographic Camera and setting its position cam = new OrthographicCamera(); cam.setToOrtho(false, Screen_Width/2 , Screen_Height/2 ); cam.position.set(Screen_Width/2 , Screen_Height/2,0); /* getting the aspect ratio so images can be adjusted accordingly , Not using in this example but kept it just to tell that this is important as well */ float aspectRaio = (float)Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth() ; /* There are many view ports available . We will be using Fit Viewport as part of this example .I have kept others commented so you can experiment with them to get a feel of what all are they and how to use them . */ //viewport = new FillViewport(Screen_Width , Screen_Height,cam); viewport = new FitViewport(Screen_Width , Screen_Height,cam); //viewport = new StretchViewport(Screen_Width , Screen_Height,cam); //viewport = new ExtendViewport(Screen_Width , Screen_Height,cam); //viewport = new ScreenViewport(cam); viewport.apply(); //Below code to get the width and height of full Text so we can render it on screen accordingly str = GameInfo.str; glyphLayout = new GlyphLayout(); glyphLayout.setText(font, str); w = glyphLayout.width; h = glyphLayout.height; /*initializing the widthOfLine to be drawn on screen below text . Initially its X co-ordinate should be same as Texts very first Letter So getting it by cam.viewpoetWidth/2 i.e. center of viewport minus full text length divided by 2 */ widthofLine = cam.viewportWidth / 2 - w / 2; // These are for logging various screen values . This will definitely help once you run the code and run experiments Gdx.app.log("LOG","Screen_Width " + Screen_Width); Gdx.app.log("LOG","Screen_Height: " + Screen_Height); Gdx.app.log("LOG","camera.viewportWidth : " + cam.viewportWidth); Gdx.app.log("LOG","camera.viewportHeight : " + cam.viewportHeight); Gdx.app.log("LOG","glyphLayout.width i.e. w " + w); Gdx.app.log("LOG","glyphLayout.height i.e. h : " + h); Gdx.app.log("LOG","GameInfo.WIDTH: " + GameInfo.GAME_WIDTH); Gdx.app.log("LOG","GameInfo.HEIGHT: " + GameInfo.GAME_HEIGHT); Gdx.app.log("LOG","Gdx.graphics.getWidth(): " + Gdx.graphics.getWidth()); Gdx.app.log("LOG","Gdx.graphics.getHeight(): " + Gdx.graphics.getHeight()); Gdx.app.log("LOG","viewport.getWorldWidth(): " + viewport.getWorldWidth()); Gdx.app.log("LOG","viewport.getWorldHeight(): " + viewport.getWorldHeight()); Gdx.app.log("LOG","viewport.getScreenWidth()): " + viewport.getScreenWidth()); Gdx.app.log("LOG","viewport.getScreenHeight(): " + viewport.getScreenHeight()); Gdx.app.log("LOG","cam.position.x " + cam.position.x); Gdx.app.log("LOG","cam.position.y : " + cam.position.y); Gdx.app.log("LOG","Aspect Ratio: " + aspectRaio); Gdx.app.log("LOG","pixelsToScreen_Width_Ratio: " + pixelsToScreen_Width_Ratio); Gdx.app.log("LOG","pixelsToScreen_Height_Ratio: " + pixelsToScreen_Height_Ratio); }
below 2 lines are most important . What we are doing here is getting the Ratio of Screen Width to our preferred Screen width I am calling this variable as pixelsToScreen_Width_Ratio . Lets say width X Height of Samsung S3 Mobile is 720 X 1280 and I am keeping my preferred screen width and height as 480 X 800 on Desktop . To render it properly and relatively we need these ratio s .
For example width x height of nexus 5 is 1080 X 1776 . Samsung S3 Mobile is 720 X 1280 , Apple might be something else and Samsung s8 might be a different one .
We can experiment this after full tutorial by changing values of DESKTOP_Game_Width and DESKTOP_Game_Height
pixelsToScreen_Width_Ratio = (float) Gdx.graphics.getWidth() / Screen_Width ;
pixelsToScreen_Height_Ratio = (float) Gdx.graphics.getHeight() / Screen_Height ;
I have explained all the initialization code in comments and point to note is that most important is to get the Pixels to Screen Ratio so whenever we are running the code on different screens resolutions the result is always the same .
Another important thing is the choosing of the correct viewport for the code . There are a couple of viewports available by libGDX . I recommend you to go through libGDX wiki for viewports here libGDX viewports Wiki .
Also Once you download the code and run it , Try uncommenting all the viewports one by one and experiment by changing the value of Game_width and Game_height which is in GameInfo Class .
GameInfo Class is just a class to keep my constants . Below is what i have there .
package com.versionpb.viewports; import com.badlogic.gdx.graphics.Color; public class GameInfo { public static final float Desktop_GAME_WIDTH = 480; public static final float Desktop_GAME_HEIGHT = 800; public static final float LineOffsetX = 25; public static final float LineAdjustmentOffsetX = 75; public static final float GAME_WIDTH = 480; public static final float GAME_HEIGHT = 800; public static final float Rectangle_Width = 5; public static final Color SplashScreenUnderLineColor =Color.WHITE; public static final String str = "Welcome"; }
Here Str is the String which we will show on the Screen .
Game_WIDTH/GAME_HEIGHT is the value which you will use to experiment the viewport rendering
LineOffsetX is a value which we will move left from screen to render text .
LineAdjustmentOffSet is another weirdly interesting parameter which i will explain in a while
Below code contains our render method .
@Override public void render(float delta) { cam.update(); // important to update your camera at each step game.getBatch().setProjectionMatrix(cam.combined); // setting projection matrix game.getBatch().begin(); //begin the batch //draw background Image game.getBatch().draw(splashBGImage,0,0,cam.viewportWidth,cam.viewportHeight); //Below piece of code to render the text on center of screen one at a time str=GameInfo.str; if (numchars < str.length()) { // if num of chars are lesser than string length , if all chars are not parsed ctimeperchar += delta; // character time per char to be added with delta if (ctimeperchar >= TIMEPERCHAR) { // if c time ie greater than time // for 1 char ctimeperchar = 0; // make ctimeper char again 0 numchars++; // go to next character , to be printed } } str = str.substring(0, numchars); // get string to be printed font.draw(game.getBatch(), str, cam.viewportWidth / 2 - w / 2, cam.viewportHeight / 2 + h / 2); game.getBatch().end(); //Here we check if full text is rendered only then start rendering the line if(str.equalsIgnoreCase(GameInfo.str)) { srend.begin(ShapeRenderer.ShapeType.Filled); // using a filled shape i.e. filled rectangle srend.setColor(GameInfo.SplashScreenUnderLineColor); // set color of rectangle /* draw rectangle on the screen . Here are those pixel to Screen ratios used . Try running without these and you will understand how important it is */ srend.rectLine( (cam.viewportWidth / 2 - w / 2 + GameInfo.LineOffsetX) * pixelsToScreen_Width_Ratio, (cam.viewportHeight/ 2 - h) * pixelsToScreen_Height_Ratio, (widthofLine + GameInfo.LineOffsetX + GameInfo.LineAdjustmentOffsetX) * pixelsToScreen_Width_Ratio, (cam.viewportHeight/ 2 - h) * pixelsToScreen_Height_Ratio, GameInfo.Rectangle_Width); srend.end(); // Logic to animate the line update(); } } private void update(){ if(widthofLine < w ) widthofLine += 10; }
Another important thing is our resize method and dispose method . You can see it from the full source code available at this github repository .
Once you download the code . To experiment . Just change the values of :
- DESKTOP_Game_WIDTH/DESKTOP_GAME_HEIGHT and try running code
- Str Value . Believe me this is very interesting . Change value from Welcome to VersionPB and you will see the line not covering the text properly and here comes the parameter LineAdjustmentOffSet into picture . Change its value to 0 for VersionPB and see .
- Experiment using different viewports in the main Screen Class .
Complete Running code with assest is at this repo
For any suggestions . Please leave a message .
Below is how this executed on a Desktop 480 X 800
See Below Example with String as VersionPB and DESKTOP_GAME_WIDTH and DESKTOP_GAME_HEIGHT as 900 x 600 .
public static final float Desktop_GAME_WIDTH = 900; public static final float Desktop_GAME_HEIGHT = 600;
See Below Experiment with interesting Value with String as VersionPB and DESKTOP_GAME_WIDTH and DESKTOP_GAME_HEIGHT as 1080x 200 .
public static final float Desktop_GAME_WIDTH = 1080; public static final float Desktop_GAME_HEIGHT = 200;
- 1 : Overview
- 2 : Environment SetUp
- 3 : Creating Project in libGDX
- 4 : Importing Projects in Eclipse
- 5 : Executing demo project for Windows
- 6 : Executing demo project for Android
- 7 : Executing demo project for HTML5
- 8 : Developing a real flappy bird game remake game using libGDX from scratch
- 9 : Environment Set Up for Game
- 10 : Understand basics of Game
- 11 : Exploring States and Game State Manager
- 12 : Create Play State and Make Bird Fly
- 13 : Building Obstacles and flying through them
- 14 : Collision and sound effect
- 15 : Porting the Game in Android Device
- 16 : libGDX More possibilities to Brisky Demo
- libGDX Example Code : Implementing Google Play Services Leader Boards in LibGDX
- libGDX Example Code : Text and line Animation
- libGDX Example Code : Experimenting Viewports with Text and Shape Animation for multiple screen Resolutions
- Step by Step Tutorial on libGDX
Table of Contents
- Overview of libGDX
- Environment SetUp
- Creating Project in libGDX
- Importing Projects in Eclipse
- Executing demo project for Windows
- Executing demo project for Android
- Executing demo project for HTML5
- Developing a real flappy bird game remake game using libGDX from scratch
- Environment Set Up for Game
- Understand basics of Game
- Exploring States and Game State Manager
- Create Play State and Make Bird Fly
- Building Obstacles and flying through them
- Collision and sound effect
- Porting the Game in Android Device
- libGDX More possibilities to Brisky Demo
Table of Contents
- 1 : Overview
- 2 : Environment SetUp
- 3 : Creating Project in libGDX
- 4 : Importing Projects in Eclipse
- 5 : Executing demo project for Windows
- 6 : Executing demo project for Android
- 7 : Executing demo project for HTML5
- 8 : Developing a real flappy bird game remake game using libGDX from scratch
- 9 : Environment Set Up for Game
- 10 : Understand basics of Game
- 11 : Exploring States and Game State Manager
- 12 : Create Play State and Make Bird Fly
- 13 : Building Obstacles and flying through them
- 14 : Collision and sound effect
- 15 : Porting the Game in Android Device
- 16 : libGDX More possibilities to Brisky Demo
- libGDX Example Code : Implementing Google Play Services Leader Boards in LibGDX
- libGDX Example Code : Text and line Animation
- libGDX Example Code : Experimenting Viewports with Text and Shape Animation for multiple screen Resolutions
- Step by Step Tutorial on libGDX