Capture Screen in libGdx - libgdx

I want to capture screen in libGdx . I use this code for my problem. On Desktop it work . But when I run on my android , I can't find image capture screen. How can I fix it? Thanks for reading my question.
public class ScreenshotFactory {
private static int counter = 1;
public static void saveScreenshot() {
try {
FileHandle fh;
do {
if (Gdx.app.getType() == ApplicationType.Desktop)
Infor.linkScreenShot = "D://chupngoc" + counter + ".png";
else
Infor.linkScreenShot = Gdx.files.getExternalStoragePath()
+ counter + ".png";
Infor.nameImage = counter + ".png";
fh = new FileHandle(Infor.linkScreenShot);
counter++;
} while (fh.exists());
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight(), true);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
} catch (Exception e) {
}
}
private static Pixmap getScreenshot(int x, int y, int w, int h,
boolean yDown) {
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
final Pixmap pixmap1 = new Pixmap(w, h, Format.RGBA8888);
ByteBuffer pixels1 = pixmap1.getPixels();
Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE,
pixels1);
Pixmap pixmap = pixmap1;
if (yDown) {
// Flip the pixmap upside down
ByteBuffer pixels = pixmap.getPixels();
int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
}

Your problem lies here...
fh = new FileHandle(Infor.linkScreenShot);
This way of creating a FileHandle is for the desktop only and will not work on Android.
You should create a file using Gdx.files.external instead...
fh = Gdx.files.external(Infor.linkScreenShot);

Related

Synchronize the paint() method of a Java Canvas instance?

Basically I am running a java emulator at 60 FPS and each time the screen refreshes it draws pixels from an array and paints it to the screen. I am getting a java.util.ConcurrentModificationException i.e. the contents of the pixel array are getting modified sometime during the paint() method execution. Is there a way I can synchronize the paint method or the generatePalette method to avoid this? Or is there another/better solution?
Code:
public class LCD extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int FRAME_RATE = 1 / 60 * 1000;
private BufferedImage canvas;
private List<Pixel> pixels = new ArrayList<>();
private int tilemapStart, tilemapEnd;
private GBCpuBootRom cpu;
private GBBus bus;
public void init() {
setTileMap(bus.cpuRUnsigned8(0xFF40));
generatePalette(bus, bus.cpuRUnsigned8(0xFF40));
}
public LCD(int len, int hei, GBCpuBootRom cpu, GBBus bus) {
canvas = new BufferedImage(len,hei,BufferedImage.TYPE_INT_ARGB);
this.cpu = cpu;
this.bus = bus;
Thread t = new Thread(this);
t.start();
}
public void setTileMapExplicit(int start, int end) {
tilemapStart = start;
tilemapEnd = end;
}
public void setTileMap(int mFF40) {
/*
* Bit 3 (bit 5)
* 0: 9800 to 9BFF
* 1: 9C00 to 9FFF
*
* Bit 4 (bit 4)
* 0: 8800 to 97FF
* 1: 8000 to 8FFF
*/
if ( ((mFF40 & 0b00001000) >> 3) == 1) {
tilemapStart = 0x9C00;
tilemapEnd = 0xA000;
}
else {
tilemapStart = 0x9800;
tilemapEnd = 0x9C00;
}
}
public void paint(Graphics g) {
for(Pixel p:pixels)
try {
canvas.setRGB(p.getX(), p.getY(), p.getColor().getRGB());
}
catch(Exception e) {
/*
* If a pixel cannot be drawn
* skip it and move on to next.
*/
System.out.println("Cannot draw pixel: " + p.getX() + ", " +
p.getY());
}
draw(g);
}
private void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(canvas, null, null);
}
public void generatePalette(GBBus bus, int mFF40) {
int hor = 0;
int ver = 0;
int x = 0;
int y = 0;
int inc = 8;
int pixelCount = 0;
/*
* maxRowPixels
* Each tile has 64 pixels
* if 256 x 256
* maxRowPixels = 2048 (32 * 64)
* else if 160 x 144
* maxRowPixels = 1280 (20 * 64)
*/
int maxRowPixels = canvas.getWidth() == 256 ? 2048 : 1280;
Pixel[] palettes;
Palette palette = new Palette();
for(int i = tilemapStart; i < tilemapEnd; i++) {
int dataAddr = spriteAddress((mFF40 & 0b00010000) >> 4, bus.cpuRUnsigned8(i));
/*
* Read range 0 to F
* e.g.
* 08000: 08000 to 0x800F
*
* 08000, 08002, 08004, 08006,
* 08008, 0800A, 0800C, 0800D,
*/
for(int k = 0; k < 16; k = k + 2) {
int hByte = bus.cpuRUnsigned8(dataAddr + k);
int lByte = bus.cpuRUnsigned8(dataAddr + (k + 1));
palette.setHB(hByte);
palette.setLB(lByte);
palette.setXY(x, y);
palette.init();
palettes = palette.getPixels();
for(Pixel pix: palettes)
pixels.add(pix);
x += inc;
pixelCount += inc;
if(x % 8 == 0) {
x = hor;
y++;
}
/*
* 1 tile completed
* 8 x 8 = 64p
* p means pixels
*/
if(pixelCount % 64 == 0) {
hor = hor + inc;
x = hor;
y = ver;
}
if(pixelCount % maxRowPixels == 0) {
x = 0;
hor = 0;
ver = ver + inc;
y = ver;
}
}
}
}
#Override
public void run() {
Thread.currentThread();
while(true) {
cpu.compute();
pixels.clear();
init();
try {
Thread.sleep(1000);
}
catch(Exception e) {
e.printStackTrace();
}
repaint();
}
}
}
This is the exception I get at line 66 (for loop in paint() method above)
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1009)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:963)
at gameboyconcept.logo.LCD.paint(LCD.java:66)

