Sliding background in Libgdx - android

I´m new with libgx and i have a basic question. I want an background like an image that repeats indefinetely, and moves down. I did with 2 images and it worked, but the problem is that is very slow. I stored the images with 512x512px.
My code is very simple but i dont know what im doing wrong.
public void render() {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
offset -= 600 * Gdx.graphics.getDeltaTime();
offset = offset % 512;
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundImage, 0, offset);
batch.draw(backgroundImage, 0, offset + 512);
batch.draw(bucketImage, 0, offset + 1024);
batch.end();
}
Any suggestions will be appreciated
Thanks a lot!

I don't see any reason your render method would cause a slowdown, are you sure the slowdown is happening there? I would bet it's not. Narrow down the root cause of the slowdown which is probably somewhere else in your code.
(I didn't have enough reputation to comment)

Related

TextureAtlas and renderCalls in libgdx

I'm creating two textures and put them in the same TextureAtlas as shown in the code:
public void create () {
pix = new Pixmap(100, 100, Pixmap.Format.RGBA8888);
textureAtlas = new TextureAtlas();
pix.setColor(Color.WHITE);
pix.fill();
textureAtlas.addRegion("white", new TextureRegion(new Texture(pix)));
pix.setColor(Color.RED);
pix.fill();
textureAtlas.addRegion("red", new TextureRegion(new Texture(pix)));
tr_list = textureAtlas.getRegions();
pix.dispose()
}
and then when rendering:
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
for (int i = 0; i < 200; ++i) {
batch.draw(tr_list.get(i % tr_list.size), (int)(Math.random()* 500), (int)(Math.random()* 500));
}
font.draw(batch, "FPS: " + Integer.toString(Gdx.graphics.getFramesPerSecond()), 0, Gdx.graphics.getHeight() - 20);
font.draw(batch, "Render Calls: " + Integer.toString(batch.renderCalls), 0, Gdx.graphics.getHeight() - 60);
batch.end();
}
I was expecting batch.renderCalls to be equal to 1, since the textures are in the same TextureAtlas, but instead it's equal to 200. What am I doing wrong?
In order to draw your TextureRegions in a single render call, each of them must be a part of the same Texture, not TextureAtlas.
TextureAtlas can contain TextureRegions of different Textures, which actually happens in your case. Even though you use the same Pixmap, you create two different Textures from it.
You are drawing them in loop 200 times.
for (int i = 0; i < 200; ++i) {
// this will be called 200 times
batch.draw(tr_list.get(i % tr_list.size), (int)(Math.random()* 500), (int)(Math.random()* 500));
}
And also TextureAtlas class doesn't create pig picture of textures that you add to it. It is just container of TextureRegions how #Arctic23 noticed.
So main problem for you is to draw 2 textures in one render call. I wouldn't recommend you doing this. It is possible but it will be hard to work with them.
Calling batch.draw(..) every time you draw a texture is not a big performance problem. So i don't know why you detach this.

Libgdx. Rectangle position on screen different from code

I’m trying to develop a very simple game for Android using libgdx: there is a bug that appears randomly on the screen and you have to touch it where the bug is to kill it. If you do, the game goes on until you miss three times, and then is game over. Simple enough.
So, I see the bug, I touch it right in the middle, but I miss: the touch point isn’t included in the bug rectangle, which is different from what I see on the screen. I print out the coordinates of both rectangle and point and I see that those of the rectangle were correct a couple of deltaTimes ago, but are no longer, despite of what I see on the screen. I have looked all over the place for a solution, read tutorials, libgdx documentation, but I don’t get it, I'm getting nuts.
This is the code for the touchDown event on the constructor
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
unidadTiempo = unidadTiempo - aceleracion;
toque.set(screenX, screenY, 0f);
camara.unproject(toque);
if (bicho.contains(toque.x, toque.y)) {
aplastamiento.play();
bichosLiquidados++;
} else {
burla.play();
vidas--;
}
return true;
}
});
This is the method drawing the bugs and accelerating the bug appearing pace
void apareceBicho(){
ultimoBicho = TimeUtils.nanoTime();
juego.letra.draw(juego.batch, "Puntuacion: " + bichosLiquidados, 0, altoPantalla);
bicho.setX(xAleatorio);
bicho.setY(yAleatorio);
juego.batch.draw(bichoImagen, bicho.x, bicho.y);
while (TimeUtils.nanoTime() - ultimoBicho < unidadTiempo && vidas > 0){
unidadTiempo = unidadTiempo - aceleracion;
xAleatorio = MathUtils.random(randomx);
yAleatorio = MathUtils.random(randomy);
}
if(vidas == 0){
risa.play();
TextureRegion fotogramActual = animacionFinal.getKeyFrame(stateTime, true);
juego.batch.draw(fotogramActual, bicho.x, bicho.y);
juego.batch.flush();
gameover = true;
}
if (gameover){
juego.setScreen(new PantallaFinal(juego, this));
}
}
And lastly, the render method
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0.2f, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
camara.update();
juego.batch.setProjectionMatrix(camara.combined);
juego.batch.begin();
juego.batch.draw(yerbita, 0, 0, anchoPantalla, altoPantalla);
apareceBicho();
juego.batch.end();
}
This is what I meant by a couple of deltaTimes ago:
06-04 09:30:05.942 RECTANGLE POSITION AIMED TO: Posicion del bicho: 612.88776, 200.9191, 133.0, 126.0
06-04 09:30:07.950 ACTUAL RECTANGLE POSITION: Posicion del bicho: 426.92572, 111.10537, 133.0, 126.0
06-04 09:30:09.946 TOUCH POSITION: Coordenadas toque = 659.2, 250.3111
Possible reason :
bicho having zero width and height.
If you created rectangle by default constructor then need to be set width and hight of that rectangle.
bicho = new Rectangle();
bicho.setSize(bichoImagen.getWidth(),bichoImagen.getHeight());

