I am having a problem that I think is possibly to do with texture coordinates, the image below shows my tile map being rendered - however sometimes there are gaps appearing between the tiles as can be seen in the screenshot at the following url (Half way down the screen there is a gap between tiles).
http://img15.imageshack.us/img15/4724/tileproblem.png
My texture regions are declared as
public class TextureRegion {
public final float u1, v1;
public final float u2, v2;
public final Texture texture;
public TextureRegion(Texture texture, float x, float y, float width, float height) {
this.u1 = x / texture.width;
this.v1 = y / texture.height;
this.u2 = this.u1 + width / texture.width;
this.v2 = this.v1 + height / texture.height;
this.texture = texture;
}
}
The tile textures come from an atlas and are 32x32 pixels, I am using GL_Nearest
being new to Open GL, I do not quite understand what I need to change.
Example of texture creation
tile = new TextureRegion(items, 192,160,34,34);
Cheers
Stuart
Make sure your texture are base 2, for example 128x256 or 512x512 etc.
Related
My application takes an image from the camera, saves it and then displays it on an ImageView, but the next step is to place a circle on top of the displayed image when the user touches the screen, and then save the "modified image".
Kinda like a image editor if you wish, problem is I do not know where to begin with the image editing. I tried this
#Override
public boolean onTouch(View v, MotionEvent event) {
circleView.setVisibility(View.VISIBLE);
circleView.setX(event.getX()-125);
circleView.setY(event.getY()-125);
try{
Bitmap bitmap = Bitmap.createBitmap(relativeLayout.getWidth(),relativeLayout.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
mImageView.setImageBitmap(bitmap);
FileOutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory());
bitmap.compress(Bitmap.CompressFormat.PNG,100,output);
output.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return true;
}//ENDOF onTouch
What can I do to save the image?
It'd be helpful if you included a bit more information about what libraries and language you're using. From the #override I'll assume this is java on android?
As for how to create a circle - there are many techniques you could use and there are probably more than a few libraries that you can use to do this. However, we can keep it pretty simple by using functions on the Bitmap object's interface, namely getPixels and setPixels.
What you need to do is grab a rectangle of pixels in to pre-allocated buffer (using getPixels), then draw your circle in to this buffer and then write the buffer back using 'setPixels'.
Here's a simple (although not exactly efficient) method for drawing a circle in the buffer you'd get from 'getPixels' in javaish pseudocode (untested):
//Return the distance between the point 'x1, y1' and 'x2, y2'
float distance(float x1, float y1, float x2, float y2)
{
float dx = x2 - x1;
float dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
//draw a circle in the buffer of pixels contained in 'int [] pixels'
//at position 'cx, cy' with the given radius and colour.
void drawCircle(int [] pixels, int stride, int height, float cx, float cy, float radius, int colour)
{
for (int y = 0; y < height; ++y)
for (int x = 0; x < stride; ++x)
{
if (distance((float)x, (float)y, cx, cy) < radius)
pixels[x + y * stride] = colour;
}
}
This just asks the question, for each pixel, 'is the point 'x,y' inside the circle given by 'cx, cy, radius'?' and if it is, it draw a pixel.
More efficient approaches might include a scanline rasteriser that steps through the left and right sides of the circle, removing the need to do a costly 'distance' calculation for each pixel.
However, this 'implicit surface' approach is quite flexible and you can achieve a lot of effects with it. Other options might be to copy a pre made circle bitmap instead of creating your own on the fly.
You could also blend the 'colour' based on the fractional value of 'distance - radius' to achieve anti-aliasing.
How can I determine the bounds of the x and y coordinate planes displayed on screen in my OpenGL ES program?
I need to fill the screen with 6 identical shapes, all equal in width & height, but in order to do this I must determine what values the x and y coordinate range across (so I can properly set the shape's vertices). In other words, I need a programmatic way to find out the value of -x and x, and -y and y.
Whats the simplest way to do this? Should I be manipulating/reading the projection matrix or the modelView matrix? Neither?
I know onSurfaceChanged() has access to the layout's height and width, but i'm not certain if these parameters are necessary to find the bounds of the on-screen coordinate bounds.
Below are the code snippets that show how I configure the frustum with the modelView and projection matrices:
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
// Enable depth testing
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// Position the eye in front of the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = -0.5f;
// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
...
}
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
layoutWidth = width; //test: string graphics
layoutHeight = height; //test: string graphics
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
screenSixth = findScreenSixths(width);
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
This problem of yours seems a bit strange. I could understand you want to manipulate the matrix so you will see all the objects on the screen but what you are asking is how to place the spheres so they are on the screen. In this case the on-screen projection of the spheres does not change and there is no reason to use the same matrix as you do for the rest of the scene. You may simply start with the identity and add a frustum to get the correct projection. After that the border values (left, right...) will be at border of your screen for Z value of near. So place the spheres at places such as (left+radius, top+radius, near).
If you still need some specific position of the spheres due to some interaction with other objects then you will most likely need to check the on-screen projections of the billboarded bounding square of the sphere. That means creating a square with the center the same as sphere and a width of twice the radius. Then multiply these square positions with the billboarded version of the sphere matrix. The billboarding can be found over the web to do properly but unless you do some strange operations on the matrices it usually works by simply setting the top left 3x3 part of the matrix to identity.
I was wondering if there was a way to make Android games in libgdx so they all share the same resolution of 480x800. Using Gdx.graphics.setDisplayMode(480, 800, true) doesn't seem to change anything. Creating an OrthographicCamera of 480 by 800 makes it so the game is 480 by 800, but doesn't zoom into fullscreen and take up the entire screen like I expected it would. When I tested it out on my phone, the phone just used blank space to fill up the rest of the screen while the game in 480x800 resolution. Here is the code that I'm using.
public class GameScreen implements Screen {
private Game game;
private OrthographicCamera guiCam;
private SpriteBatch batch;
private Texture texture;
private Rectangle glViewport;
public GameScreen (Game game)
{
this.game = game;
guiCam = new OrthographicCamera(GAME_WIDTH, GAME_HEIGHT);
guiCam.position.set(GAME_WIDTH / 2, GAME_HEIGHT / 2, 0);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/c2.png"));
glViewport = new Rectangle(0, 0, GAME_WIDTH, GAME_HEIGHT);
}
#Override
public void render(float delta) {
if (Gdx.input.justTouched()) {
texture = new Texture(Gdx.files.internal("data/c1.png"));
}
GL10 gl = Gdx.graphics.getGL10();
gl.glClearColor(1, 0, 0, 1);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glViewport((int) glViewport.x, (int) glViewport.y,
(int) glViewport.width, (int) glViewport.height);
guiCam.update();
guiCam.apply(gl);
batch.setProjectionMatrix(guiCam.combined);
batch.begin();
batch.draw(texture, 0, 0, 0, 0, 142, 192);
batch.end();
}
private static final int GAME_WIDTH = 480;
private static final int GAME_HEIGHT = 800;
}
Thanks in advance.
You've set your glViewport to 480x800, that means you're asking the phone hardware for a 480x800 window to draw on. Because most (all?) phone hardware doesn't do screen scaling (like your desktop monitor does), they just give you a 480x800 area on the screen.
You need to get OpenGL to "zoom" your screen, and you do that by setting the glViewport() to the physical resolution of your device (modulo aspect ratio caveats!). You should leave the camera at the 'virtual' resolution you prefer (so 480x800 in this case). Now OpenGL will scale all your primitives up to the screen's resolution.
As a quick test, try this:
gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
The next problem is that if the hardware aspect ratio doesn't match your 'virtual' aspect ratio. In that case you need to decide between stretching, leaving black bars on one side, or changing your virtual aspect ratio. See this blog post for more details on the camera/viewport setup, and some solutions to the aspect ratio issue: http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/
I want to create a live wallpaper, and I want to have the bottom background slide together with swiping homescreen pages, while another layer stays always on top of the background and under the app icons.
Is this possible and how can this be done?
You'll have to override public void onOffsetsChanged (float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset)
Using the value of xOffset, you can define a source rectangle that extracts part of your bitmap and draws that part on the screen.
This image should give you an understanding of how xOffset works:
Assuming that there are 5 homescreen pages,
If your picture is of size 960 x 800 (width x height) and if you want to draw a portion of size 480 x 800 every time, then you can define a source rectangle whose co-ordinates would be:
x1 = xOffset * (960 - 480); y1 = 0; x2 = x1 + 480, y2 = 800;
Then your destination rectangle would be the portion of the screen you want to draw onto.
You can then use public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint) method to draw the bitmap onto the screen.
I had used this technique a long time ago. I didn't check this in code before posting, and there may be alternatives (like using canvas.translate()). But hopefully this should help you get started. :)
I'm creating a game with libgdx that I want to run at a higher resolution on the desktop, but I want it to scale everything down correctly when I run it on android at smaller resolutions. I've read that the best way to do this is to not use a pixel perfect camera, and instead to use world coordinates, but I'm not sure how to correctly do that.
This is the code I have right now:
#Override
public void create() {
characterTexture = new Texture(Gdx.files.internal("character.png"));
characterTextureRegion = new TextureRegion(characterTexture, 0, 0, 100, 150);
batch = new SpriteBatch();
Gdx.gl10.glClearColor(0.4f, 0.6f, 0.9f, 1);
float aspectRatio = (float)Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
camera= new OrthographicCamera(aspectRatio, 1.0f);
}
#Override
public void render() {
GL10 gl = Gdx.graphics.getGL10();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
camera.apply(gl);
batch.setProjectionMatrix(camera.combined);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
draw();
}
private void draw() {
//batch.getProjectionMatrix().set(camera.combined);
batch.begin();
batch.draw(characterTextureRegion, 0, 0, // the bottom left corner of the box, unrotated
1f, 1f, // the rotation center relative to the bottom left corner of the box
0.390625f, 0.5859375f, // the width and height of the box
1, 1, // the scale on the x- and y-axis
0); // the rotation angle
batch.end();
}
The texture I'm use is 256x256 with the actual image in it being 100x150.
This is the result I get when I run the game: http://i.imgur.com/HV9Bi.png
The sprite that gets rendered is massive, considering this is the original image: http://i.imgur.com/q1cZT.png
What's the best way to go about making it so that the sprites get rendered at their original size while still keeping the ability to have the game scale correctly when played in different resolutions?
I've only found two solutions, both of which I don't like.
The image showed up how it was supposed to if I used pixel coordinates for the camera, but then that didn't scale at all when I put it on my phone with a different resolution.
I can scale the texture region down when I draw it, but it seems like there is a better way because it is extremely tedious trying to figure out the correct number to scale it by.
Have you ever used the Libgdx setup tool? When you create a project with it, it has a sample image that is displayed. It seems to keep it's ratio correct no matter what size you change the screen to.
public class RotationTest implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;
Stage stage;
public boolean leonAiming = true;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, h/w);
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); }....
#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();
sprite.draw(batch);
batch.end();
First of all you need to fix boundaries to the world (I mean to your game ). In that world only you actors(game characters) should play. If you are crossing boundaries, manage it with camera like showing up, down, left and right.