when setting up the sprite buttons in my libgdx project, i get displaced their touching area if i give a screen size that is bigger than my device one.
This is a simple example of the code i wrote. The main class extends Game...
public class Application extends Game
{
public SpriteBatch batch;
public OrthographicCamera camera;
public Vector3 touchPosition;
protected TitleScreen screen_title;
protected SettingsScreen screen_settings;
public PlayScreen screen_play;
#Override
public void create()
{
batch = new SpriteBatch();
camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
camera.setToOrtho(false,Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
touchPosition = new Vector3();
//SCREENS
screen_title = new TitleScreen(this);
screen_settings = new SettingsScreen(this);
screen_play = new PlayScreen(this);
this.setScreen(screen_title);
}
}
And a simple screen with an image to detect if is touched...
public TitleScreen(final Application game)
{
this.game = game;
game.camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
game.camera.position.set(Constants.VIEWPORT_WIDTH / 2, Constants.VIEWPORT_HEIGHT / 2, 0);
background = new Sprite(new Texture(Gdx.files.internal(Constants.PATH_BACKGROUND + "bg.png")));
img = new Sprite(new Texture(Gdx.files.internal("badlogic.jpg")));
}
#Override
public void render(float delta)
{
Gdx.gl.glClearColor(0.7f, 0.7f, 0.9f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.camera.update();
game.batch.setProjectionMatrix(game.camera.combined);
game.batch.begin();
background.draw(game.batch);
img.setPosition( Constants.VIEWPORT_WIDTH / 2, Constants.VIEWPORT_HEIGHT /2);
img.draw(game.batch);
game.batch.end();
//detect touch position
if(Gdx.input.justTouched())
{
game.touchPosition.set(Gdx.input.getX(), Gdx.input.getY(), 0);
game.camera.unproject(game.touchPosition);
if ((Gdx.input.getX() > img.getX()) &&
Gdx.input.getX() < img.getX() + img.getWidth() &&
Gdx.input.getY() < Gdx.graphics.getHeight() - img.getY() &&
Gdx.input.getY() > Gdx.graphics.getHeight() - (img.getY() + img.getHeight()))
{
System.out.println("TOUCHED BUTTON!!!");
System.out.println("X: " + Gdx.input.getX() + "/ Y: " + Gdx.input.getY());
}
}
}
As mentioned, this code sample works fine in desktop (any size) and my phone (if it has same or smaller screen size), but not when i use a bigger viewport size, and don't really understand why :)
Thanks a lot for the help :)
Related
I'm a little bit confused. I'm using libgdx for the first time and i have some problems with the coordinate systems. When i'm creating a texture and want to set the position, I do:
texture = new Texture("myGraphic.png", 0, 0);
and my picture will be positioned at the left bottom corner.
But when I try to get the touch position with:
if(Gdx.input.isTouched())
{
Vector3 tmp = new Vector3(Gdx.input.getX(),Gdx.input.getY(),0);
System.out.println("Coord:" + " + " + tmp.x + " + " + tmp.y);
}
I recognized that (0,0) is in the left top corner.
So I tried camera.unproject(tmp) before my output, but then i will get only values between -1 and 1.
How do i get the same coordinate system for all elements?
In Libgdx coordinate system for touch is y-down but for Screen or Image it's y-up.
Take a look of LibGDX Coordinate systems
If can use camera, set y-axis pointing up by camera.setToOrtho(false); and get world point by camera.unproject(vector3); method.
public class TouchSystem extends ApplicationAdapter {
SpriteBatch batch;
Texture texture;
Vector3 vector3;
OrthographicCamera camera;
#Override
public void create() {
batch=new SpriteBatch();
texture=new Texture("badlogic.jpg");
vector3=new Vector3();
camera=new OrthographicCamera();
camera.setToOrtho(false); // this will set screen resolution as viewport
}
#Override
public void render() {
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture,0,0);
batch.end();
if(Gdx.input.justTouched()) {
vector3.set(Gdx.input.getX(),Gdx.input.getY(),0);
camera.unproject(vector3);
System.out.println("Coord:" + " + " + vector3.x + " + " + vector3.y);
}
}
#Override
public void dispose() {
texture.dispose();
batch.dispose();
}
}
Im new on Box2d got a problem and couldnt solve it.
I want to move my player left and right when the user touch my left and right buttons.
I created a fixture I can move body and fixture but not the player sprite
How can I attach my player sprite to my body ?
and How should I control body because I cant stop it.
I want to find a proper way of controlling player in box2d. I couldnt use setLinerVelocity etc.
this is my codes
public World world;
public Body bplayer;
public Box2DDebugRenderer b2dr;
public Matrix4 cameraBox2D;
PlayScreen
buttonimage.addListener(new ClickListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
bplayer.setLinearVelocity(-5*PPM , 0);
return true;
}
});
world = new World(new Vector2(player.getPosition().x , player.getPosition().y) , false);
b2dr = new Box2DDebugRenderer();
bplayer = createPlayer(player.getPosition().x , player.getPosition().y);
show method
buttonimage.setPosition(160,0);
rightbuttonimage.setPosition(320,0);
pauseimage.setPosition(220,-20);
cameraBox2D = camera.combined.cpy();
Render method
Gdx.gl.glClearColor(0, 0, 2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.setProjectionMatrix(camera.combined);
player.position.y += 500 * Gdx.graphics.getDeltaTime();
sb.begin();
sb.draw(bg, 0, camera.position.y - (camera.viewportHeight/2));
sb.draw(player.sprite, player.getPosition().x , player.getPosition().y);
for (Tube tube : tubes) {
sb.draw(tube.getlefttube(), tube.getposlefttube().x, tube.getposlefttube().y);
sb.draw(tube.getrighttube(), tube.getposrighttube().x, tube.getposrighttube().y);
sb.draw(tube.getLight() , tube.getPoslight().x , tube.getPoslight().y);
}
delta*=speed;
sb.end();
update(delta);
b2dr.render(world , cameraBox2D);
stage.draw();
app.batch.begin();
app.font23.draw(app.batch,"Lights collected :" + dropsGathered , 0, 720);
app.batch.end();
cameraUpdate method
Vector3 position = camera.position;
position.x = player.position.x;
position.y = player.position.y;
camera.position.set(position);
createPlayer method
Body pBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(x * PPM, y * PPM );
def.fixedRotation = true;
pBody = world.createBody(def);
return pBody;
update method
world.step(1 / 60f , 6 , 2);
for(int i = 0; i < tubes.size; i++) {
Tube tube = tubes.get(i);
if (camera.position.y - (camera.viewportWidth/2) > tube.getposlefttube().y + tube.getlefttube().getWidth()) {
tube.reposition(tube.getposlefttube().y + ( TUBE_COUNT) );
}
if (tube.collides(player.getBounds())){
app.setScreen(new GameOver(app));
}
if (tube.gathered(player.getBounds())){
dropsGathered++;
}
if (dropsGathered >= 50){
//app.setScreen(new Stage2(app));
}
}
camera.update();
handleInput();
camera.position.y = player.getPosition().y + 300;
player.update(delta);
camera.update();
cameraUpdate(delta);
stage.act(delta);
Do not use the Sprite class. Use the TextureRegion class instead. Sprite is confusingly subclassed from TextureRegion, so when you call batch.draw(sprite, ...) its position and rotation parameters are ignored because it is being treated as a TextureRegion.
You could use a Sprite by calling sprite.draw(batch) but a Sprite is redundant because your Body already has position and rotation parameters.
Use a TextureRegion directly with the SpriteBatch. You can orient it with rotation parameters passed into the draw method.
I'm trying to move an image (300x300px) but it doesn't move smoothly, sometimes it stopped suddenly and then continued moving.
Here is my code in class "MyGdxGame" (extends "ApplicationAdapter"):
#Override
public void create() {
batch = new SpriteBatch();
img = new Texture("BG_z1_Moon.png");
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// speed = 200px/s
x -= Gdx.graphics.getDeltaTime() * 200.0f;
batch.begin();
batch.draw(img, x, 0);
batch.end();
System.out.println(Gdx.graphics.getDeltaTime() + "\tx=" + x);
}
I've try to translate camera, use Actor but I got the same result.
Thank you in advance and sorry for my poor English.
UPDATE Looks like this is a problem because of the static notification bar on tablet because of the lack of hardware buttons. I just didn't think about that. Anyway, in the case of the TF101 it returns a resolution of 1280x752 so about 1.702 (80 : 47) ratio. If I use a suitable unit size, like 33.5 or 11.75 vertically I get the proper scaling and this seems to fix the problem of skewed pixels.
END UPDATE
I've been setting up a game using 16x16 units for my tiled maps. I am using the resolution 1280x800 on both my desktop and android projects, I'm testing this to get a sense of how it will look on my TF101 asus tablet. I currently use a camera with units of 20x12.5 (wxh) and notice no pixel scaling on my desktop project, but when I run the game on my android I get weird scaling, and a green horizontal line. I can also move about quarter cell further along the x-axis on the tablet, shown in the screen shots. The pixels on the android project don't seem uniform at all.
I set the verticalTiles amount to 12.5f, then calculate the horizontalTiles amount as
verticalTiles = 12.5f;
...
horizontalTiles = (float) width / (float) height * verticalTiles;
camera = new OrthographicCamera(horizontalTiles, verticalTiles);
I'm aiming for devices with different aspect ratios to simply see more or less of the map, but can't seem to get working correctly. Any help would be appreciated.
Android Capture - http://imageshack.us/f/7/dsvg.png/ - notice the highlights on the roof edges, they are not uniform at all.
Desktop Capture - http://imageshack.us/f/853/5itv.png/
Current MainGame class
package com.bitknight.bqex;
/* Bunch of imports */
public class MainGame implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch spriteBatch;
private TiledMap map;
private OrthogonalTiledMapRenderer mapRenderer;
private Texture texture;
private Texture clothArmor;
private Sprite sprite;
private BitmapFont font;
private float horizontalTiles = 0;
private float verticalTiles = 12.5f;
private int hoverTileX = 0;
private int hoverTileY = 0;
private TiledMapTileLayer layer;
private Cell cell;
private TiledMapTile canMoveToTile;
private TiledMapTile cannotMoveToTile;
private AnimatedTiledMapTile animatedStopTile;
private AnimatedTiledMapTile animatedGoTile;
private Texture spriteSheet;
private TextureRegion region;
private Player player;
float h, w;
float ppuX, ppuY;
#Override
public void create() {
// Setup the animated tiles
Array<StaticTiledMapTile> tileArray;
// Start position on the sheet
int startX = 192;
int startY = 1568;
spriteSheet = new Texture(Gdx.files.internal("data/maps/tilesheet.png"));
spriteSheet.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
// We are trying to load two strips of 4 frames, 8 total
for( int i = 0; i < 2; ++i ) {
tileArray = new Array<StaticTiledMapTile>(4);
for( int j = 0; j < 4; ++j ) {
region = new TextureRegion(spriteSheet, startX, startY, 16, 16);
tileArray.add(new StaticTiledMapTile(region));
startX += 16;
}
if( i == 0 ) {
animatedStopTile = new AnimatedTiledMapTile(1/10f, tileArray);
} else {
animatedGoTile = new AnimatedTiledMapTile(1/10f, tileArray);
}
}
// Load the map
map = new TmxMapLoader().load("data/maps/base.tmx");
// Setup the two tiles that show movable and not movable sprites
canMoveToTile = map.getTileSets().getTileSet(0).getTile(1959);
canMoveToTile.setBlendMode(BlendMode.ALPHA);
cannotMoveToTile = map.getTileSets().getTileSet(0).getTile(1958);
cannotMoveToTile.setBlendMode(BlendMode.ALPHA);
// Manually create the layer used to show the cursor sprites
layer = new TiledMapTileLayer(100, 100, 16, 16);
layer.setName("display");
cell = new Cell();
cell.setTile(canMoveToTile);
layer.setOpacity(1f);
mapRenderer = new OrthogonalTiledMapRenderer(map, 1/16f);
spriteBatch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("data/consolas.fnt"), false);
font.setScale(0.6f);
texture = new Texture(Gdx.files.internal("data/maps/tilesheet.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
clothArmor = new Texture(Gdx.files.internal("data/img/native/clotharmor.png"));
region = new TextureRegion(clothArmor, 32, 256, 32, 32);
sprite = new Sprite(region);
sprite.setOrigin(0.5f, 0.5f);
sprite.setPosition(0f - 0.5f, 0f);
sprite.setSize(2, 2);
// Setup player and associated animations
Array<TextureRegion> regions = new Array<TextureRegion>();
player = new Player();
}
#Override
public void dispose() {
spriteBatch.dispose();
texture.dispose();
clothArmor.dispose();
spriteSheet.dispose();
}
#Override
public void render() {
player.update(Gdx.graphics.getDeltaTime());
camera.update();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if( Gdx.input.isKeyPressed(Input.Keys.ESCAPE) ) {
Gdx.app.exit();
}
// Clear the last cell
layer.setCell(hoverTileX, hoverTileY, null);
// Convert screen coordinates to world coordinates
Vector3 worldCoordinates = new Vector3(Gdx.input.getX(0), Gdx.input.getY(0), 0);
camera.unproject(worldCoordinates);
hoverTileX = (int)(worldCoordinates.x);
hoverTileY = (int)(worldCoordinates.y);
TiledMapTileLayer layer = (TiledMapTileLayer)map.getLayers().get("collision");
if( Gdx.input.isTouched(0) ) {
//sprite.setPosition(hoverTileX - 0.5f, hoverTileY);
player.pos.x = hoverTileX - 0.5f;
player.pos.y = hoverTileY - 0.25f;
cell.setTile(animatedGoTile);
} else {
if (layer.getCell(hoverTileX, hoverTileY) != null) {
cell.setTile(cannotMoveToTile);
} else {
cell.setTile(canMoveToTile);
}
}
layer.setCell(hoverTileX, hoverTileY, cell);
mapRenderer.setView(camera);
mapRenderer.render();
mapRenderer.getSpriteBatch().begin();
mapRenderer.renderTileLayer(layer);
mapRenderer.getSpriteBatch().end();
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.begin();
player.render(spriteBatch);
spriteBatch.end();
}
#Override
public void resize(int width, int height) {
horizontalTiles = (float) width / (float) height * verticalTiles;
camera = new OrthographicCamera(horizontalTiles, verticalTiles);
w = width;
h = height;
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
Looks like this is a problem because of the static notification bar on tablet because of the lack of hardware buttons. I just didn't think about that. Anyway, in the case of the TF101 it returns a resolution of 1280x752 so about 1.702 (80 : 47) ratio. If I use a suitable unit size, like 33.5 or 11.75 vertically I get the proper scaling and this seems to fix the problem of skewed pixels.
Also, while this is good for the TF101 tablet in my case it's not really a great solution. Here is a Gemserk series that talks about a nice solution.
http://blog.gemserk.com/2013/01/22/our-solution-to-handle-multiple-screen-sizes-in-android-part-one/
I'm having a hard time getting a spriteBatch to render in LibGDX. It shows when I run it for the desktop, but not on Android. I sprite I'm trying to render is the star background.
Desktop:
http://i.stack.imgur.com/6a4m5.png
Android:
http://i.stack.imgur.com/mOvo2.png
Here's my code:
#Override
public void render(float delta) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0, 0, 0, 1);
update(delta);
spriteBatchBack.begin();
sprite.draw(spriteBatchBack);
spriteBatchBack.end();
stage.act(delta);
stage.draw();
}
public void update(float delta) {
scrollTimer += delta * 0.03f;
if (scrollTimer > 1.0f)
scrollTimer = 0.0f;
sprite.setU(scrollTimer);
sprite.setU2(scrollTimer + 1);
}
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
#Override
public void resize(int width, int height) {
if (stage == null) {
stage = new Stage(width, height, true);
stage.clear();
addMusic();
addBackground();
addScence();
stage.addActor(play);
stage.addActor(options);
stage.addActor(quit);
stage.addActor(logoHead);
stage.addActor(lblPlay);
stage.addActor(lblOptions);
stage.addActor(lblQuit);
}
Gdx.input.setInputProcessor(stage);
}
public void addBackground() {
spriteBatchBack = new SpriteBatch();
Texture spriteTexture = new Texture(
Gdx.files.internal("pictures/menuBackground.png"));
spriteTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
sprite = new Sprite(spriteTexture, 0, 0, spriteTexture.getWidth(), spriteTexture.getHeight());
sprite.setSize(width, height);
}
If there's anything important that I am leaving out, comment and let me know. Thanks!
I found my problem. It turned out to be simply that the phones I used didn't support Open GL 2.0. To fix this I re-sized all my textures to the power-of-two, and changed the configuration settings to Open GL 1.1.
try to use "Image" actor as background in stage instead of using spritebatch and drawing yourself.