Libgdx : GestureListener - pan not working properly

I am new to libgdx and trying to move a circle vy draging it. But its not working properly.
class deceleration is as follows -
public class gScreen1 extends ScreenAdapter
implements GestureDetector.GestureListener {
private static final float WORLD_WIDTH = 640;
private static final float WORLD_HEIGHT = 480;
...
#Override
public void show() {
super.show();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(WORLD_WIDTH / 2, WORLD_HEIGHT / 2, 0);
camera.update();
viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);
shapeRenderer = new ShapeRenderer();
batch = new SpriteBatch();
}
private void drawGrid() {
Gdx.gl.glLineWidth(2);
shapeRenderer.setProjectionMatrix(camera.projection);
shapeRenderer.setTransformMatrix(camera.view);
shapeRenderer.setColor(Color.YELLOW);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
size = points.length;
for (int i = 0; i < size; i++) {
shapeRenderer.circle(pointsr[i].x , pointsr[i].y ,10);
}
shapeRenderer.end();
}
#Override
public void render(float delta) {
super.render(delta);
clearScreen();
drawGrid();
}
#Override
public boolean pan(float x1, float y1, float deltaX, float deltaY) {
Vector3 tmpCoords = new Vector3(x1,y1, 0);
camera.unproject(tmpCoords);
int x = (int)tmpCoords.x;
int y = (int)tmpCoords.y;
for( i = 0; i < size ; i++) {
int x2 = pointsr[i].x;
int y2 = pointsr[i].y;
if( ((x2 -x)*(x2 -x) + (y2 -y)*(y2 -y) ) < 400 )
break;
}
if( i < size ) {
pointsr[i].x += deltaX;
pointsr[i].y += deltaY;
}
}
Circles are not following movement of finger, some time they move a little bit but in opposite y direction of touch movement.

LibGDX : Detecting where a Ray hits a 3D object

