I am creating a game and trying to set up a splash screen.
Whenever I render the sprite that i want to tween to by using the sprite.draw method which looks like this:
#Override
public void render(float delta)
{
Gdx.gl20.glClearColor(0.2F, 0.5F, 1F, 1F);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
tm.update(delta);
cam.update();
sb.setProjectionMatrix(cam.combined);
sb.begin();
Assets.splash_spr_bg.draw(sb);
sb.end();
}
The tweening works great except i can only see 1/4 of the picture on my screen, it is completely out of position.
And whenever I try to use this code in order to render the sprite by using the spritebatch to draw it, which looks like this:
#Override
public void render(float delta)
{
Gdx.gl20.glClearColor(0.2F, 0.5F, 1F, 1F);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
tm.update(delta);
cam.update();
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(Assets.splash_spr_bg, 0, 0);
sb.end();
}
I can see the background great, great quality, correct size and position and all that. However, the tweening doesn't work at all; nothing happens.
Why does this not work? How can I fix it?
Here is some other code.
Initializion of the TweenHandler class:
package com.heavenapps.jumpdodge.handlers;
import com.badlogic.gdx.graphics.g2d.Sprite;
import aurelienribon.tweenengine.TweenAccessor;
public class TweenHandler implements TweenAccessor<Sprite>
{
public static final int ALPHA = 1;
#Override
public int getValues(Sprite target, int tweenType, float[] returnValues)
{
switch(tweenType)
{
case ALPHA:
returnValues[0] = target.getColor().a;
return 1;
default:
return 0;
}
}
#Override
public void setValues(Sprite target, int tweenType, float[] newValues)
{
switch(tweenType)
{
case ALPHA:
target.setColor(1, 1, 1, newValues[0]);
break;
}
}
}
Initializion of the sprite/texture:
package com.heavenapps.jumpdodge.handlers;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
public class Assets
{
public static Texture splash_tex_bg;
public static Sprite splash_spr_bg;
public static void init()
{
// Splash Screen
splash_tex_bg = new Texture(Gdx.files.internal("Splash Screen/Background.png"));
splash_tex_bg.setFilter(TextureFilter.Linear, TextureFilter.Linear);
splash_spr_bg = new Sprite(splash_tex_bg);
splash_spr_bg.setOrigin(splash_spr_bg.getWidth() / 2, splash_spr_bg.getHeight() / 2);
splash_spr_bg.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
splash_spr_bg.setColor(1, 1, 1, 0);
}
}
Usage of the tweening:
public void fadeSplashScreen()
{
Tween.to(Assets.splash_spr_bg, TweenHandler.ALPHA, 2F).target(1).ease(TweenEquations.easeInBounce).start(tm);
}
You need to set the sprite's position if you want to draw it using your first method. (sprite.draw(spriteBatch)). And you need to use your first method if you want to use the sprite's color, which is being controlled by the tween.
It looks like you did give the background sprite an initial position, but you put it off screen. So change
splash_spr_bg.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
to
splash_spr_bg.setPosition(0, 0);
The reason the second method you showed (spriteBatch.draw(sprite, x, y)) draws it in the correct position is that this method of drawing ignores the fact that it's a sprite and just draws the texture region owned by the sprite in whatever position you give it. And this method doesn't fade the sprite because it's ignoring the fact that it is a sprite (which has a color).
Related
I've been learning about libgdx recently. In the process of following the instructions on their libgdx wiki I ran into some problems.
Specifically in the GameScreen class at the 99th line I changed the code inside so that it goes back to the previous screen (MainMenuScreen class) and yes you see when the mouse is pressed it worked (I mean go back to the screen before ) but a very very short time after, the screen AUTOMATICALLY switches to the GameScreen class (like I click the mouse once but it makes me 1 more redundant task). I guess when I click on the GameScreen screen it did the code in the if statement on line 99 to go to MainMenuScreen screen. In that screen at line 32 I guess it was true after I got to this screen because when I change the key is listened then it works fine (only converts once). I was intending to try implementing InputProcessor on each screen class but now I'm avoiding it for some reason. Can someone give me some advice recommend.Thank you
Here is the source code for the MainMenuScreen class.
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.ScreenUtils;
//import com.mygdx.game.Drop;
public class MainMenuScreen implements Screen {
final Drop game;
OrthographicCamera camera;
public MainMenuScreen(final Drop gam) {
game = gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
#Override
public void render(float delta) {
ScreenUtils.clear(0, 0, 0.2f, 1);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) { //I guess right after switching to this screen this conditional sentence was true before
game.setScreen(new GameScreen(game));
dispose();
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Here is source code for the GameScreen class
package com.mygdx.game;
import java.util.Iterator;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.TimeUtils;
public class GameScreen implements Screen {
final Drop game;
Texture dropImage;
Texture bucketImage;
//Sound dropSound;
//Music rainMusic;
OrthographicCamera camera;
Rectangle bucket;
Array<Rectangle> raindrops;
long lastDropTime;
int dropsGathered;
public GameScreen(final Drop gam) {
this.game = gam;
// load the images for the droplet and the bucket, 64x64 pixels each
dropImage = new Texture(Gdx.files.internal("drop.png"));
bucketImage = new Texture(Gdx.files.internal("bucket.png"));
// load the drop sound effect and the rain background "music"
//dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
//rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
//rainMusic.setLooping(true);
// create the camera and the SpriteBatch
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
// create a Rectangle to logically represent the bucket
bucket = new Rectangle();
bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
bucket.y = 20; // bottom left corner of the bucket is 20 pixels above
// the bottom screen edge
bucket.width = 64;
bucket.height = 64;
// create the raindrops array and spawn the first raindrop
raindrops = new Array<Rectangle>();
spawnRaindrop();
}
private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800 - 64);
raindrop.y = 480;
raindrop.width = 64;
raindrop.height = 64;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
#Override
public void render(float delta) {
// clear the screen with a dark blue color. The
// arguments to clear are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
ScreenUtils.clear(0, 0, 0.2f, 1);
// tell the camera to update its matrices.
camera.update();
// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
game.batch.setProjectionMatrix(camera.combined);
// begin a new batch and draw the bucket and
// all drops
game.batch.begin();
game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480);
game.batch.draw(bucketImage, bucket.x, bucket.y);
for (Rectangle raindrop : raindrops) {
game.batch.draw(dropImage, raindrop.x, raindrop.y);
}
game.batch.end();
// process user input
if (Gdx.input.justTouched()) { //This conditional works fine
/* Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
bucket.x = touchPos.x - 64 / 2;
*/
game.setScreen(new MainMenuSceen(game)); //Screen switch
}
if (Gdx.input.isKeyPressed(Keys.LEFT))
bucket.x -= 200 * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Keys.RIGHT))
bucket.x += 200 * Gdx.graphics.getDeltaTime();
// make sure the bucket stays within the screen bounds
if (bucket.x < 0)
bucket.x = 0;
if (bucket.x > 800 - 64)
bucket.x = 800 - 64;
// check if we need to create a new raindrop
if (TimeUtils.nanoTime() - lastDropTime > 1000000000)
spawnRaindrop();
// move the raindrops, remove any that are beneath the bottom edge of
// the screen or that hit the bucket. In the later case we play back
// a sound effect as well.
Iterator<Rectangle> iter = raindrops.iterator();
while (iter.hasNext()) {
Rectangle raindrop = iter.next();
raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
if (raindrop.y + 64 < 0)
iter.remove();
if (raindrop.overlaps(bucket)) {
dropsGathered++;
//dropSound.play();
iter.remove();
}
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
// start the playback of the background music
// when the screen is shown
//rainMusic.play();
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
dropImage.dispose();
bucketImage.dispose();
//dropSound.dispose();
//rainMusic.dispose();
}
}
Here is source for Drop class
package com.mygdx.game;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class Drop extends Game {
SpriteBatch batch;
BitmapFont font;
public void create() {
batch = new SpriteBatch();
// Use LibGDX's default Arial font.
font = new BitmapFont();
this.setScreen(new MainMenuScreen(this));
}
public void render() {
super.render(); // important!
}
public void dispose() {
batch.dispose();
font.dispose();
}
}
Your analysis of the problem seems correct to me. The method Gdx.input.isTouched() will immediately return true, if the screen is still being touched after you changed to the main menu.
Also you the solution that you already tried seems correct:
I was intending to try implementing InputProcessor on each screen class
When using an InputProcessor you will get one event (the method call to touchDown or touchUp) when the screen is touched, and don't need to pull the touch event using the isTouched method.
A problem when implementing InputProcessor with both classes probably is, that you can only set one to be the input processor of the game using the method Gdx.input.setInputProcessor. (When setting the second input processor, the first one is removed).
A solution to this problem is the InputMultiplexer. You can add this multiplexer as the input processor of the game (using Gdx.input.setInputProcessor(multiplexer)) and then add your input processors (the main menu and game objects) to this multiplexer: multiplexer.addProcessor(mainMenu) or ((InputMultiplexer) Gdx.input.getInputProcessor()).addProcessor(game).
This way you can handle touch events instead of pulling the touched state in both of your classes.
My goal is to create a game that is always displayed with an aspect ratio of 9:16 (basically 16:9, but upright) using FitViewport; it should be independet of a target device's resolution. In order to test this setup, I created the following minimal working example. A small green square indicates the origin of the coordinate system:
MyGame.java
public class MyGame extends ApplicationAdapter {
final int WORLD_WIDTH = 900;
final int WORLD_HEIGHT = 1600;
Stage stage;
Viewport vp;
public void create() {
stage = new Stage();
vp = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, stage.getCamera());
stage.setViewport(vp);
stage.addActor(new MySquare());
}
public void render() {
stage.act();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
}
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
// dispose...
}
MySquare.java
public class MySquare extends Actor {
ShapeRenderer renderer = new ShapeRenderer();
#Override
public void draw(Batch batch, float alpha){
batch.end();
renderer.begin(ShapeRenderer.ShapeType.Filled);
renderer.setColor(Color.GREEN);
renderer.rect(0, 0, 50, 50);
renderer.end();
batch.begin();
}
}
Unfortunately, the result is not as expected: As you can see, the green square is actually not a square. This behavior is the same for both Windows and Android (in landscape mode):
However, when setting the size of the window programmatically and explicitly via LwjglApplicationConfiguration in DesktopLauncher.java to a valid 9:16 resolution, the green square is displayed correctly. Why is that and how can I avoid this workaround (which does not work for Android anyway)?
Your problem is that your shape renderer is ignoring the camera. Update it like this:
public void draw(Batch batch, float alpha){
batch.end();
renderer.setProjectionMatrix(batch.getProjectionMatrix()); // <<<<< Add this
renderer.begin(ShapeRenderer.ShapeType.Filled);
renderer.setColor(Color.GREEN);
renderer.rect(0, 0, 50, 50);
renderer.end();
batch.begin();
}
If you are planning to eventually use sprites, and you're simply wanting rectangle placeholders for your actors, you don't need a custom actor for this. You can use a generic Actor and call setDebug(true) on it, and Stage will automatically draw its outline using an internal ShapeRenderer. Of course, you must first set a size and position on the Actor.
I have a camera in my GameStage class and am trying to translate the camera when the left or right arrow keys are pressed. When I press either key and print the camera x position it changes, but nothing moves (actors on screen stay in the same position). What am I doing wrong?
Screen Render Method:
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(255, 255, 255, 255);
gameStage.update();
gameStage.draw();
gameStage.act(delta);
}
Stage Code Involving the Camera:
public GameStage() {
super(new ScalingViewport(Scaling.stretch, Lib.WIDTH, Lib.HEIGHT, new OrthographicCamera(Lib.WIDTH, Lib.HEIGHT)));
initCamera();
Gdx.input.setInputProcessor(this);
}
public void initCamera() {
camera = new OrthographicCamera(Lib.WIDTH, Lib.HEIGHT);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0f);
camera.update();
}
public void updateCamera() {
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
camera.translate(-5, 0);
} else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
camera.translate(5, 0);
}
camera.update();
}
public void update() {
updateCamera();
}
Thanks :)
From you visible code I would say that the problem is you have two cameras.
One is created when you are calling super constructor. And one created manually. Even if you are translating the camera you created, for rendering batch will use stages camera.
Remove the camera you created and work only with stages camera.
I'm having problems to draw some text in the screen, and I found out that depending on the viewport size, the text may get out of the display despite being calculating the coordinates as the center of the screen. Here's the code, it is a just slightly modified project as created by libgdxgenerator by default:
package net.iberdroid.libgdxtestfonts;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class LibGdxTestFonts extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
BitmapFont defaultFont;
private OrthographicCamera camera;
private Viewport viewport;
private float textY;
private float textX;
#Override
public void create() {
camera = new OrthographicCamera();
viewport = new FitViewport(
640,
480,
camera);
camera.setToOrtho(false);
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
defaultFont = new BitmapFont();
textX = viewport.getWorldWidth() / 2;
textY = viewport.getWorldHeight() / 2;
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.setProjectionMatrix(camera.combined);
defaultFont.setColor(Color.WHITE);
Gdx.app.log("render", String.format("TextX: %f TextY: %f", textX, textY));
defaultFont.draw(batch, "HELLO WORLD!", textX, textY);
batch.end();
}
#Override
public void dispose() {
batch.dispose();
img.dispose();
}
}
As far as I understand, that should draw a HELLO WORLD! text starting around the center of the screen. And it actually does it with that viewport size. Now, if you try with a bigger viewport, let's say 800x600, the text will move to the right and top, if try even with higher values, it will become a point in which the text will get out the boundaries of the screen by the top-right corner.
The same happens in the opposite direction. The smaller viewport you try, the further from the center and closer to the bottom-left corner the text will appear, until it eventually get out the boundaries too.
So either I am failing to grasp something here, or the BitMap.draw method seems to be ignoring the viewport size and using others that I cannot figure out.
If someone else does it, please, make me know.
Thanks a lot in advance!
P.S. I've tried also with a Hiero generated font and had the same issue.
Adding this seems to solve the problem with the position, though I still have a problem with the scale, but that's a different issue.
#Override public void resize (int width, int height) {
viewport.update(width, height, true);
}
I'm seriously betting that I did something effing stupid and just can't seem to notice it.
package com.me.mygdxgame;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class Locked implements ApplicationListener
{
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;
private BitmapFont font;
private CharSequence str = "Hello World!";
private float width;
private float height;
#Override
public void create()
{
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, height / width);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/libgdx.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275);
sprite = new Sprite(region);
sprite.setSize(0.9f, 0.9f * sprite.getHeight() / sprite.getWidth());
sprite.setOrigin(sprite.getWidth() / 2, sprite.getHeight() / 2);
sprite.setPosition(-sprite.getWidth() / 2, -sprite.getHeight() / 2);
font = new BitmapFont(Gdx.files.internal("data/digib.fnt"),
Gdx.files.internal("data/digib.png"), false);
}
#Override
public void dispose()
{
batch.dispose();
texture.dispose();
}
#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();
font.setColor(0.0f, 0.0f, 0.0f, 1.0f);
//sprite.draw(batch);
font.draw(batch, str, width*0.5f, height*0.5f);
batch.end();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
}
The project was generated with the template tool they provide gdx-setup-ui.jar
As you can see in the code, I didn't bother to get rid of the default codes (Just some simple draw codes to render the LibGDX logo).
So, with the cleanly generated project, I followed this guide here
http://code.google.com/p/libgdx-users/wiki/addingText2D
and finally arriving with the provided code above.
The problem is, why won't the !##$ing text show!? I changed the position so many times and still no luck :\
Did I miss something?
FYI: The fonts are fine, I dropped them into another game and it works.
Try to change projection matrix like this:
Matrix4 normalProjection = new Matrix4().setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(normalProjection);
All I do is
spriteBatch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("data/nameOfFont.fnt"),
Gdx.files.internal("data/nameOfFont.png"), false);
and in render method
spriteBatch.begin();
font.setColor(1.0f, 1.0f, 1.0f, 1.0f);
font.draw(spriteBatch, "some string", 25, 160);
spriteBatch.end();
You can read something more about it on my blog: http://algorhymes.wordpress.com/2012/11/17/javalibgdx-fonts/
Personally I'm not a big fan of converting all the fonts to .fnt format. If you need different sizes for a certain font you have to spend a lot of time (and app space) to make all the conversions.
You can just use the FreeType Extension and load straight from a .ttf
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(fontFile);
BitmapFont font15 = generator.generateFont(15);
BitmapFont font22 = generator.generateFont(22);
generator.dispose();
More info here
Rendering is done in the same way as explained by watis.
create a .fnt file using hiero which is provided by libgdx website
set the size of font 150 ,it will create a .fnt file and a png file
copy both of file in your assests folder
now declare the font
BitmapFont font;
nw in create method
font = new BitmapFont(Gdx.files.internal("data/100.fnt"), false);//100 is the font name you can give your font any name
in render
font.setscale(.2f);
font.draw(batch, "whatever you want to write", x,y);
this will work smoothly
The main problem with your code is that you have created camera with
viewportWidth = 1 &
viewportHeight = width/height
and you are drawing font at width*0.5f & height*0.5f which is out of scope from camera
Either change the camera initialization to
camera = new OrthographicCamera(width, height);
....
or change the draw font statement to
font.setScale(1,height/width);
font.draw(batch, str, 0.5f, height/width*0.5f);
Did you try giving position manually like this. I hope this will work
batch.setProjectionMatrix(camera.combined);
batch.enableBlending();
batch.begin();
font.draw(batch, yourString, 100,100);
batch.end();