How to render Hindi text in libgdx using mangal.ttf or any other font.
Square boxes are coming when try to print hindi text.
Try FreeTypeFont, FreetypeFont is available in maven repository so you can easily inject dependency through gradle in your project and use in your code.
public class MyGdxGame extends Game {
SpriteBatch spriteBatch;
BitmapFont font;
OrthographicCamera camera;
GlyphLayout glyphLayout,glyphLayout1;
String text,text1;
#Override
public void create() {
camera=new OrthographicCamera();
camera.setToOrtho(false,400,640);
spriteBatch = new SpriteBatch();
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Mangal.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.color = Color.WHITE;
parameter.magFilter = Texture.TextureFilter.Linear; // used for resizing quality
parameter.minFilter = Texture.TextureFilter.Linear;
//ँंंःअआइईउऊऋएऐऑओऔकखगघचछजझञटठडढणतथदधनपफबभमयरलवशषसह़ािीुूृॅेैॉोौ्
parameter.characters = "शुभ प्रभात आप का स्वागत है"; //The characters the font should contain
parameter.size=15;
font=generator.generateFont(parameter);
font.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
font.setColor(1.0f, 0.0f, 0.0f, 1.0f);
generator.dispose();
text="शुभ प्रभात";
text1="आप का स्वागत है";
glyphLayout=new GlyphLayout(font,text);
glyphLayout1=new GlyphLayout(font,text1);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(1,1,0,1);
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.begin();
font.draw(spriteBatch,text,camera.viewportWidth*.5f-glyphLayout.width/2f,camera.viewportHeight*.5f);
font.draw(spriteBatch,text1,camera.viewportWidth*.5f-glyphLayout1.width/2f,camera.viewportHeight*.4f);
spriteBatch.end();
}
#Override
public void resize(int width, int height) {
camera.setToOrtho(false,width,height);
}
#Override
public void dispose() {
font.dispose();
spriteBatch.dispose();
}
}
Output looks like this :
We can use "Chanakya" font for render the Hindi Text in correct way. Download the chanyaka.ttf from hera :
http://indiatyping.com/index.php/download/199-chanakya-font
After installing the font . You should encode your Hindi text using the coverter :
http://indiatyping.com/index.php/font-converter/unicode-to-chanakya-font-converter
Once converted the text, simply copy it to your destination and you should be good to go!
Enjoy :)
Related
Is it possible to change the colour of one word in a
phrase using Label in libgdx, my idea is on my dialog box some importante words like important places, or names have a different color than the rest of the text to make them stand out.
I think you don't need to use any third party artifact, LibGDX has built in API for your requirement. You can use color markup language, that Label supports as well.
Enable markupEnabled on the BitmapFont
font.getData().markupEnabled = true;
I've some code
public class MyGdxGame extends ApplicationAdapter {
private Stage stage;
private BitmapFont bitmapFont;
#Override
public void create () {
stage=new Stage();
bitmapFont=new BitmapFont(Gdx.files.internal("Roboto-Medium_24.fnt"));
bitmapFont.getData().markupEnabled=true;
bitmapFont.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
Label label=new Label("Welcome to [BLUE]LibGDX, []Game development framework \n" +
"\nPublish your games on [GREEN]Windows,[] [#00FFFF]Mac, []Linux, [#FFFF00]Android,[] [BLACK]iOS,[] BlackBerry and HTML5, all with the same code base. ",new Label.LabelStyle(bitmapFont, Color.WHITE));
label.setPosition(20,340);
label.setWrap(true);
label.setWidth(500);
stage.addActor(label);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void dispose () {
stage.dispose();
bitmapFont.dispose();
}
}
Output :
I was wondering if I am doing something wrong (most likely) or if there is an issue with LibGDX SkinLoader regarding additional resource dependencies.
According to the documentation of SkinLoader.SkinParameter you can pass an additional ObjectMap to define resources that the skin depends on.
I wanted to use that for bitmap fonts because I am creating them at runtime out of a .ttf file to be able to create the correct font sizes for the correct density/size of the target device's display.
Here is an example program that causes the issue:
public class Test extends Game {
private AssetManager assetManager;
private Skin skin;
private Batch batch;
#Override
public void create() {
this.assetManager = new AssetManager();
final FileHandleResolver resolver = new InternalFileHandleResolver();
assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
assetManager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
final ObjectMap<String, Object> resources = new ObjectMap<String, Object>();
final FreetypeFontLoader.FreeTypeFontLoaderParameter fontParam = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
fontParam.fontFileName = "ui/font.ttf";
fontParam.fontParameters.size = (int) (16 * Gdx.graphics.getDensity());
assetManager.load("font16.ttf", BitmapFont.class, fontParam);
assetManager.finishLoading();
resources.put("font_16", assetManager.get("font16.ttf", BitmapFont.class));
assetManager.load("ui/ui.json", Skin.class, new SkinLoader.SkinParameter(resources));
assetManager.finishLoading();
skin = assetManager.get("ui/ui.json", Skin.class);
batch = new SpriteBatch();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
skin.get("font_16", BitmapFont.class).draw(batch, "Test123", 10, 10);
batch.end();
}
#Override
public void dispose() {
super.dispose();
// enabling the next line will get rid of the Pixmap already disposed exception
// skin.remove("font_16", BitmapFont.class);
assetManager.dispose();
batch.dispose();
}
}
Now when disposing the assetManager at the end of the program then I got an exception "Pixmap already disposed" because the bitmap fonts got disposed multiple times (once when the Skin gets disposed and once when the Bitmap font itself gets disposed).
To solve that for now I called skin.remove(fontName, BitMapFont.class) before assetManager.dispose() to release the bitmap fonts only once BUT imo this is not a nice way and I would expect that the dependency handling of the assetManager should take care of that.
I checked the code of the SkinLoader class and to me it seems like those passed resources are not added as a dependency of the Skin and that is why this error occurs.
My question now is:
Did I do something wrong or does anyone have a working code for that to show how the resourcesmap should be used in the correct way?
Found a topic which is related to this but seems like it never got a real answer
I have got the answer that I needed. Actually it is not an issue with the asset manager. It is an issue with the Skin class.
Look at the dispose method:
public void dispose () {
if (atlas != null) atlas.dispose();
for (ObjectMap<String, Object> entry : resources.values()) {
for (Object resource : entry.values())
if (resource instanceof Disposable) ((Disposable)resource).dispose();
}
}
It disposes any resource directly which is then not reflected in the asset manager of course and therefore the asset manager will also dispose the created bitmap fonts.
To solve this issue I wrote my own loader and Skin class. In case anyone is interested here is the code:
public class SkinLoader extends AsynchronousAssetLoader<Skin, SkinLoader.SkinParameter> {
public static class SkinParameter extends AssetLoaderParameters<Skin> {
private final String fontPath;
private final int[] fontSizesToCreate;
public SkinParameter(final String fontPath, final int... fontSizesToCreate) {
if (fontPath == null || fontPath.trim().isEmpty()) {
throw new GdxRuntimeException("fontPath cannot be null or empty");
}
if (fontSizesToCreate.length == 0) {
throw new GdxRuntimeException("fontSizesToCreate has to contain at least one value");
}
this.fontPath = fontPath;
this.fontSizesToCreate = fontSizesToCreate;
}
}
public SkinLoader(final FileHandleResolver resolver) {
super(resolver);
}
#Override
#SuppressWarnings("unchecked")
public Array<AssetDescriptor> getDependencies(final String fileName, final FileHandle file, final SkinParameter parameter) {
if (parameter == null) {
throw new GdxRuntimeException("SkinParameter cannot be null");
}
// texture atlas dependency
final Array<AssetDescriptor> dependencies = new Array<AssetDescriptor>();
dependencies.add(new AssetDescriptor(file.pathWithoutExtension() + ".atlas", TextureAtlas.class));
// bitmap font dependencies
for (int fontSize : parameter.fontSizesToCreate) {
final FreetypeFontLoader.FreeTypeFontLoaderParameter fontParam = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
fontParam.fontFileName = parameter.fontPath;
// enable anti-aliasing
fontParam.fontParameters.minFilter = Texture.TextureFilter.Linear;
fontParam.fontParameters.magFilter = Texture.TextureFilter.Linear;
// create font according to density of target device display
fontParam.fontParameters.size = (int) (fontSize * Gdx.graphics.getDensity());
dependencies.add(new AssetDescriptor("font" + fontSize + ".ttf", BitmapFont.class, fontParam));
}
return dependencies;
}
#Override
public Skin loadSync(final AssetManager manager, final String fileName, final FileHandle file, final SkinParameter parameter) {
// load atlas and create skin
final String textureAtlasPath = file.pathWithoutExtension() + ".atlas";
final TextureAtlas atlas = manager.get(textureAtlasPath, TextureAtlas.class);
final Skin skin = new Skin(atlas);
// add bitmap fonts to skin
for (int fontSize : parameter.fontSizesToCreate) {
skin.add("font_" + fontSize, manager.get("font" + fontSize + ".ttf"));
}
// load skin now because the fonts in the json file are now available
skin.load(file);
return skin;
}
#Override
public void loadAsync(final AssetManager manager, final String fileName, final FileHandle file, final SkinParameter parameter) {
}}
public class Skin extends com.badlogic.gdx.scenes.scene2d.ui.Skin {
Skin(final TextureAtlas atlas) {
super(atlas);
}
#Override
public void dispose() {
for (String bitmapFontKey : this.getAll(BitmapFont.class).keys()) {
remove(bitmapFontKey, BitmapFont.class);
}
super.dispose();
}}
I'm using libgdx in my 2D platformer game project for college task. For now I'm confused with loading tiledmap in libgdx. I have a big tmx map with size of 11400x1500 pixels and 30x30 tile size. Also an image with same pixel size which I load it in image layer. I try to load it but libgdx shows nothing.
My question is how to load single big tmx map or should I divide the map into several segment/section? Because I've tried other small tmx (3000x1500). If the tmx is divided then how to load them as one stage?
public class Layarloh implements Screen{
private JumatUtama game;
private TiledMap map;
private TmxMapLoader mapLoader;
private OrthographicCamera kamera;
private OrthogonalTiledMapRenderer mapRenderer;
private Viewport viewport;
public Layarloh(JumatUtama utama) {
float l=Gdx.graphics.getWidth(),t=Gdx.graphics.getHeight();
this.game = utama;
loadstage();
kamera = new OrthographicCamera();
kamera.setToOrtho(false,l,t);
kamera.update();
viewport = new FitViewport(l/3,t/3,kamera);
}
public void loadstage(){
mapLoader = new TmxMapLoader();
map = mapLoader.load("stage/s11.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
}
public void stik(float dt){
if (Gdx.input.isKeyPressed(Input.Keys.ANY_KEY))
kamera.position.x +=100*dt;
}
#Override
public void render(float delta) {
stik(delta);
kamera.position.set(550,550,0);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
#Override
public void resize(int width, int height) {
kamera.viewportWidth = viewport.getScreenWidth();
kamera.viewportHeight = viewport.getScreenHeight();
kamera.update();
}
Unitscale does nothing, the code above works on smaller size of tmx map.
EDIT
Code above isn't working, and the below is working, notice the maploader is loading different tmx file, above code trying to load 11400x1500 pixel with 30x30 tile size, while code below trying to load 3800x1500 with 30x30 tile size, but I try to use the code below to load bigger tmx, its not working,
public class Layarloh implements Screen{
private JumatUtama game;
private TiledMap map;
private TmxMapLoader mapLoader;
private OrthographicCamera kamera;
private OrthogonalTiledMapRenderer mapRenderer;
public Layarloh(JumatUtama utama) {
float l=Gdx.graphics.getWidth(),t=Gdx.graphics.getHeight();
this.game = utama;
loadstage();
kamera = new OrthographicCamera();
kamera.setToOrtho(false,l,t);
kamera.position.set(550,550,0);
kamera.update();
}
public void loadstage(){
mapLoader = new TmxMapLoader();
map = mapLoader.load("stage/segmen1.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
}
public void stik(float dt){
if (Gdx.input.isKeyPressed(Input.Keys.ANY_KEY))
kamera.position.x +=100*dt;
}
#Override
public void render(float delta) {
stik(delta);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
Try this code and this should fix it.
#Override
public void render(float delta) {
kamera.position.set(x, y, z);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
#Override
public void resize(int width, int height) {
kamera.viewportWidth = width;
kamera.viewportHeight = height;
kamera.update();
}
EDIT
In the original code, OP was missing kamera.update() statement. And also the resize method. That is something which causes trouble when displaying the tiled map properly as you need to update the camera at every iteration of render.
I'm developping games with LIBGDX on ANDROID. Today, i've tried to generate one of my project in a HTML5 version. I put the content of the WAR folder on my server. All is fine except 2 things. I'll present you here just one of these 2 issues.
The problem : when a texture has to be disposed (by the call of its method dispose()), i get a BufferUnderflowException. It happens everytime.
Here is the sample code which is automatically generated when you create a new project :
public class TexDispose implements ApplicationListener
{
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, h/w);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/libgdx.png"));
Gdx.input.setInputProcessor(this);
}
#Override
public void dispose() {
batch.dispose();
texture.dispose(); // HERE IS THE ERROR
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
}
#Override
public void resize(int width, int height) {
}
}
Has one of you already met this issue..? If yes, how can i avoid that (except by not disposing anything lol) ?
Thank you ! ;)
I've written an app that custom draws everything inside paint() based on fixed pixel positions. Then I disabled resize of the frame so its always visible.
However, now I would like to be able to resize it but I dont want to change my drawling code. I was hoping I could grab the 300x300 square of the Graphics g object and resize it to the JFrame current size after all of my drawling code, but I have no idea what I'm doing.
Here sample code. In this I want the 100x100 square to remain in the middle, proportionate to the resized JFrame:
package DrawAndScale;
import java.awt.Color;
import java.awt.Graphics;
public class DASFrame extends javax.swing.JFrame {
public DASFrame() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DASFrame().setVisible(true);
}
});
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fill3DRect(100, 100, 100, 100, true);
}
}
Thanks.
Assuming you rename your method that paints for 300x300 as paint300, define a buffered image:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300); // empty image
paint300(bufferImage.getGraphics()); // fill the image
g.drawImage(bufferImage, 0, 0, null); // send the image to graphics device
}
Above is when you want to draw at full size (300x300).
If your window is resized:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300);
paint300(bufferImage.getGraphics());
int width = getWidth();
int height = getHeight();
CropImageFilter crop =
new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
Image croppedImage = createImage(fis);
g.drawImage(croppedImage, 0, 0, null);
}
The new classes are from from java.awt.image.*.
I didn't test this code. It's just to send you in the right direction.
if you want to painting Custom paint then look for JLabel or JPanel and including Icon/ImageIcon inside, simple example about that
import java.awt.*;
import javax.swing.*;
public class MainComponentPaint extends JFrame {
private static final long serialVersionUID = 1L;
public MainComponentPaint() {
setTitle("Customize Preffered Size Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void display() {
add(new CustomComponent());
pack();
setMinimumSize(getSize());
setPreferredSize(getSize());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setVisible(true);
}
});
}
public static void main(String[] args) {
MainComponentPaint main = new MainComponentPaint();
main.display();
}
}
class CustomComponent extends JComponent {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
for (int i = 0; i < Math.max(w, h); i += 20) {
g.drawLine(i, 0, i, h);
g.drawLine(0, i, w, i);
}
}
}
Not an expert, but you could just scale the Graphics2D object (the passed Graphics is in fact a Graphics2D instance), where the x and y ratios are the ratios of the fixed size you chose to draw and the actual size of the frame.
See http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#scale%28double,%20double%29
You could do this with some math.
public void paint(Graphics g){
int height = 100;
int width = 100;
int x = (this.getWidth() / 2) - (width / 2);
int y = (this.getHeight() / 2) - (height / 2);
g.setColor(Color.BLACK);
g.fill3DRect(x, y, width, height, true);
}
Or if you wanted to keep the width and height of the box with the same proportion, use int width = this.getWidth() / 3; and int height = this.getHeight() / 3.
The other option is to use Graphics2D.scale(), as JB pointed out, the passed Graphics object is actually a Graphics2D object.