Infinite Scrolling Texture

I am using the libgdx framework and trying to repeat a background of spikes forever. The issue I am having is that the texture is moving extremely fast forever, but I want to slow it down. I was looking at a tutorial from Google Code and another user had this same issue. The "supposed" solution was this:
if(scrollTimer>1.0f)
scrollTimer = 0.0f;
scrollTimer = 3f;
This was to make it scroll 3 times faster, so I attempted this and substituted 0.3f instead of 3f, but this makes the background at a standstill.
Here is some relevant code that might help in solving this issue:
public class PlayScreen implements Screen{
final Rectangle upSpikeBounds = new Rectangle(0,0,Gdx.graphics.getWidth() * 2, 25);
final Rectangle downSpikeBounds = new Rectangle(0,Gdx.graphics.getHeight() - 25,Gdx.graphics.getWidth() * 2, 25);
Rectangle blockBounds;
float total_time = 0f;
Sprite spikeUpSprite, spikeDownSprite, spriteBlock;
public PlayScreen(Game game){
batch = new SpriteBatch();
player = new Player(new Vector2(Gdx.graphics.getWidth()/10, Gdx.graphics.getHeight()/2), batch);
stage = new Stage();
this.game = game;
Texture spikeUp = new Texture(Gdx.files.internal("spikes.png"));
Texture spikeDown = new Texture(Gdx.files.internal("spikes.png"));
spikeUp.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
spikeDown.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
spikeUpSprite = new Sprite(spikeUp, 0, 0, Gdx.graphics.getWidth(), 25);
spikeDownSprite = new Sprite(spikeDown, 0, 25, Gdx.graphics.getWidth(), -25);
spikeDownSprite.setPosition(0, Gdx.graphics.getHeight() - 20);
spikeUpSprite.setSize(1200, 25);
spikeDownSprite.setSize(1200, 25);
}
public void render(float deltaTime) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
label.setText("Score: " + player.score);
cam.position.set(player.getPosition().x + Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight () / 2,0);
batch.setProjectionMatrix(cam.combined);
cam.update();
total_time += Gdx.graphics.getDeltaTime();
if (total_time > 1.0f){
total_time = 0.0f;
}
spikeUpSprite.setU(total_time);
spikeUpSprite.setU2((total_time+1));
spikeDownSprite.setU(total_time);
spikeDownSprite.setU2(total_time+1);
stage.act();
batch.begin();
spikeUpSprite.draw(batch);
spikeDownSprite.draw(batch);
batch.end();
stage.draw();
}
}
Can anyone help me?
You should look up the tween engine, it will enable you to use 'tween animation', which is an animation of values, who with a duration. For instance if you animate from zero to 700 with a 700ms duration, the value will start from zero and increase by 1 every ms
While micnubinub's answer is certainly interesting and worth checking out, I have figured out a quick fix for my issue. The problem lies in this line:
total_time += Gdx.graphics.getDeltaTime();
This is where the speed of the background lies. Because delta time is so fast (probably to the microsecond), the background scrolls by too fast. If I change it to a manual number, such as 0.0093f, I get a background that scrolls at the speed I desire.

Android problem with Image Rotate and Matrix

