Multiple cameras and ScissorStack? - java

I'm currently trying to make a game, and I'm still novice with using cameras, and I'm thinking that two OrthographicCameras may be necessary, but I'm not sure if that's the most efficient way, or even how to do so.
Basically, I want this to be the layout for it:
The Main Area is where the main stuff is, which is a Server Interface. The Game Level is where the actual game part is in. I am currently using a ScissorStack to cut the region, but with this demo, results make me question how to do this:
public class TestScissorStackAndCamera extends ApplicationAdapter {
private SpriteBatch batch;
private OrthographicCamera camera;
private Sprite sprite;
private int width, height;
#Override
public void create() {
Gdx.gl.glClearColor(0, 0, 0, 0);
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
batch = new SpriteBatch();
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
createSprite();
}
private void createSprite() {
Pixmap map = new Pixmap(width, height, Format.RGBA8888);
map.setColor(Color.RED);
map.fillRectangle(0, 0, width, height);
map.setColor(Color.BLUE);
map.drawLine(width / 2, 0, width / 2, height);
map.drawLine(0, height / 2, width, height / 2);
Texture texture = new Texture(map);
sprite = new Sprite(texture);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined); // The Question!
batch.begin();
{
Rectangle scissors = new Rectangle();
Rectangle area = new Rectangle(10, 10, width - 20, height - 20);
ScissorStack.calculateScissors(camera, batch.getTransformMatrix(), area, scissors);
ScissorStack.pushScissors(scissors);
batch.draw(sprite, 0, 0);
batch.flush();
ScissorStack.popScissors();
}
batch.end();
}
public static void main(String[] args) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = "ScissorStack & Camera Test";
config.resizable = false;
new LwjglApplication(new TestScissorStackAndCamera(), config);
}
}
Questioning batch.setProjectionMatrix(camera.combined)
I marked a line in the code with a comment, The Question!, which is what is affecting the results. If I don't have it, using the camera.translate(...) method, the image is drawn at (0, 0) but what it does is it moves what part is viewed. If I do have that line, when I use the camera.translate(...) method, the image is drawn respectively to the position of the camera.
In respect to the game that I'm currently developing, it behaves awkwardly without the projectionMatrix not being set, but when I do set it, it messes up the positioning of the rest of the game. I even added some testing features, and it's not rendering inside of the correct ScissorStack
How could I go about setting up two cameras, or what could I do to set up what I'm trying to correctly and efficiently?
With my actual game (not the mock-up) this is what it is doing. It should be rendering inside of the red lines, but it's not:
If you'd like to see my current code for my GameLevel that is handling the ScissorStack and OrthographicCamera:
public GameLevel(int x, int y, int displayWidth, int displayHeight) {
this.x = x; // x = 10
this.y = y; // y = 10
this.displayWidth = displayWidth; // displayWidth = Gdx.graphics.getWidth() - x - 10
this.displayHeight = displayHeight; // displayHeight = Gdx.graphics.getHeight() - y - 120
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(displayWidth / 2, displayHeight / 2, 0);
// FBLAGame.batch.setProjectionMatrix(camera.combined);
camera.update();
init();
}
...
#Override
public void render() {
Rectangle area = new Rectangle(x, y, displayWidth, displayHeight);
Rectangle scissor = new Rectangle();
Matrix4 matrix = FBLAGame.batch.getTransformMatrix();
ScissorStack.calculateScissors(camera, matrix, area, scissor);
ScissorStack.pushScissors(scissor);
renderLevel();
FBLAGame.batch.flush();
ScissorStack.popScissors();
Pixmap map = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Format.RGBA8888);
map.setColor(Color.RED);
map.drawRectangle((int) area.x, (int) area.y, (int) area.width, (int) area.height);
Texture t = new Texture(map);
map.dispose();
FBLAGame.batch.draw(t, 0, 0);
}

Related

Java LibGDX how to check if sprite stands on specific tile e.g. door?

