Unexpected results implementing simple motion blur in Libgdx - java

In the two attached pictures, the desktop screenshot of libgdx functions as expected. The screenshot from my Galaxy Nexus is unfortunately not as expected. I am attempting to create a simple motion blur or trail effect.
Rendering as I expected on my desktop.
Not rendering as I expected on my Galaxy nexus.
The circle textures are drawn in a for loop during rendering and the effect is achieved with a pixmap using the RGBA of 0, 0, 0, 0.1f that is drawn before the circles.
screenClearSprite creation
Pixmap screenClearPixmap = new Pixmap(256, 256, Format.RGBA8888);
screenClearPixmap.setColor(Color.rgba8888(0, 0, 0, 0.1f));
screenClearPixmap.fillRectangle(0, 0, 256, 256);
screenClearTexture = new Texture(screenClearPixmap);
screenClearSprite = new Sprite(screenClearTexture);
screenClearSprite.setSize(screenWidth, screenHeight);
screenClearPixmap.dispose();
Render
batch.begin();
font.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 0, 20);
screenClearSprite.draw(batch);
for (int i = 0; i < circleBodies.size(); i++) {
tempPos = circleBodies.get(i).getPosition();
batch.draw(circleTexture, (tempPos.x * SCALE) + screenWidthHalf
- circleSizeHalf, (tempPos.y * SCALE) + screenHeightHalf
- circleSizeHalf);
}
batch.end();
So, what did I do wrong? Perhaps there is a better way to get the 'motion blur' effect of movement?

Here is a different approach, where you clear your screen each time with solid color and no alpha.
This means that you will have to modify your code some. The good thing about this, is that the way you are doing it has some flaws: It will blur everything in motion, not just the balls. And can quickly produce ugly results/artefacts unless you are careful.
Do the same as you are doing now, but instead of drawing the balls to the batch, draw them onto a texture/bitmap/whatever. Then each frame add an alpha-blended image over the balls-image, and then draw the balls in their current position on top of that. Then add that image to your screen. Very much like you are doing now, except you draw to something else and keep it. This way you don't have to rely on the viewport you are drawing onto, and can keep everything separated.
This method is similar to drawing to an accumulation buffer.
Instead of doing it the way you are doing, you can keep track of the n latest positions of each ball. And then draw all of them each frame, with different alpha. This is very easy to implement. Can result in many drawing calls if you have many balls or a large n, but if it's not too much it shouldn't limit your fps and gives nice control.

Perhaps there is a better way to get the 'motion blur' effect of
movement?
in order to make motion blur in my game i use another approch "The particle effect" it works realy fine with me and i didn't have Android/Desktop problems or with different android devices
all you have to do is to use "Particle Effect Editor" of Libgdx and make your effect then load it in your project finally draw it at the same position you draw your object (and alos draw your object)
Tips to make the right effect file with Paticle Editor :
set (use) the same image of the object that you want to blur it motion in the particle effect
try to limit the count : the max number of particle allowed
Disable the "velocity" and "Angle"
parameter
Particle effect help to do motion effect
Hope this will help someone !

Related

Libgdx Spritebatch bug

however, i have a weird issue, when drawing, it seems the outside 1px of an image is stretched to fit a rectangle, but the inside is only stetched to an extend, i was drawing to 48x48 tiles, but drew a 500x500 tile to show the issue. [ 500x500 draws fine ]
the worst part seems to be, it chooses when to stretch and not to stretch. and also what to strech. im sorry this is hard to explain but i have attached a image that i hope does a better job.
it could just be misunderstanding how to use a draw with spritebatch
edit: Tile is 48x48 not 64x64, ive just been working all day.
This is because you are not rendering "pixel perfect" which means your image does not line up with the pixel grid of your monitor. A quick fix might be to set a linear filter for your textures, since by default it uses nearest and thus a pixel on the screen will inherit the closest color it can get. A linear filter will interpolate colors and make that line "look" thinner.
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
If you are using texturepacker you can do this in one go by altering it's settings.
texturePackerSetting.filterMin = Texture.TextureFilter.Linear;
texturePackerSetting.filterMag = Texture.TextureFilter.Linear;
Or you could edit the atlas file itself by by changing the filter parameter to:
filter: Linear,Linear
This obviously costs more power since it needs to do more calculations for each pixel you drawn to the screen but I would not worry about this until your drawing is starting to get a bottleneck.
Another solutions is to draw pixel perfect which means you need to set your viewport to the size of the device gdx.graphics.getWidth, gdx.graphics.getHeight, in other words a ScreenViewport and draw your textures at exact sizes you want them. Of course this means a screen with more pixels sees more of your game world then a screen with less pixels and the more pixels a device has the smaller your textures will look. Another drawback of this is that you have to forget about any zooming or draw sprites for each level of zoom so they line up with the pixel grid of the device again.

Java Libgdx get screenshot very slow

