I'm trying to make a draggable image, still can't get the result. The image jumps on the Y-axis when I click on it.
My coding attempt:
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
Sprite sprite;
float offsetX;
float offsetY;
#Override
public void create() {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
sprite = new Sprite(img);
sprite.setPosition(200,200);
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite.draw(batch);
batch.end();
if (Gdx.input.justTouched()) {
offsetX = Gdx.input.getX() - sprite.getX();
offsetY = Gdx.input.getY() - (Gdx.graphics.getHeight() - (sprite.getY() + sprite.getHeight()));
}
if (Gdx.input.isTouched()){
sprite.setPosition(Gdx.input.getX() - offsetX, (Gdx.graphics.getHeight() - Gdx.input.getY()) - offsetY);
}
}
}
This is the result I'm getting:
How do I fix it?
offsetY = Gdx.graphics.getHeight() - Gdx.input.getY() - sprite.getY();
should work
Related
My goal is to draw all my visuals to a framebuffer which has a size that matches 1 by 1 with my pixel art assets. And then output the framebuffer texture to the current screen size. (A common solution for scaling pixel art).
The problem I am having while trying to achieve this is 2-fold
The frameBuffer texture is drawn too small. I expect the texture to match the whole window.
resizing the screen further distorts the proportions and position. I expect the frameBuffer texture to keep filling the screen after resizing it.
This is my trimmed down code.
public class BattleScreen extends GameScreen {
public static final int VISIBLE_WIDTH = 21;
public static final int VISIBLE_HEIGHT = 21;
private static OrthographicCamera mapCamera = null;
private SpriteBatch spriteBatch;
private OrthographicCamera hudCamera;
private Hud hud;
private EntityStage entityStage;
private FrameBuffer fbo;
private void initializeVariables(UnitOwner enemy, MapManager mapMgr) {
mapCamera = new OrthographicCamera();
mapCamera.setToOrtho(false, VISIBLE_WIDTH, VISIBLE_HEIGHT);
fbo = new FrameBuffer(Pixmap.Format.RGBA8888, 672, 672, false);
spriteBatch = new SpriteBatch(900);
entityStage = new EntityStage();
hudCamera = new OrthographicCamera();
hudCamera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
#Override
public void show() {
resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
mapCamera.position.set(currentMap.getMapWidth() * 0.5f, currentMap.getMapHeight() * 0.5f, 0f);
mapRenderer = new OrthogonalTiledMapRenderer(mapMgr.getCurrentTiledMap(), Map.UNIT_SCALE, spriteBatch);
mapRenderer.setView(mapCamera);
final FitViewport vp = new FitViewport(VISIBLE_WIDTH, VISIBLE_HEIGHT, mapCamera);
currentMap.getTiledMapStage().setViewport(vp);
entityStage.setViewport(vp);
}
private void update(final float delta) {
mapCamera.position.x = Utility.clamp(mapCamera.position.x, currentMap.getTilemapWidthInTiles() - (mapCamera.viewportWidth * 0.5f), 0 + (mapCamera.viewportWidth * 0.5f));
mapCamera.position.y = Utility.clamp(mapCamera.position.y, currentMap.getTilemapHeightInTiles() - (mapCamera.viewportHeight * 0.5f), 0 + (mapCamera.viewportHeight * 0.5f));
mapCamera.update();
hudCamera.update();
}
private void renderElements(final float delta) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
fbo.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderMap();
renderUnits();
renderHUD(delta);
fbo.end();
spriteBatch.begin();
Texture texture = fbo.getColorBufferTexture();
TextureRegion textureRegion = new TextureRegion(texture);
textureRegion.flip(false, true);
spriteBatch.draw(textureRegion, 0, 0, fbo.getWidth(), fbo.getHeight());
spriteBatch.end();
}
private void renderMap() {
spriteBatch.setProjectionMatrix(mapCamera.combined);
mapRenderer.setView(mapCamera);
currentMap.getTiledMapStage().getViewport().apply();
mapRenderer.render();
}
private void renderUnits() {
spriteBatch.begin();
entityStage.getViewport().apply();
for (Entity unit : units) {
final Color temp = spriteBatch.getColor();
spriteBatch.setColor(new Color(temp.r, temp.g, temp.b, unit.getEntityactor().getColor().a));
spriteBatch.draw(getFrame(), getEntityactor().getX(), unit.getEntityactor().getY(), 1.0f, 1.0f);
spriteBatch.setColor(temp);
}
}
private void renderHUD(final float delta) {
spriteBatch.setProjectionMatrix(hud.getStage().getCamera().combined);
hud.getStage().getViewport().apply();
hud.render(delta);
}
#Override
public void resize(final int width, final int height) {
currentMap.getTiledMapStage().getViewport().update(width, height, false);
entityStage.getViewport().update(width, height, false);
hud.resize(width, height);
pauseMenu.resize(width, height);
}
}
What I tried is changing the width and height on this line in the render method
spriteBatch.draw(textureRegion, 0, 0, 1000, 1000);
And then it does fill up the whole screen nicely
Which is weird because the screen is 672 x 672 in size.
Fixed problem 1 with the following adaptation
mapCamera.setToOrtho(false, fbo.getWidth(), fbo.getHeight()); //adapt camera to fbo
mapCamera.update();
spriteBatch.setProjectionMatrix(mapCamera.combined);
spriteBatch.draw(textureRegion, 0, 0, fbo.getWidth(), fbo.getHeight());
spriteBatch.end();
mapCamera.setToOrtho(false, VISIBLE_WIDTH, VISIBLE_HEIGHT); //reset camera
mapCamera.update();
The spriteBatch is being reused for the map, the entities and the ui for efficiency. So I had to configure it to project the buffer texture on the screen
I have an issue in LibGDX where when i call upon Gdx.input.getY(), it selects a pixel that's on the other side of the application relative to the center of the screen.
public class Main extends ApplicationAdapter {
private SpriteBatch batch;
private Texture img;
private OrthographicCamera camera;
int xPos;
int yPos;
private Vector3 tp = new Vector3();
BitmapFont font;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("crosshair.png");
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280, 720);
font = new BitmapFont();
}
#Override
public void render () {
yPos = Gdx.input.getY();
xPos = Gdx.input.getX();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.unproject(tp.set(xPos, yPos, 0));
batch.begin();
font.draw(batch,xPos + " , " + yPos, Gdx.input.getX() - 25, Gdx.input.getY() - 5);
batch.draw(img, xPos, yPos);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
}
Subtracting the viewport height with the touch location won't work, because that would be subtracting world coordinates with touch coordinates. (and even for a pixel perfect projection it would be height - 1 - y). Instead use the unproject method to convert touch coordinates to world coordinates.
There are two problems with your code:
You are never setting the batch projection matrix.
Even though you are using the unproject method, you are never using its result.
So instead use the following:
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
camera.unproject(tp.set(Gdx.input.getX(), Gdx.input.getY(), 0));
font.draw(batch,tp.x+ " , " + tp.y, tp.x - 25, tp.y - 5);
batch.draw(img, tp.x, tp.y);
batch.end();
}
I would suggest to read the following pages, which describe this and the reasoning behind it in detail:
https://github.com/libgdx/libgdx/wiki/Coordinate-systems
https://xoppa.github.io/blog/pixels/
https://github.com/libgdx/libgdx/wiki/Viewports
It's better to try this
yPos = camera.viewportHeight - Gdx.input.getY();
i'm trying to make my libgdx map scroll, but i dont know the code to make map scroll, please guys help me, i would like the map to scroll like flappy bird game, this is my my code which show the map on the screen
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
position.y = position.y - 4;
if(Gdx.input.isTouched()){
position.y = position.y +10;
}
if(position.y < 0){
position.y = 0;
}
if(position.y > Gdx.graphics.getHeight() -70){
position.y = Gdx.graphics.getHeight() - 70;
}
renderer.setView(camera);
renderer.render();
//tells the computer when to start drawing textures
batch.begin();
batch.draw(Green1, position.x, position.y, 50, 50);
batch.end();
}
#Override
public void show() {
Green1 = new Texture("img/Green1.png");
batch = new SpriteBatch();
position = new Vector2(20, Gdx.graphics.getHeight());
map = new TmxMapLoader().load("maps/map1.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
camera = new OrthographicCamera();
}
#Override
public void hide() {
}
#Override
public void create() {
Green1 = new Texture("img/Green.png");
batch = new SpriteBatch();
position = new Vector2(20, Gdx.graphics.getHeight());
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.position.set(width/2f, height/3f, 0); //by default camera position on (0,0,0)
camera.update();
}
#Override
public void render() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
map.dispose();
renderer.dispose();
}
}
When I was learning to build 2D games I used star-assault for an example. You can find their github repository here: https://github.com/chrismorales/2d-sidescroller && https://github.com/chrismorales/2d-sidescroller/blob/master/star-assault/src/net/obviam/starassault/view/WorldRenderer.java should be useful to look at.
Player Class
public class Player extends Sprite implements InputProcessor {
public Vector2 velocity = new Vector2();
private float speed = 500;
public Rectangle rectangle;
public Player(Sprite sprite){
super(sprite);
this.rectangle = sprite.getBoundingRectangle();
}
public void draw(SpriteBatch spriteBatch){
update(Gdx.graphics.getDeltaTime());
super.draw(spriteBatch);
}
public void update(float delta) {
rectangle = new Rectangle(getX() + velocity.x * delta,0,rectangle.getWidth(),rectangle.getWidth());
setX(getX() + velocity.x * delta);
}
}
PlayScreen Class
public class PlayScreen implements Screen {
private Player player;
private OrthographicCamera camera;
private OrthogonalTiledMapRenderer renderer;
private TiledMap map;
private Rectangle rightRectangle, leftRectangle, playerRectangle;
//private ShapeRenderer shapeRenderer;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
renderer.getSpriteBatch().begin();
player.draw(renderer.getSpriteBatch());
renderer.getSpriteBatch().end();
//shapeRenderer.begin(ShapeType.Filled);
//shapeRenderer.setColor(0, 1, 0, 1);
//shapeRenderer.rect(
// player.getX() + player.velocity.x * delta, 0,
// player.rectangle.getWidth(), player.rectangle.getHeight());
//shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
}
#Override
public void show() {
camera = new OrthographicCamera();
map = new TiledMap();
renderer = new OrthogonalTiledMapRenderer(map);
//shapeRenderer = new ShapeRenderer();
player = new Player(new Sprite(new Texture("img/player.png")));
rightRectangle = new Rectangle(1280,0,0,720);
leftRectangle = new Rectangle(0,0,0,720);
boolean wallLeft = leftRectangle.overlaps(player.rectangle);
boolean wallRight = rightRectangle.overlaps(player.rectangle);
if(wallLeft){
System.out.println("wallLeft Overlap");
player.velocity.x = 0;
}
else if(wallRight){
System.out.println("wallRight Overlap");
player.velocity.x = 0;
}
player.setPosition(
Gdx.graphics.getWidth()/2f - player.getWidth()/2f,
Gdx.graphics.getHeight()/2f - player.getHeight()/2f
- Gdx.graphics.getHeight()/5f);
}
}
Doesn't seem to be colliding correctly. The rightRectangle and leftRectangle are my screen side bounds. When I use the shapeRenderer, it produces the ShapeRendered rectangle and it will follow my player around. However, I believe that my player.rectangle is not moving at all for some reason, resulting in it not colliding with my side bounds. Any help would be greatly appreciated!
rightRectangle = new Rectangle(1280,0,0,720);
leftRectangle = new Rectangle(0,0,0,720);
A Rectangle is defined as Rectangle(x, y, width, height). It looks like you are trying to define it incorrectly as Rectangle(x1, y1, x2, y2). In the above, you have created two rectangles of 0 width.
I created small test, with the following code, and tried doing these steps to use the hotswap functionality.
Run the program using the Debug button
Create a break point in the render function, to pause the program.
Change the value of rectangle.width
Compile the program
Let intelliJ reload the code.
But this doesn't seem to change the size of the rectangle on the screen.
public class HotSwapTest extends ApplicationAdapter {
OrthographicCamera camera;
ShapeRenderer shapeRenderer;
private static final int SCREEN_WIDTH = 800;
private static final int SCREEN_HEIGHT = 480;
Rectangle rectangle;
#Override
public void create() {
shapeRenderer = new ShapeRenderer();
camera = new OrthographicCamera();
camera.setToOrtho(false, SCREEN_WIDTH, SCREEN_HEIGHT);
rectangle = new Rectangle();
rectangle.x = SCREEN_WIDTH / 2 - 64 / 2;
rectangle.y = 20;
rectangle.width = 100;
rectangle.height = 30;
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(1, 1, 0, 1);
shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
shapeRenderer.end();
camera.update(); // only if we're moving the screen though
}
}
Realized after typing this that I should have changed the width of the rectangle in the render function. Since create function won't be run again.
The following code works properly.
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
rectangle.width = 5; // Change this line while debugging.
rectangle.height = 10;
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(1, 1, 0, 1);
shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
shapeRenderer.end();
camera.update(); // only if we're moving the screen though
}