I am building a 3D game in LibGDX, I have used the following code to work out if I touch a object, but how do I find out at what point it collides. I am not using Bullet as I want to make a HTML5 port
public int getObject (int screenX, int screenY) {
int result = -1;
float distance = -1;
Ray ray = camera.getPickRay(screenX, screenY);
Vector3 pos = new Vector3(camera.position);
for (int i = 0; i < boxInstance.size; i++) {
GameObject instance = boxInstance.get(i);
instance.transform.getTranslation(pos);
float dist2 = ray.origin.dst2(pos);
if (distance >= 0f && dist2 > distance) continue;
if (Intersector.intersectRayBoundsFast(ray, pos, instance.dimensions)) {
result = i;
distance = dist2;
Vector3 v = new Vector3();
if (Intersector.intersectRayBounds(ray, instance.bounds, v))
{
boxInstance.get(result).materials.get(0).set(ColorAttribute.createDiffuse(Color.RED));
}
}
}
if (result > -1)
{
//boxInstance.removeIndex(result);
}
return 1;
};
The reason I need this is if I touch a large plane, I want to be able to plane a object where I touch.
Update
I found intersectRayBounds which should do what I want but it never fires
Here is my GameObject class. Maybe my BoundingBox is wrong?
public class GameObject extends ModelInstance {
public final Vector3 center = new Vector3();
public final Vector3 dimensions = new Vector3();
public static BoundingBox bounds = new BoundingBox();
public GameObject (Model model, float x, float y, float z) {
super(model, x,y,z);
calculateBoundingBox(bounds);
bounds.getCenter(center);
bounds.getDimensions(dimensions);
}
}
I am not sure why this is the fix but it appears you have to compute the Bounding box everytime. See code below.
public int getObject (int screenX, int screenY) {
int result = -1;
float distance = -1;
Ray ray = camera.getPickRay(screenX, screenY);
Vector3 pos = new Vector3(camera.position);
for (int i = 0; i < boxInstance.size; i++) {
GameObject instance = boxInstance.get(i);
instance.transform.getTranslation(pos);
instance.updateBox();
float dist2 = ray.origin.dst2(pos);
if (distance >= 0f && dist2 > distance) continue;
Vector3 v = new Vector3();
if (Intersector.intersectRayBounds(ray, instance.bounds, v))
{
result = i;
distance = dist2;
Gdx.app.log("MyTag 2", "x " + v.x + " z " + v.z);
}
}
if (result > -1)
{
boxInstance.get(result).materials.get(0).set(ColorAttribute.createDiffuse(Color.RED));
}
return 1;
};
public class GameObject extends ModelInstance {
public final Vector3 center = new Vector3();
public final Vector3 dimensions = new Vector3();
public static BoundingBox bounds = new BoundingBox();
private float x,y,z;
public GameObject (Model model, float x, float y, float z) {
super(model, x, y, z);
this.x = x;
this.y = y;
this.z = z;
updateBox();
}
public void updateBox()
{
calculateBoundingBox(bounds);
bounds.getCenter(center);
bounds.getDimensions(dimensions);
bounds.set(bounds.min.add(x,y,z), bounds.max.add(x,y,z));
Gdx.app.log("MyTag 2", "x " + bounds.min + " z " + bounds.max );
}
}

Libgdx Screenshot method not working

