I am trying to make a "Share Score" button in my game. Part of what I want to do as part of the score sharing is create a little graphic that has the game logo along with the user's score. This graphic will then be shared via whatever platform the user chooses. However, I am stuck on generating this graphic. Right now I have a base graphic that has the logo, but I need a way to draw text onto that graphic (i.e. draw the users score onto it) using libGDX.
In other words, is there a way to write text onto the a Pixmap in order to do this?
Thanks
You can use FrameBuffer object for your requirement then read block of pixels from the frame buffer using Gdx.gl.glReadPixels(...) in this way :
FrameBuffer frameBuffer;
SpriteBatch spriteBatch;
BitmapFont font;
TextureRegion bufferTextureRegion;
Texture texture;
OrthographicCamera cam;
#Override
public void create() {
cam=new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
cam.setToOrtho(false);
spriteBatch=new SpriteBatch();
texture=new Texture("badlogic.jpg");
font=new BitmapFont();
int w=texture.getWidth();
int h=texture.getHeight();
frameBuffer=new FrameBuffer(Pixmap.Format.RGBA8888,Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),false) ;
frameBuffer.begin();
Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
spriteBatch.draw(texture,0,0);
font.draw(spriteBatch,"Score :100",100,100);
spriteBatch.end();
//bufferTextureRegion =new TextureRegion(frameBuffer.getColorBufferTexture(),0,0,frameBuffer.getWidth(),frameBuffer.getHeight());
//bufferTextureRegion.flip(false,true);
ByteBuffer buf;
Pixmap pixmap = new Pixmap(w, h, Pixmap.Format.RGB888);
buf = pixmap.getPixels();
Gdx.gl.glReadPixels(0, 0, w, h, GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, buf);
frameBuffer.end();
PixmapIO.writePNG(Gdx.files.external("output.png"), pixmap);
}
Related
The problem
When I move the Camera every texture that is getting rendered flickers about the screen on 2 different positions.
What I want
example: When I move the camera to the left, I want the all the textures to move 32 pixels to the right. camera moves 32 pixels per button press.
Current code
I added some extra explanation in comments.
MainProgramEntryPoint
/**
* DefaultCamera: Setting up OrthographicCamera
* CameraMovement: Using camera.translate on keypresses to move the screen.
* TestMoveable: Creating a texture for testing rendering.
*/
public class WorldSimGame extends ApplicationAdapter {
private DefaultCamera defaultCamera;
private CameraMovement cameraMovement;
private TestMoveable testMoveable;
// Setting up the camera and texture.
public void create () {
defaultCamera = new DefaultCamera();
cameraMovement = new CameraMovement(defaultCamera.getCamera());
testMoveable = new TestMoveable();
testMoveable.create(defaultCamera);
}
// The testMoveable.render(defaultCamera) should keep track of the testMoveable position
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
defaultCamera.render();
testMoveable.render(defaultCamera);
}
}
TestMoveable
public class TestMoveable {
private Texture tex;
private SpriteBatch batch;
private Vector3 position;
public void create(DefaultCamera defaultCamera) {
tex = new Texture(("wall.png"));
batch = new SpriteBatch();
position = new Vector3(100, 100, 0);
defaultCamera.getCamera().unproject(position);
}
I cant imagine setting the x and y coordinates on the world coordinates wouldn't work.
public void render(DefaultCamera defaultCamera) {
batch.begin();
batch.draw(tex, position.x, position.y);
batch.end();
}
}
What am I doing wrong here? And is there a better way to implement position checking for the renderers?
You don't need to check the position of the renderer. All what you must do is to set the size and position of your camera. Then with batch.setProjectionMatrix(camera.combined) you say the batch to draw what the camera sees.
So when you create a camera with size = 50x50 and position = 100,100
and you now create a Texture with size = 50x50 and position = 75,75
The Texture will perfectly fit the hole screen.
The position of camera is in the center. So the position of Texture is 75,75 and not 100,100
When you now will move your camera, you can use the method: translate() of your camera.
Call: camera.translate(25,0) to move your camera 25 units to the right and now you only see the half of your Texture on the left side of the screen.
This is an easy example of a Moveable camera. You can use the arrow keys to move around:
public class WorldSimGame extends ApplicationAdapter {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
public WorldSimGame() { }
#Override
public void create(){
//Create texture, batch and camera
texture = new Texture(Gdx.files.internal("badlogic.jpg"));
batch = new SpriteBatch();
camera = new OrthographicCamera(60,60);
}
#Override
public void render(){
//clear screen
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
moveCamera();
//update camera that he recalculate his position and Matrix
camera.update();
batch.setProjectionMatrix(camera.combined); //set batch to draw what the camera sees
batch.begin();
batch.draw(texture,0,0); //draw texture
batch.end();
}
private void moveCamera(){
//move camera
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
camera.translate(4,0);
}
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
camera.translate(-4,0);
}
if(Gdx.input.isKeyPressed(Input.Keys.UP)){
camera.translate(0,4);
}
if(Gdx.input.isKeyPressed(Input.Keys.DOWN)){
camera.translate(0,-4);
}
}
}
I'm currently working on a libgdx game and before I give it final touches I wanted to actually hear something from experienced users, that has been bothering me for a few days already.
If I want to support as many as possible devices, essentially I will be designing graphics for the biggest possible res ,which is then going to be scaled if needed, for smaller screens, right? How do I go about developing for a resolution that is even bigger than my laptop's(the 2015/16 gen phones). My laptop has a resolution of 1920x1080px and the S7 Samsung has 2k+ width.
Thank you!
I think what you are looking for is Viewports. You have to decide which strategy fits best your needs. For example a FitViewport always keeps the aspect ratio you define, which might lead to black bars on some devices.
When I personally develop with libgdx I place and size all objects relative to the screen width and height. This includes images, fonts, buttons, etc. This gives me a pretty consistent result across all devices because most devices today have a ratio 16:9 or something close to it. For developing an image larger than your screen size what's wrong with just using photoshop to create the image of the specified size?
Better you choose the screen with as 1280 and screen height as 800 and also use the fill viewPort . So you will be able to render your game in almost all the screens without the issue of stretching.
Viewport is the method which provided by the libgdx to solve this multi screen compatible issue . here i will post some sample code which you can use for the reference.
public class myGame extends ApplicationAdapter {
public OrthographicCamera camera;
public Viewport viewPort;
private SpriteBatch batch;
private BitmapFont myScoreFont;
private Texture texture;
public myGAme() {
}
#Override
public void create() {
myScoreFont = new BitmapFont(Gdx.files.internal(Constants.PATH_TO_MY_SCORE_FONT), true);
batch = new SpriteBatch();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
texture = new Texture(Gdx.files.internal(Constants.PATH_TO_LEFT_BAR));
camera = new OrthographicCamera();
camera.position.set(0, 0, 0);
camera.update();
camera.setToOrtho(false, Constants.APP_WIDTH, Constants.APP_HEIGHT);
// Here is the viewport is setting up with the camera and the screen size
viewPort = new FillViewport(1280, 800, camera);
}
#Override
public void dispose() {
batch.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(myScorefont,"Score",0,0);
batch.end();
}
#Override
public void resize(int width, int height) {
// the game area will be resized as per the screen size of the device
viewPort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
Is it possible to set a minimum and maximum aspect ratio?
Lets say from 1:1 to 2.5:1. Or at least set min and max for width and height?
You can use a FitViewport to maintain a fixed width and height:
FitViewport viewport = new FitViewport(SCREEN_WIDTH, SCREEN_HEIGHT, camera);
If you are using a Stage to draw all your actors then all you need to do is set the viewport on the stage like this:
stage.setViewport(viewport);
However if you are not using a Stage then you need to do the following. If you are drawing directly with a SpriteBatch you will need to set up a Camera too:
SpriteBatch batch = new SpriteBatch();
OrthographicCamera camera = new OrthographicCamera(SCREEN_WIDTH, SCREEN_HEIGHT);
camera.setToOrtho(true);
//center the camera in the center of the screen
camera.position.set(SCREEN_WIDTH / 2f, SCREEN_HEIGHT / 2f, 0f);
//pass the camera to the third argument of the viewport
FitViewport viewport = new FitViewport(SCREEN_WIDTH, SCREEN_HEIGHT, camera);
Then you will need to set up the projection matrix on the Camera and SpriteBatch when rendering:
#Override
public void render(float deltaTime) {
camera.update();
batch.setProjectionMatrix(camera.combined);
// do all the rendering of textures and stuff
}
Also you need to update the viewport every time the screen is resized:
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
I have tried to make a ellipse object in libgdx. Sorry if i can't describe properly but im a newbie in java.
My code looks like:
public class GameScreen implements Screen{
MyGame game;
OrthographicCamera camera;
SpriteBatch batch;
...
Ellipse playBounds;
public GameScreen(MyGame game) {
this.game = game;
camera = new OrthographicCamera();
camera.setToOrtho(false, 1080, 1920);
batch = new SpriteBatch();
state = GAME_READY;
touchPoint = new Vector3();
pauseBounds = new com.badlogic.gdx.math.Rectangle(1080-128,1920-128,128,128);
playBounds= new Ellipse()
}
...
public void render(float delta) {
Gdx.gl.glClearColor(1F, 1F, 1F, 1F);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
generalupdate();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(Assets.sprite_bg, 0, 0);
switch (state){
case GAME_READY:{
batch.draw(Assets.sprite_startScreen, 0, 0);
batch.draw(Assets.sprite_playButton,218,800,644,225);
break;
}
Basically it draws background, a welcome screen and a button(with "play" on it)
So here i made a touch detection.
if (Gdx.input.justTouched()) {
camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
if (state==GAME_READY);
if (playBounds.contains(touchPoint.x, touchPoint.y)) {
state=GAME_RUNNING;
Drawing works fine but the problem is when i touch the button it doesnt work instead if i touch near it game starts as it should
Alright, ignoring the several errors in the code which I will just assume were made here instead of the actual code, I believe the problem could be that you are not setting the values in the Ellipse. By this I mean the width, height, x, and y.
An nice way to do this would be to use the constructor:
Ellipse(float x, float y, float width, float height)
instead of just :
Ellipse()
That way you can set the values right away. Refer to this website for more info in Ellipses for LibGDX.
If that doesn't solve your problem you may have to post a little more of the relevant parts of your code.
This is from day 6 of the flappy bird recreation tutorial
-http://www.kilobolt.com/day-6-adding-graphics---welcome-to-the-necropolis.html
Here is the image file i am using for texture in my game. It is a 256px x 64px .png file.
Here is the class that I used for loading the texture and the specific TextureRegion(part of the texure) that I want the SpriteBatch to draw.
public class AssetLoader {
public static Texture texture;
public static TextureRegion bg;
public static void load() {
texture = new Texture(Gdx.files.internal("data/texture.png"));
bg = new TextureRegion(texture, 0, 0, 136, 43);
}
}
And I call AssertLoader.load(), along with setting up game screen from
public class MyGdxGame extends Game{
#Override
public void create() {
AssetLoader.load();
setScreen(new GameScreen());
}
}
And inside GameScreen.java
public class GameScreen implements Screen {
//delegate render task
private GameRenderer renderer;
public GameScreen() {
float screenHeight = Gdx.graphics.getHeight();
float screenWidth = Gdx.graphics.getWidth();
float gameWidth = 136;
float gameHeight = screenHeight / (screenWidth / gameWidth);
renderer = new GameRenderer((int)gameHeight);
}
}
And inside GameRederer, the class I delegate to render the game
public class GameRenderer {
private int gameHeight;
private SpriteBatch batch;
private OrthographicCamera cam;
public GameRenderer(int gameHeight) {
this.gameHeight = gameHeight;
cam = new OrthographicCamera();
batch = new SpriteBatch();
batch.setProjectionMatrix(cam.combined);
cam.setToOrtho(true, 136, gameHeight);
}
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.disableBlending();
batch.draw(AssetLoader.bg, 0, (gameHeight/2) + 23, 136, 43);
batch.end()
}
}
What I get when I run the desktop version of the game is the black screen shown above(black because i set the background to black with these lines of code
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Does anyone know why the SpritchBatch drawing isn't showing up? I extracted the texture portion of the texture I wanted with this line of code(starts from 0,0, width of 136, height of 43) - used GIMP - to find out portion to cut.
bg = new TextureRegion(texture, 0, 0, 136, 43);
I also put a few log statements(removed them from view) to ensure that before drawing, bg's width and height were set correctly, which they were. And the issue can't be game height because I used a print statement and found that to be 204 which means that this expression, (gameHeight/2) + 23 will evaluate to 125 which is in bounds between 0 and game height.
I checked out other threads as well.
My issue can't be libgdx spritebatch not rendering textures because the SpriteBatch should overwrite the background.
And it can't be LibGDX: Android SpriteBatch not drawing because i am running mine on desktop, not andorid.
could be that you have to first put cam.setToOrtho(true, 136, gameHeight);before the batch, so I can not confirm hopefully help
public GameRenderer(int gameHeight) {
this.gameHeight = gameHeight;
cam = new OrthographicCamera();
batch = new SpriteBatch();
cam.setToOrtho(true, 136, gameHeight);
batch.setProjectionMatrix(cam.combined);
}
If anyone's having a similar issue, the way I solved the problem was to call
batch.setProjectionMatrix(cam.combined);
after
cam.setToOrtho(true, 136, gameHeight);
Which didn't really make sense to me because it's still the same Matrix4 in Camera.java, that is
public final Matrix4 combined = new Matrix4();
Was hoping someone else could clarify that.