I want to change the map (method changeMapToWinter()) when sprite stands on specific tile of specific map. I have no layers on map.
Currently I do something like that if(sprite.getX() > 100 && sprite.getX() < 200 && sprite.getY() > 100 && sprite.getY() < 200) but of course it works only on one map and do not look too good and I guess there is a better solution for that.
Texture img;
TiledMap tiledMap;
OrthographicCamera camera;
TiledMapRenderer tiledMapRenderer;
SpriteBatch sb;
Texture texture;
Sprite sprite;
private ShapeRenderer shapeRenderer;
private TiledMapTileLayer tileLayer;
private TiledMap winterMap;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);
camera.update();
tiledMap = new TmxMapLoader().load("untitled.tmx");
winterMap = new TmxMapLoader().load("untitled2.tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap);
Gdx.input.setInputProcessor(this);
sb = new SpriteBatch();
texture = new Texture(Gdx.files.internal("bold_brown_blue-1.png"));
sprite = new Sprite(texture);
}
void changeMapToWinter() {
tiledMap.dispose();
winterMap = new TmxMapLoader().load("untitled2.tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(winterMap);
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
tiledMapRenderer.setView(camera);
tiledMapRenderer.render();
sb.begin();
sb.draw(sprite, (int) (Gdx.app.getGraphics().getWidth() / 2) - (sprite.getWidth()), (int) (Gdx.app.getGraphics().getHeight() / 2) - (sprite.getHeight() / 2));
sb.end();
Vector3 click = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
TiledMapTileLayer layer = (TiledMapTileLayer)tiledMap.getLayers().get(0);
// WANT TO CHANGE IT
if(sprite.getX() > 100 && sprite.getX() < 200 && sprite.getY() > 100 && sprite.getY() < 200)
changeMapToWinter();
}
Solution you might use can be something like this:
Rectangle changePosition = new Rectangle(100,100,100,100);
if(sprite.getBoundingRectangle().overlaps(changePosition)) ...
Constructor for rectangle have this format Rectangle(float x, float y, float width, float height).
Also this will behave a bit differently from your code as you weren't taking into account size of the sprite, but this code does.
Btw LibGDX have usefull class for problems like this if you wouldn't be able to find appropriate function in Rectangle class or whatever shape you are using. It is called Intersector.

how to maintain the appearance of the tiled map when I change the resolution in libGDX

i have created a test tiled map for a 2D game that i am programming. And everything is fine with!, but when i change the resolution the camera doesn´t fit the screen correctly.
I have a player sprite and the Tile map, and I use a resolution of 1366x768, as you can see the screen fit correctly:
but when i change the resolution, for example 640x480. The player doesn´t fit according to the new resolution as you can see in this picture:
The player seems bigger, but i want to fit the entire screen according to the new resolution, including all the sprites.
I think there is a problem with the cam rendering, but i don´t know what can i do to solve it. The camera is following the player movement and everything is ok with that, but i want to fit the screen game with the resolutions selected.
I'll put some parts of my code for you can see:
Here is the main code:
public class codeTiled implements ApplicationListener {
... //Variables.....
public void create() {
manager = new AssetManager();
manager.setLoader(TiledMap.class, new TmxMapLoader());
manager.load("C:/Users/HOME/Desktop/tilemap/TiledMap/data/maps/test.tmx", TiledMap.class);
manager.finishLoading();
map = manager.get("C:/Users/HOME/Desktop/tilemap/TiledMap/data/maps/test.tmx", TiledMap.class);
batch=new SpriteBatch();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(50, 50 * (h / w));
float unitScale = 1 / 8f;
renderer = new OrthogonalTiledMapRenderer(map, unitScale);
player=new playerEx(100, 100, camera);
}
public void render() {
handleInput();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
renderer.setView(camera);
renderer.render();
batch.begin();
player.render(batch);
batch.end();
}
private void handleInput() {
if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)){
System.exit(0);
}
camera.zoom = MathUtils.clamp(camera.zoom, 0.1f, 100/camera.viewportWidth);
float effectiveViewportWidth = camera.viewportWidth * camera.zoom;
float effectiveViewportHeight = camera.viewportHeight * camera.zoom;
camera.position.x = MathUtils.clamp(camera.position.x, effectiveViewportWidth / 2f, 100 - effectiveViewportWidth / 2f);
camera.position.y = MathUtils.clamp(camera.position.y, effectiveViewportHeight / 2f, 100 - effectiveViewportHeight / 2f);
}
And this is some part of my player class:
public class playerEx {
...//Variables....
public playerEx(int x, int y, OrthographicCamera camera){
this.camera=camera;
recP= new Rectangle();
recP.height = 64;
recP.width = 64;
recP.x = x;
recP.y = y;
imagen=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/minigunattack.png"));
imagen2=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/minigunstand.png"));
TextureRegion[][] tmp=TextureRegion.split(imagen,
imagen.getWidth()/5,imagen.getHeight());
imagen1=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/feet.png"));
TextureRegion[][] tmp1=TextureRegion.split(imagen1,
imagen1.getWidth()/5,imagen1.getHeight());
movPlayer=new TextureRegion[5];
movFeet=new TextureRegion[5];
for(int i=0;i<5;i++){
movFeet[i]=tmp1[0][i];
}for(int i=0;i<5;i++){
movPlayer[i]=tmp[0][i];
}animationAttack=new Animation(0.08f,movPlayer);
animationFeet=new Animation(0.10f,movFeet);
tiempo=0f;
}
Again, the camera is programmed to follow the player and it works fine. But when i want to change it to another resolution the sprite player doesn´t fit with the tiled map :(.
Hope somebody can help me with this...
Thank you!.
I recommend you to use a viewport and some Constants values for your world.
Firstly we define a default screen width and height in pixel. Doesn't matter how big the end screen will be.
In my example, I say the default screen size is: 512x256 pixel.
Secondly, I must decide how many pixels are one Meter. So if I say 256 pixels is one meter, my viewport shows 2x1 meter of my world. That's very small. If I want that my viewport shows for example 16 meter I can calculate: 512 / 16 = Pixel_Per_Meter. In this case 32.
Finally, we create a Constants class:
public class Constants {
public static final float PPM = 32; // PPM = Pixel per Meter
public static final float MPP = 1 / PPM; // MPP = Meter per Pixel
public static final int WORLD_PIXEL_WIDTH = 512;
public static final int WORLD_PIXEL_HEIGHT = 256;
public static final float WORLD_WIDTH = WORLD_PIXEL_WIDTH / PPM; //in meter
public static final float WORLD_HEIGHT = WORLD_PIXEL_HEIGHT / PPM; //in meter
}
Now when you see later in your game, the shown world is too small or too big, you can change the WORLD_PIXEL_WIDTH and WORLD_PIXEL_HEIGHT to show more or less
Now we create our OrthographicCamera, FitViewport and OrthogonalTiledMapRenderer
Viewport is a very important part of the game. If you will know more about Viewports read the viewport part of
calling render method from another class and Libgdx set ortho camera
So first create our OrthographicCamera 'camera' and our FitViewport 'viewport'
camera = new OrthographicCamera();
viewport = new FitViewport(Constants.WORLD_WIDTH, Constants.WORLD_HEIGHT, camera);
camera.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0); // Differ from your I eat ann Apple
Then our SpriteBatch 'batch' and TiledMap 'map'
batch = new SpriteBatch();
map = app.getAssets().loadSingleAsset("map/" + level + ".tmx", TiledMap.class);
And finally, our OrthogonalTiledMapRenderer 'mapRenderer'
mapRenderer = new OrthogonalTiledMapRenderer(map, Constants.MPP);
To render our world:
#Override
public void render(float delta) {
camera.update();
mapRenderer.setView(camera);
mapRenderer.render();
batch.setProjectionMatrix(camera.combined);
batch.begin();
player.draw(batch);
batch.end();
}

Kinect & Processing: Passing skeleton hand data to mouse position

I've been working on this a while and feel so close! Should be easy, but I'm still new to this.
The skeleton hand data is being passed in as joints[KinectPV2.JointType_HandLeft] and can be accessed through joint.getX() and joint.getY(). I want to pass this data into the update function to replace mouseX and mouseY. I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function? How can I replace the mouse position data with the hand position?
import KinectPV2.*;
KinectPV2 kinect;
private class MyFluidData implements DwFluid2D.FluidData{
// update() is called during the fluid-simulation update step.
#Override
public void update(DwFluid2D fluid) {
float px, py, vx, vy, radius, vscale, temperature;
radius = 15;
vscale = 10;
px = width/2;
py = 50;
vx = 1 * +vscale;
vy = 1 * vscale;
radius = 40;
temperature = 1f;
fluid.addDensity(px, py, radius, 0.2f, 0.3f, 0.5f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
boolean mouse_input = mousePressed;
// add impulse: density + velocity, particles
if(mouse_input && mouseButton == LEFT){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
vx = (mouseX - pmouseX) * +vscale;
vy = (mouseY - pmouseY) * -vscale;
fluid.addDensity (px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addVelocity(px, py, radius, vx, vy);
particles.spawn(fluid, px, py, radius*2, 300);
}
// add impulse: density + temperature, particles
if(mouse_input && mouseButton == CENTER){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
temperature = 2f;
fluid.addDensity(px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
}
// particles
if(mouse_input && mouseButton == RIGHT){
px = mouseX;
py = height - 1 - mouseY; // invert
radius = 50;
particles.spawn(fluid, px, py, radius, 300);
}
}
}
int viewport_w = 1280;
int viewport_h = 720;
int viewport_x = 230;
int viewport_y = 0;
int gui_w = 200;
int gui_x = 20;
int gui_y = 20;
int fluidgrid_scale = 3;
DwFluid2D fluid;
// render targets
PGraphics2D pg_fluid;
//texture-buffer, for adding obstacles
PGraphics2D pg_obstacles;
// custom particle system
MyParticleSystem particles;
// some state variables for the GUI/display
int BACKGROUND_COLOR = 0;
boolean UPDATE_FLUID = true;
boolean DISPLAY_FLUID_TEXTURES = false;
boolean DISPLAY_FLUID_VECTORS = false;
int DISPLAY_fluid_texture_mode = 0;
boolean DISPLAY_PARTICLES = true;
public void settings() {
size(viewport_w, viewport_h, P2D);
smooth(4);
}
public void setup() {
surface.setLocation(viewport_x, viewport_y);
// main library context
DwPixelFlow context = new DwPixelFlow(this);
context.print();
context.printGL();
// fluid simulation
fluid = new DwFluid2D(context, viewport_w, viewport_h, fluidgrid_scale);
// set some simulation parameters
fluid.param.dissipation_density = 0.999f;
fluid.param.dissipation_velocity = 0.99f;
fluid.param.dissipation_temperature = 0.80f;
fluid.param.vorticity = 0.10f;
fluid.param.timestep = 0.25f;
fluid.param.gridscale = 8f;
// interface for adding data to the fluid simulation
MyFluidData cb_fluid_data = new MyFluidData();
fluid.addCallback_FluiData(cb_fluid_data);
// pgraphics for fluid
pg_fluid = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_fluid.smooth(4);
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// pgraphics for obstacles
pg_obstacles = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_obstacles.smooth(4);
pg_obstacles.beginDraw();
pg_obstacles.clear();
float radius;
radius = 200;
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/2f, 1*height/4f, radius, radius/2, 10);
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/3.5f, 1*height/2.5f, radius, radius/2, 10);
//// border-obstacle
//pg_obstacles.strokeWeight(20);
//pg_obstacles.stroke(64);
//pg_obstacles.noFill();
//pg_obstacles.rect(0, 0, pg_obstacles.width, pg_obstacles.height);
pg_obstacles.endDraw();
fluid.addObstacles(pg_obstacles);
// custom particle object
particles = new MyParticleSystem(context, 1024 * 1024);
kinect = new KinectPV2(this);
//Enables depth and Body tracking (mask image)
kinect.enableDepthMaskImg(true);
kinect.enableSkeletonDepthMap(true);
kinect.init();
background(0);
frameRate(60);
}
public void draw() {
PImage imgC = kinect.getDepthMaskImage();
image(imgC, 0, 0, 320, 240);
//get the skeletons as an Arraylist of KSkeletons
ArrayList<KSkeleton> skeletonArray = kinect.getSkeletonDepthMap();
//individual joints
for (int i = 0; i < skeletonArray.size(); i++) {
KSkeleton skeleton = (KSkeleton) skeletonArray.get(i);
//if the skeleton is being tracked compute the skleton joints
if (skeleton.isTracked()) {
KJoint[] joints = skeleton.getJoints();
color col = skeleton.getIndexColor();
fill(col);
stroke(col);
drawHandState(joints[KinectPV2.JointType_HandRight]);
drawHandState(joints[KinectPV2.JointType_HandLeft]);
}
}
// update simulation
if(UPDATE_FLUID){
fluid.addObstacles(pg_obstacles);
fluid.update();
particles.update(fluid);
}
// clear render target
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// render fluid stuff
if(DISPLAY_FLUID_TEXTURES){
// render: density (0), temperature (1), pressure (2), velocity (3)
fluid.renderFluidTextures(pg_fluid, DISPLAY_fluid_texture_mode);
}
if(DISPLAY_FLUID_VECTORS){
// render: velocity vector field
fluid.renderFluidVectors(pg_fluid, 10);
}
if( DISPLAY_PARTICLES){
// render: particles; 0 ... points, 1 ...sprite texture, 2 ... dynamic points
particles.render(pg_fluid, BACKGROUND_COLOR);
}
// display
image(pg_fluid , 320, 0);
image(pg_obstacles, 320, 0);
// display number of particles as text
//String txt_num_particles = String.format("Particles %,d", particles.ALIVE_PARTICLES);
//fill(0, 0, 0, 220);
//noStroke();
//rect(10, height-10, 160, -30);
//fill(255,128,0);
//text(txt_num_particles, 20, height-20);
// info
//String txt_fps = String.format(getClass().getName()+ " [size %d/%d] [frame %d] [fps %6.2f]", fluid.fluid_w, fluid.fluid_h, fluid.simulation_step, frameRate);
//surface.setTitle(txt_fps);
}
//draw a ellipse depending on the hand state
void drawHandState(KJoint joint) {
noStroke();
handState(joint.getState());
//println(joint.getState());
pushMatrix();
translate(joint.getX(), joint.getY(), joint.getZ());
//println(joint.getX(), joint.getY(), joint.getZ());
ellipse(joint.getX(), joint.getY(), 70, 70);
popMatrix();
}
/*
Different hand state
KinectPV2.HandState_Open
KinectPV2.HandState_Closed
KinectPV2.HandState_Lasso
KinectPV2.HandState_NotTracked
*/
//Depending on the hand state change the color
void handState(int handState) {
switch(handState) {
case KinectPV2.HandState_Open:
fill(0, 255, 0);
break;
case KinectPV2.HandState_Closed:
fill(255, 0, 0);
break;
case KinectPV2.HandState_Lasso:
fill(0, 0, 255);
break;
case KinectPV2.HandState_NotTracked:
fill(100, 100, 100);
break;
}
}
I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function?
What happened when you tried those approaches?
Either approach sounds fine. You could store the variables in a sketch-level variable, set those variables from the kinect code, then use those variables in your drawing code. Or you could pass the variables as a parameter to the drawing code. Either should work fine. I'd probably go for the first approach because it sounds easier to me, but that's just my personal preference.
I suggest working in smaller chunks. Create a separate program that ignores the kinect for now. Create a hard-coded sketch-level variable that holds the same type of information you'd get from the kinect. Then write drawing code that uses that hard-coded variable to draw the frame. Get that working perfectly before you try adding the kinect code back in.
Then if you get stuck on a specific step, you can post a MCVE and we can go from there. Good luck.

Libgdx Orthographic Camera initial position

I would like the camera to be positioned correctly but I am getting the result below:
It seems like when I resize the window, the map does not get rendered properly. Why does that happen?
Code:
public void render(float delta){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
mapRenderer.setView(camera);
mapRenderer.render(background);
mapRenderer.render(foreground);
shapeRenderer.setProjectionMatrix(camera.combined);
//draw rectangles around walls
for(MapObject object : tiledMap.getLayers().get("walls").getObjects()){
if(object instanceof RectangleMapObject) {
RectangleMapObject rectObject = (RectangleMapObject) object;
Rectangle rect = rectObject.getRectangle();
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.rect(rect.x, rect.y, rect.width, rect.height);
shapeRenderer.end();
}
}
//done drawing rectangles
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
}
#Override
public void show(){
//call the tile map here
//I believe this is called first before render() is called
tiledMap = new TmxMapLoader().load("data/mapComplete.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(tiledMap, 1f);
//initiate shapeRenderer. Can remove later
shapeRenderer = new ShapeRenderer();
shapeRenderer.setColor(Color.RED);
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
This should center the camera at the viewport of the game.
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.position.set(width/2f, height/2f, 0); //by default camera position on (0,0,0)
}
You do not set the position of the camera anywhere. Thus it is looking at (0, 0) by default (which means (0, 0) will be in the center of your screen). The TiledMapRenderer renders the bottom left corner of the map at (0, 0) which means that it will fill the top right quadrant of your screen. That's what you see in your screenshot.
To set it to the center of the map, you could do something like the following:
TiledMapTileLayer layer0 = (TiledMapTileLayer) map.getLayers().get(0);
Vector3 center = new Vector3(layer0.getWidth() * layer0.getTileWidth() / 2, layer0.getHeight() * layer0.getTileHeight() / 2, 0);
camera.position.set(center);

Apply pixel Coordinates to Screen Coordinates

I'm trying to make an object appear where the person last touched. However when I try to do so it appears in the wrong place. I assume this is because of the fact the coordinates that the input returns is different to the display coordinates, my code is as follows:
public class Core implements ApplicationListener, InputProcessor
{ //Has to be here otherwise the code formatting becomes buggy
private Mesh squareMesh;
private PerspectiveCamera camera;
private Texture texture;
private SpriteBatch spriteBatch;
Sprite sprite;
float moveX = 0;
private final Matrix4 viewMatrix = new Matrix4();
private final Matrix4 transformMatrix = new Matrix4();
#Override
public void create()
{
Gdx.input.setInputProcessor(this);
texture = new Texture(Gdx.files.internal("door.png"));
spriteBatch = new SpriteBatch();
sprite = new Sprite(texture);
sprite.setPosition(0, 0);
viewMatrix.setToOrtho2D(0, 0, 480, 320);
float x = 0;
float y = 0;
}
#Override
public void dispose()
{
}
#Override
public void pause()
{
}
#Override
public void render()
{
viewMatrix.setToOrtho2D(0, 0, 480, 320);
spriteBatch.setProjectionMatrix(viewMatrix);
spriteBatch.setTransformMatrix(transformMatrix);
spriteBatch.begin();
spriteBatch.disableBlending();
spriteBatch.setColor(Color.WHITE);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//spriteBatch.draw(texture, 0, 0, 1, 1, 0, 0, texture.getWidth(),
// texture.getHeight(), false, false);
sprite.draw(spriteBatch);
spriteBatch.end();
update();
}
#Override
public void resize(int width, int height)
{
float aspectRatio = (float) width / (float) height;
camera = new PerspectiveCamera(67, 2f * aspectRatio, 2f);
}
#Override
public void resume()
{
}
public void update()
{
float delta = Gdx.graphics.getDeltaTime();
if(Gdx.input.isTouched())
{
Vector3 worldCoordinates = new Vector3(sprite.getX(), sprite.getY(), 0);
camera.unproject(worldCoordinates);
sprite.setPosition(Gdx.input.getX(), Gdx.input.getY());
float moveX = 0;
float moveY = 0;
}
}
I cropped this code for sake of simplicty.
I also made a video demonstrating the bug:
http://www.youtube.com/watch?v=m89LpwMkneI
Camera.unproject converts screen coordinates to world coordinates.
Vector3 pos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(pos);
sprite.setPosition(pos.x, pos.y);
Firstly, Gdx.input.getX() and Gdx.input.getY() return "screen coordinates". You want to transform these to your "camera coordinates". Screen coordinates typically have (0,0) in the top left corner of the window. I think your camera coordinates have (0,0) at the bottom left corner (either libgdx or opengl are doing that). Your video seems to suggest that this true. So you will need to multiply the Y value by -1. Secondly, I suspect the scale of the screen is different from the scale of the camera. I think you can fix the scale by multiplying by (world/screen).
Let's say your screen has width=800, height=600 and your world has width=480 height=320. Then your new X,Y for your sprite should be:
X = Gdx.input.getX()*(480/800)
Y = Gdx.input.getY()*(320/600)*-1
you should check your touch cordinates.
Gdx.app.log("", "hello x"+touchx);
Gdx.app.log("", "hello x"+touchy);
here touchx and touchy are your input x and input y variables
then do calculation where touch should work
like if u touched x=100,y=100
and touchx is coming 120
and touch y is coming 120
soo in your update method do this
sprite.setPosition(Gdx.input.getX()-20, Gdx.input.getY()-20);
i think this will help
I figured out the screen size/ game ratio and multiplied it to the current screen size:
rect.x=((((1024/Gdx.graphics.getWidth()))* Gdx.graphics.getWidth())
for a screen width of 1024 pixels
There must be an easier way however this works for me.

Categories