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);
Related
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.
I am new to android programming and trying to create 5 rectangles(two on the right side of the screen and three on the left side of the screen) on android using the canvas drawRect method, but it only shows the top left rectangle only. What am I doing wrong here? Thanks for your help.
Here's my RectAngle class:
public class RectAngle extends View {
public RectAngle(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float x = getWidth();
float y = getHeight();
Paint topLeftRect = new Paint();
Paint bottomLeftRect = new Paint();
Paint topRightRect = new Paint();
Paint midRightRect = new Paint();
Paint bottomRightRect = new Paint();
// Draw the top left rectangle
topLeftRect.setStyle(Paint.Style.FILL);
//topLeftRect.setColor(Color.WHITE);
topLeftRect.setColor(Color.parseColor("#FFFF99"));
// canvas.drawPaint(topLeftRect);
canvas.drawRect(0, 0, x / 2, y / 2, topLeftRect);
//Draw the bottom left rectangle
bottomLeftRect.setStyle(Paint.Style.FILL);
//bottomLeftRect.setColor(Color.WHITE);
// canvas.drawPaint(bottomLeftRect);
bottomLeftRect.setColor(Color.parseColor("#FFFF99"));
canvas.drawRect(0, y / 2, x / 2, 0, bottomLeftRect);
//Draw the top tight rectangle
topRightRect.setStyle(Paint.Style.FILL);
//topRightRect.setColor(Color.WHITE);
topRightRect.setColor(Color.parseColor("#FF6600"));
//canvas.drawPaint(topRightRect);
canvas.drawRect(x / 2, 0, 0, y / 3, topRightRect);
// Draw the middle right rectangle
midRightRect.setStyle(Paint.Style.FILL);
//midRightRect.setColor(Color.WHITE);
midRightRect.setColor(Color.parseColor("#66FFFF"));
// canvas.drawPaint(midRightRect);
canvas.drawRect(x / 2, 0, 0, y / 3, midRightRect);
//Draw the bottom right rectangle
bottomRightRect.setStyle(Paint.Style.FILL);
//bottomRightRect.setColor(Color.WHITE);
bottomRightRect.setColor(Color.parseColor("#CCCC00"));
// canvas.drawPaint(bottomRightRect);
canvas.drawRect(x/2, y/3, 0, 0, bottomRightRect);
}
}
Here's my main activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new RectAngle(this));
//setContentView(R.layout.activity_main);
}
Here's an image of my emulator. I am only getting one colored rectangle and it should be 4 more on the bottom left, top right, middle right, and bottom right of the screen.
Emulator image
public class RectAngle extends View {
public RectAngle(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float x = getWidth();
float y = getHeight();
Paint topLeftRect = new Paint();
Paint bottomLeftRect = new Paint();
Paint topRightRect = new Paint();
Paint midRightRect = new Paint();
Paint bottomRightRect = new Paint();
// Draw the top left rectangle
topLeftRect.setStyle(Paint.Style.FILL);
//topLeftRect.setColor(Color.WHITE);
topLeftRect.setColor(Color.parseColor("#FFFF99"));
// canvas.drawPaint(topLeftRect);
canvas.drawRect(0, 0, x / 2, y / 2, topLeftRect);
//Draw the bottom left rectangle
bottomLeftRect.setStyle(Paint.Style.FILL);
//bottomLeftRect.setColor(Color.WHITE);
// canvas.drawPaint(bottomLeftRect);
bottomLeftRect.setColor(Color.parseColor("#FF5599"));
canvas.drawRect(0, y / 2, x / 2, y, bottomLeftRect);
//Draw the top tight rectangle
topRightRect.setStyle(Paint.Style.FILL);
//topRightRect.setColor(Color.WHITE);
topRightRect.setColor(Color.parseColor("#FF6600"));
//canvas.drawPaint(topRightRect);
canvas.drawRect(x / 2, 0, x, y / 3, topRightRect);
// Draw the middle right rectangle
midRightRect.setStyle(Paint.Style.FILL);
//midRightRect.setColor(Color.WHITE);
midRightRect.setColor(Color.parseColor("#66FFFF"));
// canvas.drawPaint(midRightRect);
canvas.drawRect(x / 2, y/3, x, 2*y / 3, midRightRect);
//Draw the bottom right rectangle
bottomRightRect.setStyle(Paint.Style.FILL);
//bottomRightRect.setColor(Color.WHITE);
bottomRightRect.setColor(Color.parseColor("#CCCC00"));
// canvas.drawPaint(bottomRightRect);
canvas.drawRect(x/2, 2*y/3, x, y, bottomRightRect);
}
}
first of all, sorry, because of my rusty English. Since i learnt German i forgot the English.
I'm doing tests with libGDX and my code doesn't detect any collisions.
In my Screen:
public Pantalla(SpriteBatch batch_1) {
batch = batch_1;
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
stage = new Stage(new StretchViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()),batch);
Gdx.input.setInputProcessor(stage);
camera = new OrthographicCamera();
camera.setToOrtho(false, 1000, 840);
camera.update();
mapas = new Mapas(camera);
// ACTORS
indiana_actor = new indiana_Actor();
//Here comes TOUCHPAD with Skin blaBlaBla...
if (touchpad.isTouched()) {
if (touchpad.getKnobX() > 120) {
indiana_actor.moveBy(32,0);
camera.translate(32, 0);
return; }
}
stage.addActor(indiana_actor);
stage.addActor(touchpad);
Gdx.input.setInputProcessor(stage);
}
public void render(float delta) {//TODO RENDER
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapas.MapasRender(camera,indiana_actor);
batch.begin();
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
indiana_actor Class:
public indiana_Actor() {
W=Gdx.graphics.getWidth(); H=Gdx.graphics.getHeight();
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
Animation anim_temp;
#Override
public void draw(Batch batch, float parentAlpha) {
stateTime += Gdx.graphics.getDeltaTime();
batch.setColor(getColor());
batch.draw(Assets.indiana_stop_arriba, (W/2), (H/2), 110, 160);
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
and Mapas Class.
In these class i get the Objects in the "objetos" TiledLayer, and triying to check collisions with a for(...) in the renderer.
public Mapas(OrthographicCamera camera2){
map = new TmxMapLoader().load("terrain/prueba.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 10);//ESCALA
renderer.setView(camera2);
collisionObjects = map.getLayers().get("objetos").getObjects();
collisionRects = new Array<Rectangle>();
collisionRects_total=collisionObjects.getCount();
int tileWidth = 32; // whatever your tile width is
int tileHeight = 32; // whatever your tile height is
for (int i = 0; i < collisionObjects.getCount(); i++) {
RectangleMapObject obj = (RectangleMapObject) collisionObjects.get(i);
Rectangle rect = obj.getRectangle();
collisionRects.add(new Rectangle(rect.x / tileWidth, rect.y / tileHeight, rect.width / tileWidth, rect.height / tileHeight));
}
}
public void MapasRender(OrthographicCamera camera2,indiana_Actor indi){
camera2.update();
renderer.setView(camera2);
renderer.render();
for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i);
if (indi.bounds.overlaps(rect)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}if (rect.overlaps(indi.bounds)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}
}
}
I know (Through the logcat) that the
" for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i); "
get always the objectsRectangle , but in the next line find any overlaps.
Is that a problem with the actor bounds-rectangle?A problem when moving actor through the map??....
Thanks in advance!!
Why dont U at first check if your rectangle for collision draw correctly on position. You can do that by calling
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(Color.NAVY);
shapeRenderer.rect(object.getrect().x,
object.getrect().y,object.getrect().width,
object.getrect().height);
may be you draw collision rectangles at wrong position so collision will never occur.
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);
}
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.