I have a tiled map that is 40960px wide and 640px high.
I also have a main character and a badguy that are both 64px wide and 64px high.
Assuming that the bottom left corner of the tiled map is displayed at (0,0) in pixels.
I am trying to make the main character start at position (0,0) of the tiled map and be able to move all the way to the other end of the tiled map along the x axis dependent upon the users input.
Also I want a bad guy to be rendered at (255,0) on the x axis and to have a range of movement between 255 and 511 on the x axis this will be controlled programtically.
At the moment my code will display the tiled map and the two characters but when I move one of the characters the other character is moved as well.
I have a link here to an image for clarity
Here is my code in a class that implements libGdx screen interface.
public TestScreen(MyGame game){
this.game = game;
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2, 0);
camera.update();
String filename = "levelMaps/level_1.tmx";
map = new TmxMapLoader().load(filename);
mapRenderer = new OrthogonalTiledMapRenderer(map);
mainPlayer = new Player();
badGuy = new BadGuy();
badGuy.velocity.x = camera.position.x;
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapRenderer.setView(camera);
mapRenderer.render();
game.batch.begin();
mainPlayer.render(game.batch);
badGuy.render(game.batch);
game.batch.end();
//simple input handling
if(Gdx.input.isKeyPressed(Keys.LEFT)){
if(mainPlayer.velocity.x >= 0 && camera.position.x > 400){
mainPlayer.moveLeft();
camera.position.x -= Math.abs(superSim.velocity.x);
} else {
camera.position.x = 400;
superSim.velocity.x = 0;
}
}
if(Gdx.input.isKeyPressed(Keys.RIGHT)){
if(mainPlayer.velocity.x >= 0 && camera.position.x < 41286-(64*12)){
mainPlayer.moveRight();
camera.position.x += superSim.velocity.x;
}
}
camera.update();
mainPlayer.update(delta);
}
How can I get badguys position to remain the same whilst the players position is dynamic?
Anyhelp is truly appreciated
This is how i inialize my camera to be 16*9 units.
private OrthographicCamera camera;
camera = new OrthographicCamera(16, 9);
camera.position.set(camera.viewportWidth / 2,
camera.viewportHeight / 2, 0);
camera.update();
My resize method
public void resize(int width, int height) {
camera.viewportHeight = 16 * (float) height / (float) width;
camera.update();
}
Really my camera is 16*y units because i calculate height to keep same aspect ratio.
Use deltaTime for movement to make app run smoothly on different fps rates. Your input handling is very weird. Why do you change camera's position there? If you need to make your camera follow the player then make something like this:
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.mygdx.game.entities.Player;
public class ExtendedCamera extends OrthographicCamera {
public Player player;
public ExtendedCamera(Player player) {
super(Constants.WORLD_WIDTH, Constants.WORLD_HEIGHT);
this.player = player;
}
public void followPlayer() {
if (player.body.getPosition().x - position.x > Constants.CAMERA_FOLLOW_LINE_X) {
position.x = player.body.getPosition().x
- Constants.CAMERA_FOLLOW_LINE_X;
update();
} else if (player.body.getPosition().x - position.x < -Constants.CAMERA_FOLLOW_LINE_X) {
position.x = player.body.getPosition().x
+ Constants.CAMERA_FOLLOW_LINE_X;
update();
}
if (player.body.getPosition().y - position.y > Constants.CAMERA_FOLLOW_LINE_Y) {
position.y = player.body.getPosition().y
- Constants.CAMERA_FOLLOW_LINE_Y;
update();
} else if (player.body.getPosition().y - position.y < -Constants.CAMERA_FOLLOW_LINE_Y) {
position.y = player.body.getPosition().y
+ Constants.CAMERA_FOLLOW_LINE_Y;
update();
}
}
}
With this follow method player has zone where he can move freely and camera won't follow him. If player left this zone, camera moves.
Related
So I am trying to make a game with LWJGL 3 in Java. And I want to always keep the Player Object in the middle of the screen while moving the camera.
But I have problems doing that.
I tried to just set the position of camera to the player position but this doesn't work that well.
It dose move the player when the camera moves, however it doesn't move enough to keep the player in the middle.
This is my code :
public class Player extends Texture {
Camera camera;
public Player(Vector3f position, Vector3f rotation, Camera camera) {
super("/resources/textures/entities/Player.png", position, rotation, new Vector3f(0.1f, 0.2f, 0.1f));
this.camera = camera;
}
public void update() {
Vector3f camPos = camera.getPosition();
// set x and y from camera to player
this.getGameObject().getPosition().x = camPos.x;
this.getGameObject().getPosition().y = camPos.y;
}
}
My camera update method looks like this :
public void update() {
if (Input.isKeyDown(GLFW.GLFW_KEY_A)) {
this.position.x -= movementSpeed * Engine.delta;
}
if (Input.isKeyDown(GLFW.GLFW_KEY_D)) {
this.position.x += movementSpeed * Engine.delta;
}
if (Input.isKeyDown(GLFW.GLFW_KEY_W)) {
this.position.y += movementSpeed * Engine.delta;
}
if (Input.isKeyDown(GLFW.GLFW_KEY_S)) {
this.position.y -= movementSpeed * Engine.delta;
}
if (Input.isScrollingUp()) {
this.position.z -= movementSpeed * ZOOM_MULTIPLIER * Engine.delta;
if (this.position.z < MIN_Z) {
this.position.z = MIN_Z;
}
}
if (Input.isScrollingDown()) {
this.position.z += movementSpeed * ZOOM_MULTIPLIER * Engine.delta;
if (this.position.z > MAX_Z) {
this.position.z = MAX_Z;
}
}
}
I don't think there is something wrong with the camera update method but if it helps đ¤ˇ.
So yeah I tried a bit more but that worked even worse so please help me I can't find a solution.
Edit :
Here is my code for the renderer I however have only a vague idea how it works because I flowed this tutorial where this part wasn't explained that well. The source code for the Matrixf4 Class is here from the tutorial guy :
public void renderObject(GameObject object, Camera camera) {
GL30.glBindVertexArray(object.getMesh().getVAO());
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, object.getMesh().getIBO());
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMesh().getMaterial().getTextureID());
shader.bind();
shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale()));
shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation()));
shader.setUniform("projection", window.getProjection());
GL11.glDrawElements(GL11.GL_TRIANGLES, object.getMesh().getIndices().length, GL11.GL_UNSIGNED_INT, 0);
shader.unbind();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL30.glDisableVertexAttribArray(0);
GL30.glDisableVertexAttribArray(1);
GL30.glBindVertexArray(0);
}
The window.getProjection() just returns this :
Matrix4f.projection(70.0f, (float)width / (float) height, 0.01f, 5000.0f);
The first value is the fov, The second is the aspect ration and the last two are how near and far something can be until it won't be rendered anymore.
Edit 2 :
What I think is important is the scale variable because it scales the whole Mesh down so it doesn't cover the full screen.
Edit 3 :
Found out that the scale was the problem.
I just had to divide the cam position by the scale in the Player class:
public void update() {
Vector3f camPos = camera.getPosition();
this.getGameObject().getPosition().x = camPos.x / this.getGameObject().getScale().x;
this.getGameObject().getPosition().y = camPos.y / this.getGameObject().getScale().y;
}
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();
}
I got a problem on Box2d I'm new on Box2d so couldnt handle it movement of my player.
I want to move my player to the left and right when the user touch left and right buttons in my game.
in my game player already going through the up y axis .
I wanted see cool smooth animation while controlling player.
I just couldnt move my player to the left how can I do that ?
thanks in advance
//EDITED
I created a fixture for testing , I can move fixture but not my player.
how can I attach my player sprite to body ?
and I have to find a proper way to controlling body. it wont stop once you started.
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);
In your createPlayer method you can do body.setUserData(sprite). Then in your render method, you can do this (similar to how you are rendering tubes):
for (Body body : bodies) {
Sprite playerSprite = (Sprite) body.getUserData();
playerSprite.setPosition(body.getPosition().x, body.getPosition().y);
playerSprite.draw(spriteBatch);
}
This will update the sprite's position with the body's position.
I am programming a 2d platformer with libgdx, I'm trying to make a menu screen where the player can click a button and it will load that level. I use gdx.input for the click coordinates and TextureRegion.getRegionX() for the button coordinates. They don't sync together and I read that camera.unproject should fix this problem. I duly used it but the coords still don't match. camera.unproject seems to set 0,0 for x and y as the centre of the screen, while batch.draw (which is the method which draws the TextureRegion to screen) seems to be using the bottom left hand corner as x and y's 0, 0.
Here is the code, I left out what I didn't think was relevant:
public class LevelScreen implements Screen {
private TextureRegion level_bg;
private SpriteBatch batch;
private Camera camera;
private TextureAtlas textureAtlas;
private TextureRegion lockselectbg[]=new TextureRegion[10];
public LevelScreen(){
}
#Override
public void show() {
batch=new SpriteBatch();
camera = new OrthographicCamera(500,700);
LevelStatus.put();
LevelStatus.get();
textureAtlas=new TextureAtlas(Gdx.files.internal("levelatlas.pack"));
Array<AtlasRegion> atlasArrays = new Array<AtlasRegion>(textureAtlas.getRegions());
level_bg = atlasArrays.get(0);
lockselectbg[0] = atlasArrays.get(21);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(159/255.0f,220/255.0f,235/255.0f,0xff/255.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(level_bg, -500/2,-348/2);
batch.draw(lockselectbg[0], -180,0);
batch.end();
if(Gdx.input.isTouched()){
Vector3 tmp = new Vector3(Gdx.input.getX(),Gdx.input.getY(), 0);
camera.unproject(tmp);
Rectangle textureBounds = new Rectangle(lockselectbg[0].getRegionX(), lockselectbg[0].getRegionY(), lockselectbg[0].getRegionWidth(), lockselectbg[0].getRegionHeight());
if(textureBounds.contains(tmp.x, tmp.y)) {
System.out.println("It worked");
}
}
}
#Override
public void dispose() {
textureAtlas.dispose();
batch.dispose();
}
Camera#unproject will convert touch coordinates to world coordinates. They have nothing to do with the location of the region on the texture, which is what TextureRegion is. You are practically comparing world (read: game logic) coordinates with asset coordinates. Those two are completely unrelated.
If you want to check whether your image on the screen is touched then compare the touch coordinate with the location and size of the image you used in the batch.draw call. For example:
float x = -180f;
float y = 0f;
float width = 200f;
float height = 150f;
...
batch.draw(region, x, y, width, height);
...
camera.unproject(tmp.set(Gdx.input.getX(),Gdx.input.getY(), 0));
boolean touched = tmp.x >= x && tmp.y >= y && tmp.x < (x + width) && tmp.y < (y + height);
if (touched)
System.out.println("It worked");
Btw, you might want to read this post: http://blog.xoppa.com/pixels as well, because you are coupling your logic with asset size.
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.