Hopefully this is an easy one because I've been trying all sorts of different ways to get rid of this.
I am making an android app which incorporates a clock animation. I've got everything working really well except one very annoying thing.
I have a second hand on the clock and I'm using the following code to rotate it around a the second hand center point. As you'll probably notice I'm trying to make this look like an analogue second hand so it sweeps instead of just ticking.
public float secdegrees, secondwidth, secondheight;
secondMatrix = new Matrix();
secondwidth = secondHand.getWidth();
secondheight = secondHand.getHeight();
secdegrees = anglepersec * secnow;
secdegrees += anglepluspermilli * millis;
secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
newSecond = Bitmap.createBitmap(secondHand, 0, 0,
(int) secondwidth, (int) secondheight, secondMatrix, true);
c.drawBitmap(newSecond, (centrex - newSecond.getWidth()/2),
((face.getHeight()/2) - newSecond.getHeight()/2), null);
It actually does just the job I want... almost.
The problem is the hand shakes/jiggles around the center point ever so slightly, but it's really noticeable and really spoils the aesthetics.
I pretty much suspect that it's the way that it's rounding the float value, but I was hoping that someone had experienced this before and had any ideas on how to get rid of it.
For reference the second hand image was originally 74 px x 28 px and is (currently) 74 x 74 pixels .png with the middle of the second hand exactly crossing the crossing point. I've also tried making it 75 x 75 so that there is actually a central pixel too but no luck.
Any help at all would be appreciated.
** UPDATE
I've tried to change the code in case the decimals were getting dropped but still no luck I'm afraid. Here is option 2 I've tried and failed with;
secondMatrix = new Matrix();
secondwidth = secondHand.getWidth();
secondheight = secondHand.getHeight();
secdegrees = anglepersec * secnow;
secdegrees += anglepluspermilli * millis;
secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, (int) secondwidth,
(int) secondheight, secondMatrix, true);
float secW = newSecond.getWidth()/2;
float secH = newSecond.getHeight()/2;
// NEW CODE HERE
float calcdeg = secdegrees % 90;
calcdeg = (float) Math.toRadians(calcdeg);
float NegY = (float) ((secondwidth*Math.cos(calcdeg)) +
(secondwidth * Math.sin(calcdeg)));
c.drawBitmap(newSecond, centrex - NegY/2,
((face.getHeight()/2) - NegY/2), null);
I understand your problem, I have never encountered it mysleft, but it sounds pretty obvious to me. Since the rotations changes the width and height of the image, your imprecision comes from centrex - NegX/2
I have not tested, but I suggest you try:
Matrix matrix=new Matrix()
//first translate to place the center of the hand at Point(0,0)
matrix.setTranslate(-secondWidth/2,-secondHeight/2);
matrix.setRotate(secdegrees);
//now place the pivot Point(0,0) at its expected location
matrix.setTranslate(centreX,centreY);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,0,0,null);
Of course, this is suboptimal, since the newSecond bitmap is much larger than it actually needs to be. So if your centrex and centrey are big, you might want to translate less than that, and then draw with a translation of the difference.
//now place the pivot to a position where the hand can be fully drawn without imprecion on the future location of Point(0,0)
matrix.setTranslate(secondWith,secondHeight);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,centrex-secondWidth,centrey-secondHeight,null);
Hope this helps.

Problems with glDrawTex_OES

I'm not sure I'm using glDrawTex_OES correctly. In fact, I'm sure I'm not because I'm getting a black rectangle on the screen rather than the intended texture.
To get the silly points out of the way: Yes, the GL Extension string contains the OES_draw_texture token. Yes, the texture is loaded into memory/etc. correctly: it displays just fine if I map it to a polygon.
From reading the various bits of documentation I can find for it, it looks like I need to "configur[e] the texture crop rectangle ... via TexParameteriv() with pname equal to TEXTURE_CROP_RECT_OES". According to this post in the khronos forums (best documentation google can find for me), the values for that are "Ucr, Vcr, Wcr, Hcr. That is, left/bottom/width/height"
Here's the render code:
void SetUpCamera( int windowWidth, int windowHeight, bool ortho ) // only called once
{
glViewport( 0, 0, windowWidth, windowHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
if( ortho )
{
float aspect = (float)windowWidth / (float)windowHeight;
float halfHeight = 32;
glOrthof( -halfHeight*aspect, halfHeight*aspect, -halfHeight, halfHeight, 1.0f, 100.0f );
}
else
{
mygluPerspective( 45.0f, (float)windowWidth / (float)windowHeight, 1.0f, 100.0f ); // I don't _actually_ have glu, but that's irrelevant--this does what you'd expect.
}
}
void DrawTexture( int windowWidth, int windowHeight, int texID )
{
// Clear back/depth buffer
glClearColor( 1, 1, 1, 1 );
glClearDepth( 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Next 2 lines probably not necessary, but, you know, sanity check:
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// set up texture
glBindTexture( GL_TEXTURE_2D, texID ); // texID is the glGenTexture result for a 64x64 2D RGB_8 texture - nothing crazy.
GLint coords [] = {0, 0, 64, 64};
glTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, coords );
// blit? =(
glDrawTexiOES( windowWidth / 2 - 32, windowHeight - 70, 10, 64, 64 );
}
Am I missing something obvious? Doing anything just plain dumb?
Apparently the problem is that you're (or I am, as the case may be) not calling glColor() with all full color channels first. This seems like a bug in the implementation I'm working with (Android, NDK), as the default Color should be (1, 1, 1, 1). Yet calling glColor4f(1, 1, 1, 1) is enough to fix things.
(I have no other calls to glColor in my program. Not sure if there's any other way to update the current color, but the textures render correctly using the default color and drawing them with glEnableClientState(GL_TEXTURE_COORD_ARRAY) / glDrawArrays() )

Categories

Resources