I write a game for android using libgdx. If the user opens the pause menu I take a screenshot of the current game, blur it and use it as background for the options menu. This works fine but the code for getting the screenshot is very slow. It takes about 0.8 seconds on average using the code below...
Is there another way to take a screenshot in libgdx which is much faster?
If not, when the user opens the options menu I could try to just keep rendering the game, pause the game logic and blur the screen and draw the options on top.. If this is the only fast way, how could one blur the screen? I found this link but I didn't get it to work.
If it is possible I prefer the solution with the screenshot because it is much easier...
Code to get the screenshot (from official wiki):
public static Pixmap getScreenshot(){
long start = TimeUtils.millis();
byte[] pixels = ScreenUtils.getFrameBufferPixels(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), true);
Pixmap pixmap = new Pixmap(Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), Pixmap.Format.RGBA8888);
BufferUtils.copy(pixels, 0, pixmap.getPixels(), pixels.length);
long time = TimeUtils.millis()-start;
Gdx.app.log("INFO", "Time for screenshot in sec.: " + time); // about 0.8 seconds
return pixmap;
}
I use the resulting Pixmap to draw my texture.
EDIT:
My code now with the answer of Deniz Yılmaz for getting the screenshot fast:
public Texture getScreenshot(){
Texture texture = new Texture(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Pixmap.Format.RGB888);
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
texture.bind();
Gdx.gl.glCopyTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGB, 0, 0,Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 0);
Gdx.gl.glDisable(GL20.GL_TEXTURE_2D);
return texture;
}
Actually taking screenshot is not slow.
Slow part is data transfer between GPU and CPU so any other way to get pixels wont be faster so much.
But also there are openGl codes helping us right here.
You can use opengl codes via Gdx.gl class.
void glCopyTexImage2D(
GLenum target, //Target Opengl Texture
GLint level, //Mipmap level
GLenum internalformat, //Color format
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLint border);
This function copy pixels into a 2D texture image but not bringing them to CPU.
You just belong a FBO at GPU.
In libgdx first you must bind texture to openGl's texture with a method.
This texture can be empty screen sized texture or you can use old texture you wont use again.
Texture.bind();
or
Gdx.gl.glBindTexture(Opengltexture, texture.getTextureObjectHandle());
For bounding and taking screen
Enable GPUtexture type.
Activate for exact GPUtexture
Call texture bind method
Call opengl function for active GPUtexture
Disable GPUtexture type.
Here is what code look like :
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
texture.bind();
Gdx.gl.glCopyTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA,0, 0,width , height, 0);
Gdx.gl.glDisable(GL20.GL_TEXTURE_2D);
Be aware binding is only active in 1 and 5. My fault was here because i tried to bind texture in create method and had got black screen.
BE AWARE!!!
On android, it needs opengl es 2.0 . You can edit manifest to make sure unsupported devices cant download your game.
< uses-feature android:glEsVersion="0x00020000"
android:required="true" >
RGBA format color space doesnt supported. So make sure you are
using Format.RGB for both opengl function and texture creation.
Result texture will be flipped vertically because of openGl matrix
system. So you have to fix it manually.
I also suggest you to look at fragments and shaders.
It seems like hard but actually enjoyable.

Android translated canvas collision of rectangles

im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.

Java & LibGDX: Limit Rendering Range of a Sprite

Recently I switched from using an array of integers as my screen in Java to using a library. The library I'm using is LibGDX, and the conversion for me is quite different. Most things I have already started to get the hang of, and I'm still writing a bit of the code myself.
At this point, I'm curious if I can limit the rendering range of Sprites and any other factor of drawing, such as if a sprite stuck half-way out of a box, it wouldn't render the part that was sticking out (as so:)
Is there a way to render in a specific range, and if it is partially out of the range, it doesn't render what is out of the range, or will I have to do that myself?
You can do simple "clipping" to a rectangle with the LibGDX ScissorStack.
Because OpenGL is stateful and many of the LibGDX drawing APIs cache, be sure to "flush" or "end" your batches within the range of the scissors. See libgdx ScissorStack not working as expected and libgdx Cutting an image
If i did not missunderstand you, you are looking for camera.
The camera lets you define a Viewport (size) and you only see things inside this Viewport.
You can also move it arroung to see other parts of the world.
For example:
OrthographicCamera cam = new OrthographicCamera(80, 45);
This defines a camera, which showes you 80 units in x and 45 units in y. It P(0/0) by default is in the middle of the screen, so this camera shows objects from -40 to +40 in x and -22.5 to + 22.5 in y.
You can move it, so that the P(0/0) is in the left lower corner:
camera.position.x = -40;
camera.position.y = -22.5;
camera.update();
This should move the camera to the left by 40 units and down by 22.5 units, so that the P(0/0) is the left lower corner. Don't forget to call update() as this recalculates the projection and view matrix.
Finally, to draw with this camera, you need to set the SptieBatchs projectionMatrix to the one of the camera:
spriteBatch.setProjectionMatrix(camera.combined);
Now you can use this SpriteBatch to draw.
You should also consider to se ViewFrustum-Culling, which means, that you don't draw things out of the camera, because they will never appear on screen, but the draw call costs some performance.

Rotate sprite on sprite pixel level, not screen pixel level, in LibGDX

I'm making a pixelated game, and I'm trying to rotate a sprite. However, I'm not achieving the sort of rotating effect I'm aiming for.
Currently, my sprite looks like this when it rotates:
As you can see, it rotates relatively smoothly. You can see that the 'big pixels' rotate smoothly. However, this isn't the rotating effect I'm looking for. Instead, this is how I want it to rotate:
However, preferably in a way that doesn't distort the pixels as much. You can see the difference. I want the actual 'big pixels' to rotate, not the 'screen pixels'.
I think the issue might lie in how I scale the pixels to become bigger. What I'm doing, is that I'm zooming the camera in, moving it closer sorta. What I instead want to do, is to render like normal, then just scale up the screen pixels. That way I'd automatically achieve the rotation effect I want. I don't know how to do that, though.
This is how I currently 'scale up the pixels':
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280 / 4, 720 / 4);
The game's resolution is 1280x720, so the way I make the pixels bigger is that I just zoom in 4x times.
However, what I instead want to do, is to render like normal, then just stretch the screen 4x times.
Any help on how I could do this would be greatly appreciated.
Have a look at this post. Here is a kind of solution for your problem. Just render first to small frame buffer with nearest neighbor interpolation and then to screen. Perhaps it is not effective way, but definitely the way to achieve such behavior.
Good luck!

Categories

Resources