I have a sprite that I move around the world; it has its velocity increased based on a constant acceleration when the user touches the screen. I also move the camera with this sprite; but I also have a BG image that needs to stay still on the screen so the camera moves with the exact same velocity and acceleration as the background image so that it seems that the background is still. However, I see a slight out of sync between the camera and the background image; the background should stay still but it doesn't :
#Override
public void render () {
batch.setProjectionMatrix(camera.combined);
world_velocity += acceleration;
back.setPosition(back.getX(), back.getY() + world_velocity);
camera.position.y += world_velocity;
camera.update();
}
How can I sync the BG image with the camera so that the BG image stays still? NOTE : If I use constant velocity (no updates based on acceleration ) there is no issue.
Related
So here is my issue. I have a 800x800 libgdx game and I have created a 800x800 .png using gimp. I add it and draw it but the image now seems to be extremely larger than expected. For instance, if I have a ocean .png, all that renders is a dark blue screen. Seems like it is accepting my image but I am doing something else wrong. Any help would be awesome. Code is below. The player and enemy both render fine and on top of the blue.
private Texture img;
private TextureRegion textureRegion;
float drawingWidth,drawingHeight;
//Constructor
public GameScreen(Game game) {
this.game = game;
img = new Texture("tester2.png");
img.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.ClampToEdge);
int width=Gdx.graphics.getWidth();
textureRegion=new TextureRegion(img,0,0,width,img.getHeight());
drawingWidth=width;
drawingHeight=Gdx.graphics.getHeight();
Gdx.app.log(ID, "GameScreen is loaded! " + drawingWidth + " " + drawingHeight);
}
#Override
public void render(float deltaTime) {
//buffer screen
Gdx.gl20.glClearColor((11f / 255.0f), (11f / 255.0f), (11f / 255.0f), 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.begin();
sb.setProjectionMatrix(camera.combined);
update(deltaTime);
sb.draw(textureRegion,0,0,drawingWidth,drawingHeight);
sb.draw(img, 0, 0);
player.render(sb);
enemy.render(sb);
sb.end();
}
From my testing it seems like your camera's viewport is improperly configured. If you are using an OrthographicCamera then you want to use OrthographicCamera.setToOrtho() to set the viewport. Right now the camera is set to display a 2x2 pixel corner of your image. HOVEVER, your example is not replicable and I don't know how you set up your SpriteBatch or your Camera, or anything for that matter so I may be off.
P.S. why are you drawing img and texture region when they are the same? img will just put the image in the bottom left corner, textureRegion will repeat a few times across the screen.
This problem seemed very obvious for me to solve, but whatever I try, it doesn't work. What I'm trying to do is to incorporate a mini-version of my PlayScreen in a ScrollPane as a tutorial where you can read text and try it out immediately.
Because I didn't find any better solution to add this to the Table inside the ScrollPane, I edited the draw() method of the PlayScreen to take the ScrollPane.getScrollPercentY() and offset the camera of the PlayScreen accordingly.
What I want to do now is to only render only part of the viewport that would be normally visible in the real game. Subsequently, I want to be able to control the size and position of this "window".
I also want to be able to resize and move the content, while cutting off the edges that are not visible to the camera. This is what I tried inside the PlayScreenDraw:
public void draw(final float yOffset,
final int xTiles,
final int yTiles) {
view.getCamera().position.y = yTiles / 2f - yOffset * yTiles / HEIGHT; // HEIGHT = 800
view.getCamera().position.x = xTiles / 2f;
view.setWorldSize(xTiles, yTiles); //Do i even need to change the world size?
b.setProjectionMatrix(view.getCamera().combined);
b.begin();
...
b.end();
view.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
What this gives me, in terms of the picture above, is this
How do I need to change the viewport and/or the camera? Btw., this is how i set the two up:
cam = new OrthographicCamera();
cam.setToOrtho(false, WIDTH, HEIGHT); // WIDTH = 8, HEIGHT = 16
batch.setProjectionMatrix(cam.combined);
view = new FitViewport(WIDTH, HEIGHT, cam);
The Pixmap class can help you achieve what you want since you stated that you wanted to "cut off" the parts outside of the green selection box.
You need to render what the camera sees to an FBO and then get the pixmap from the FBO itself.
Framebuffer Objects are OpenGL Objects, which allow for the creation of user-defined Framebuffers. With them, one can render to non-Default Framebuffer locations, and thus render without disturbing the main screen.
-- OpenGL wiki
// Construct an FBO and keep a reference to it. Remember to dispose of it.
FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, width, height, false);
public void render() {
//Start rendering to the fbo.
fbo.begin();
//From the camera's perspective.
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Draw whatever you want to draw with the camera.
batch.end();
// Finished drawing, get pixmap.
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, width, height);
//Stop drawing to your fbo.
fbo.end();
}
After getting the pixmap you can iterate through the pixels and set the alpha of the pixels outside your green selection window to 0 making them invisible or "cutting them off"
I am trying to draw on the surface view using the Camera2 API sample code from Google. But for some reason, the drawing disappears after the camera preview starts. I am really confused as to why this is happening.
private void drawonSurfaceView(){
Paint paint = new Paint();
SurfaceHolder surfaceHolder= mOverlay.getHolder();
if(surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
//... actual drawing on canvas
paint.setStyle(Paint.Style.FILL);
int x = canvas.getWidth();
int y = canvas.getHeight();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
Rect rect = new Rect(50, 50, x-300, y-300);
canvas.drawRect(rect, paint );
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
I Have placed the code inside the setUpCameraOutputs() method.
That's true, you cannot lock the canvas of a preview surface for drawing. Some while ago, the SurfaceView used for camera preview required special settings (see What does SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS means?), but since API 11, this happens automagically.
You can always draw on a transparent view that is above the camera preview, but this is not the recommended solution. Much better, use a SurfaceTexture for your camera live stream, and draw with OpenGL in the 2D virtual world that includes that texture. To have your drawings synchronized with the camera stream, you should hide the preview texture and draw the camera frames yourself using the same callback that you use to feed the image processing algorithm.
I have a Sprite that spawns every second, what I wan't to do is change the sprite texture to animation, and the when it's touched it will be back to a normal texture.
public void draw(SpriteBatch batch){
enemyIterator=enemies.iterator(); //arraylist iterator
boolean touched=Gdx.input.justTouched();
float touchX=Gdx.input.getX();
//rendering and making the current sprite move
while(enemyIterator.hasNext()){
Sprite sprite=enemyIterator.next();
sprite.draw(batch);
sprite.translateY(deltaTime*movement);
//detecting if the screen is touched and if the inputX is inside of the sprite.
if(touched==true && touchX > sprite.getX() && touchX < sprite.getX()+sprite.getWidth()){
enemyIterator.remove(); //removing the sprite when touched.
Pools.free(sprite); //freeing the Pools
}
}
To change from a texture to an animation
Create a subclas of Sprite called MySprite or something, and override the draw(batch) method.
In the overriden draw method, if you want to draw a texture, simply call super.draw(batch), otehrwise use your animation draw code. You can get the delta time using Gdx.graphics.getDeltaTime()
Why you have to specify timePassed
Your program will run at different frame rates to the animation, so by telling the animation how much time has passed, it can work out what frame it should be on according to it's own framerate.
Note that the framerate of your app can vary from frame-to-frame depending on how much work it has to do.
I've searched all around google and this website for infos about this problem, but cannot solve it..
I'm a newbie in game development and LibGDX, and cannot find a solution well explained on how to port my game to all the various screen sizes..
Would you kindly help me?
Thanx
When using the newest libgdx version, you will find the Viewport class...
The viewport describes the transformation of the coordinate system of the screen (being the pixels from 0,0 in the lower left corner to e.g. 1280,768 in the upper right corner (depending on the device)) to the coordinate system of your game and scene.
The Viewport class has different possibilities on how to do that transformation. It can either stretch your scene coordinate system to exactly fit the screen coordinate system, which might change the aspect ratio and for example "stretch" your images or buttons.
It's also possible to fit the scene viewport with its aspect ratio into the viewport, which might produce a black border. E.g. when you have developed the game for 4:3 screens and now embed it into 16:10 displays.
The (in my opinion) best option is through fitting the scene viewport into the screen by matching either the longest or shortest edge.
This way, you can have a screen/window coordinate system from (0,0) to (1280,768) and create your game coordinate system maybe from (0,0) to (16,10) in landscape mode. When matching the longest edge, this means that the lower left corner of the screen will be (0,0), the lower right will be (16,0)... On devices that don't have the same aspect ratio, the y-values on the upper corners might differ a bit.
Or when matching the shortest edge, this means your scene coordinates will always be shown from (x,0) to (x,10) ... But the right edge might not exactly have and x value of 16, since device resolutions differ...
When using that method, you might have to reposition some buttons or UI elements, when they are supposed to be rendered on the top or the right edges...
Hope it helps...
Once me too suffered from this problem but at end i got the working solution, for drawing anything using SpriteBatch or Stage in libgdx. Using OrthographicCamera we can do this.
first choose one constant resolution which is best for game. Here i have taken 1280*720 (landscape).
class ScreenTest implements Screen {
final float appWidth = 1280, screenWidth = Gdx.graphics.getWidth();
final float appHeight = 720, screenHeight = Gdx.graphics.getHeight();
OrthographicCamera camera;
SpriteBatch batch;
Stage stage;
Texture img1;
Image img2;
public ScreenTest() {
camera = new OrthographicCamera();
camera.setToOrtho(false, appWidth, appHeight);
batch = new SpriteBatch();
batch.setProjectionMatrix(camera.combined);
img1 = new Texture("your_image1.png");
img2 = new Image(new Texture("your_image2.png"));
img2.setPosition(0, 0); // drawing from (0,0)
stage = new Stage(new StretchViewport(appWidth, appHeight, camera));
stage.addActor(img2);
}
#Override
public void render(float delta) {
batch.begin();
batch.draw(img, 0, 0);
batch.end();
stage.act();
stage.act(delta);
stage.draw();
// Also You can get touch input according to your Screen.
if (Gdx.input.isTouched()) {
System.out.println(" X " + Gdx.input.getX() * (appWidth / screenWidth));
System.out.println(" Y " + Gdx.input.getY() * (appHeight / screenHeight));
}
}
// ...
}
run this code in any type of resolution it will going to adjust in that resolution without any disturbance.