A couple of weeks ago I implemented this method https://github.com/libgdx/libgdx/wiki/Take-a-Screenshot
And it worked great with libgdx 1.3.1 . Now though I upgraded to 1.6.0 and it have stopped working.
When the method is executed it freezes. I have it implemented on a button, and it gets stuck in "downclick" and nothing more happens.
private void saveScreenshot() {
try{
FileHandle fh;
do{
fh = new FileHandle(files.getLocalStoragePath() + "screenshot" + ".png");
}while(fh.exists());
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 130, true);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
System.out.println("Path:" + fh.toString());
}catch(Exception e) {
}
}
private Pixmap getScreenshot(int x, int y, int w, int h, boolean yDown){
final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(x, y, w, h);
w = pixmap.getWidth();
h = pixmap.getHeight();
if(yDown) {
ByteBuffer pixels = pixmap.getPixels();
int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
btnArrow.addListener(new ChangeListener() {
//photoshop "save" and "back" on arrow/back image to clarify.
#Override
public void changed(ChangeEvent event, Actor actor) {
saveScreenshot();
sharePhoto();
}
});
I share the image to facebook aswell. And this method is in AndroidLauncher of course and is passed through an interface. And here I fetch the screenshot:
public void sharePhoto() {
Matrix matrix = new Matrix();
String filePath = (files.getLocalStoragePath() + "screenshot" + ".png");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
Bitmap rotateBit = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
//Starts sharing process
SharePhoto photo = new SharePhoto.Builder()
.setBitmap(rotateBit)
.build();
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(photo)
.build();
share.show(content);
}
So what I believe may be the issue is libgdx have done changes on Pixmap class or Bitmap class of some sort. Since sharing a link through facebook on that button works fine.
I also printed the path as you can see in saveScreenshot() and it returns this
selinux_android_setcategory: no category for userid: 0, path: /data/data/com.sparc.tormt.android/lib
Is it stuck because this is an infinite loop if the file already exists:
do {
fh = new FileHandle(files.getLocalStoragePath() + "screenshot" + ".png");
} while(fh.exists());

Trying to create a circle with VBO's - LWJGL

Im trying to create a circle in LWJGL , using VBO's and VAO , and move it using an offset , but it seems one vertex is stuck in the center of the screen . I can't figure out how to move it to the new location . Any help is appreciated , thanks !
P.S : I have already tried debugging the program , but I can't locate the faulty vertex in my array
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
public class Test {
// Setup variables
private int WIDTH = 800;
private int HEIGHT = 600;
private String title = "Circle";
// Quad variables
private int vbo = 0; // Vertex Buffer Object
private int vao = 0; // Vertex Array Object
int SUBDIVISIONS = 100;
float[] vertex = new float[(SUBDIVISIONS + 1) * 4];
public Test() {
// Initialize
setupOpenGL();
setupQuad();
while (!Display.isCloseRequested()) {
loop();
Display.update();
Display.sync(60);
}
Display.destroy();
}
public void setupOpenGL() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setTitle(title);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(-1); // If error , exit program
}
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void setupQuad() {
float r = 0.2f;
float x;
float y;
float offSetX = 0.3f;
float offSetY = 0.3f;
vertex[0] = (float) Math.sin(Math.PI*2*0/SUBDIVISIONS) * r + offSetX;
vertex[1] = (float) Math.cos(Math.PI*2*1/SUBDIVISIONS) * r + offSetY;
for (int i = 2; i < 360; i = i + 2) {
double angle = Math.PI * 2 * i / SUBDIVISIONS;
x = (float) Math.cos(angle) * r;
vertex[i] = x + offSetX;
}
for (int i = 3; i < 360; i = i + 2) {
double angle = Math.PI * 2 * i / SUBDIVISIONS;
y = (float) Math.sin(angle) * r;
vertex[i] = y + offSetY;
}
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertex.length);
vertexBuffer.put(vertex);
vertexBuffer.flip();
vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,vertexBuffer,GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
public void loop() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL30.glBindVertexArray(vao);
GL20.glEnableVertexAttribArray(0);
// Draw the vertices
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, 0, vertex.length / 2);
// Put everything back to default (deselect)
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
public static void main(String[] args) {
new Test();
}
}
"I think I've found the problem . I was setting the positions of only 359 vertices out of 404 vertices (nr of subdivisions + 1 times 4) . It seems the rest of the vertices were stuck at 0,0 on the screen . Allowing both FOR statements to cycle up to 404 seems to solve the problem"