libgdx sprite is disorted when scaling and rotating - libgdx

I want to rotate and scale my Sprite but it looks disorted:
This is my render method:
public void renderMain(float delta){
batch.begin();
GameScreenShipUpdater.getTexture(yourship).setPosition(yourship.getRectangle().x, yourship.getRectangle().y);
GameScreenShipUpdater.getTexture(yourship).setSize(25f, 10f);
GameScreenShipUpdater.getTexture(yourship).setOriginCenter();
GameScreenShipUpdater.getTexture(yourship).setRotation(130f);
GameScreenShipUpdater.getTexture(yourship).draw(batch);
batch.end();
}
How can I fix this? This is how the Sprite looks without rotating:

Related

Relation between stage.draw and stage.getBatch.draw Libgdx

I am new to libgdx stage, and is very confuse about stage.draw and stage.getbatch.draw. Is the following codes a proper practice?
public void render(float delta) {
Gdx.gl.glClearColor(101,10,0,2);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
elapseTime += Gdx.graphics.getDeltaTime();
stage.getBatch().begin();
stage.getBatch().draw(texture.animation.getKeyFrame(elapseTime,true),locationX,locationY);
stage.getBatch().end();
}
I'm using stage.draw to perform some action to my ui button, and stage.getbatch.draw to perform my texture animaiton. Are them referring to the same sprite batch?

LibGDX Scene2d Action affects multiple Actors

I am working on my second app and it went quite well so far. But now I got stuch on a problem I just can´t manage to find a solution for.
I´ve been using scene2d stage to display everything. Now I´ve added a black image which fades out whenever a new Screen is called(as a transition).
My problem is, that when I add the fade out action to my black Image it also fades out the background. Interestingly only the background is affected, no other Actor what so ever.
I´ve tried changing the order of the Actors, putting them into groups, clearing all actions from the background, setting his alpha to 1 but nothing worked.
Thanks for helping me !
For the background:
public class BackgroundColor extends Actor {
public BackgroundColor(int x) {
this.setBounds(x, 0, 270, 960);
}
public void act(float delta) {
}
public void draw(Batch batch, float alpha) {
batch.draw(image, this.getX(), this.getY(), this.getWidth(), this.getHeight());
}
}
For the screen:
public class GameScreen implements Screen {
public Stage stage;
public BackgroundColor backgroundColor;
public Image black;
public GameScreen() {
stage = new Stage(new ExtendViewport(540, 900, 540, 960));
Gdx.input.setInputProcessor(stage);
setupStage();
}
private void setupStage() {
backgroundColor = new BackgroundColor(0);
stage.addActor(backgroundColor);
//this is the black layer
black = new Image(AssetLoader.black);
black.setBounds(0, 0, stage.getWidth(), stage.getHeight());
stage.addActor(black);
black.addAction(Actions.sequence(Actions.fadeOut((float)0.5), Actions.touchable(null)));
}
#Override
public void show() {
}
#Override
public void render(float deltaTime) {
Gdx.gl.glClear(0);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
So, I kinda figured it out...
apparently having a different Image as the first layer of the stage solves the issue.
I added in a random Image before the backgroundColor = new BackgroundColor(0); and that fixed it.
I still have no Idea what causes this, maybe I missed something...
Would be great if you could tell me what is going on here!
Cheers

render to FrameBuffer not working in combination with ShapeRenderer in a custom Actor (libgdx)

I try to implement a custom Actor which displays contents of a FrameBuffer by extending Image. Inside I'd like to draw using a ShapeRenderer.
public class CustomActor extends Image {
private FrameBuffer frameBuffer = null;
private ShapeRenderer shapeRenderer = new ShapeRenderer();
private int width;
private int height;
public CustomActor() {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
shapeRenderer.setAutoShapeType(true);
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (frameBuffer == null) {
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width / 2, height / 2, false);
TextureRegion textureRegion = new TextureRegion(frameBuffer.getColorBufferTexture());
textureRegion.flip(false, true);
setDrawable(new TextureRegionDrawable(textureRegion));
}
frameBuffer.begin();
// render content
Gdx.gl.glClearColor(0, 1, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.rect(0, 0, frameBuffer.getWidth() / 2, frameBuffer.getHeight() / 2);
shapeRenderer.end();
if (frameBuffer != null) {
frameBuffer.end();
}
super.draw(batch, parentAlpha);
}
}
When deleting the ShapeRenderer part I can see the green background in the scene. But as soon as I use the ShapeRenderer the content is black. There is no white rectangle visible.
Any ideas what I am doing wrong?
Just found out that using my own SpriteBatch (with begin() and end()) after the FrameBuffer end() it works. So the problem seems to have to do with the calling order of the FrameBuffers methods and the SpriteBatches methods. Ending the given actor batch before beginning the FrameBuffer and "re"-beginning it to draw the actor is also working (see comment above).

How to use SpriteBatch and ShapeRenderer in one screen?

I'm using SpriteBatch to draw textures and ShapeRenderer to draw some shape.
Here is my code in an actor
#Override
public void draw(Batch batch, float parentAlpha) {
batch.end();
Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.begin(ShapeType.Filled);
//change color
shapeRenderer.setColor(color);
shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
}
and call stage.draw() on the screen
#Override
public void render(float delta) {
Gdx.gl20.glClearColor(0, 0, 0, 0);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
stage.act(delta);
stage.draw();
//......
}
It's working but unpredictably throw exception:
STACK_TRACE=java.lang.IllegalStateException: SpriteBatch.end must be called before begin.
at com.badlogic.gdx.graphics.g2d.SpriteBatch.begin(SpriteBatch.java:164)
at com.badlogic.gdx.scenes.scene2d.Stage.draw(Stage.java:127)
at c.i.a.a(AbstractCardRoomRenderer.java:3078)
at c.i.s.a(TLMNCardRoomRenderer.java:1158)
at c.j.e.render(GameScreen.java:22)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
EDIT: For more details what I'm doing:
What I want is to draw a shape. Because the stage's batch is drawing so I have to end it for shape drawing. My code still work but sometime, another actor, I think, use stage's batch to draw something else. It make the stage begin its batch. So it conflict between begin and end.
For example, the actor draw method:
batch.end();
//drawing shapes
batch.begin() (somewhere else) <--- I think this code is call when stage call draw on other actor
//drawing completed
batch.begin()
EDIT:
If others' answer not suit you, please consider my workaround I post as an answer below.
#Override
public void draw(Batch batch, float parentAlpha) {
batch.end(); <--
Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING);
../// other code
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin(); <--
I think the error is in you is calling, batch.end () before bacth.begin (); try to change the order
on the other hand, if the draw method. It is the stage class, you call him with the arguments you require, public void draw (Batch batch, float parentAlpha)
If you don't close all Renderers before opening a new one you will get a view without the previous ones
spriteBatch.begin()
... // render Textures
shapeRenderer.begin()
... // render Shapes
shapeRenderer.close()
spriteBatch.close()
this would cause a Screen without your spriteBatch-Textures ---
you already solved this problem by resorting your code to this
#Override
public void draw(Batch batch, float parentAlpha) {
batch.end(); // close A
...
shapeRenderer.begin(ShapeType.Filled); // open B
...
shapeRenderer.end(); // close B
batch.begin(); // open A
}
But in the very first batch.end() your code is not able to find any opened spriteBatch that can be closed, therefore you get an IllegalStateException
You have to call
batch.begin() one time before using the end()-method
(but be aware that you shouldn't begin a batch every frame)
the most simple solution i would recommend to solve the issue is the following:
class MyActor{
private boolean firstDraw = true;
#Override
public void draw(Batch batch, float parentAlpha) {
if(firstDraw)
{
batch.begin();
firstDraw=false;
}
batch.end();
Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.begin(ShapeType.Filled);
//change color
shapeRenderer.setColor(color);
shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
}
...
}
Like Angel * 2 is saying, your error is coming from calling a .end before .begin. Using multiple drawing batches is perfectly possible and being used often, but you have to use them in order and begin/end them properly. The following code is valid:
spriteBatch.begin();
spriteBatch.draw(..);
//more draw calls for this spritebatch
spriteBatch.end();
shapeRenderer.begin(..);
shapeRenderer.line(..);
//more draw calls for shaperenderer go here
shapeRenderer.end();
anotherSpriteBatch.begin();
anotherSpriteBatch.draw(..);
anotherSpriteBatch.end();
//You can also use the same batch again.
shapeRenderer.begin(..);
shapeRenderer.circle(..);
shapeRenderer.close();
I know this is my old question but I can see there are still new people using libgdx facing this error too. So I post my workaround as an answer:
The problem is that there is something break in between
batch.begin()
and
batch.end()
when the stage drawing
so if you use Stage to manage the batch, try-catch can save your time:
#Override
public void render(float delta) {
try {
stage.act(delta)
stage.draw()
} catch (Exception ex) {
if(stage.batch.isDrawing)
stage.batch.end()
}
}
** This is just a workaround to bypass some accidental error (e.g glyphlayout) in a frame and it should work fine in next frame. If there is any real problem in your code or resources, your render code will end up in the catch{}

Make actor clip child Image

I want an actor that draws a drawable, but clips it to the size of the actor. I'm deriving this class from Widget, and using some hard-coded values as a simple test:
public class MyWidget extends Widget {
public MyWidget(Drawable drawable) {
setDrawable(drawable);
setSize(100, 100);
}
public void draw(Batch batch, float parentAlpha) {
clipBegin(getX(), getY(), 20, 20);
drawable.draw(batch, getX(), getY(), 500, 500);
clipEnd();
}
}
No clipping is performed though, the drawable spills out of the bounds of the actor. This actor is part of a Table, if it matters. I believe I am using the clipBegin() / clipEnd() methods incorrectly. What is the right way to do this?
Thanks
This is what I found based on the comments and my own experimentation. It's important to flush the batch before starting the clip and after drawing to ensure the proper drawing gets clipped.
public void draw(Batch batch, float parentAlpha) {
batch.flush();
if (clipBegin(getX(), getY(), 20.0f, 20.0f)) {
//do your drawing here
drawable.draw(batch, getX(), getY(), 500, 500);
batch.flush();
clipEnd();
}
}