I am using scene2d for a board game. I want the board to be zoomable and movable inside its assigned rectangular part of the screen, while the rest of the screen stays the same.
I have tried to use a separate stage for the board, but haven't found a way to initialise viewports and cameras that does this correctly.
I tried the following code in Screen.resize(int width, int height) as a test, but the boardStage becomes stretched vertically, and when zoomed in (like here), it fills the whole screen.
hudStage.setViewport(8, 12, true, 0, 12, width, height);
boardStage.setViewport(8, 8, true, 0, 10, width, width);
OrthographicCamera cam = (OrthographicCamera) boardStage.getCamera();
cam.zoom =.5f;
What is the correct way to do this?
We have implemented a similar zoom for our board game.
https://play.google.com/store/apps/details?id=net.peakgames.mobile.rummi.android
We are using a second camera which is zoomed:
A scissorStack is used to clip the second camera rendering area.
Second camera is enabled only when there is a touch/drag on the board.
we are changing the camera position as the user drags on the board.
hope this helps..
I think you want to use a scene2d ScrollPane instead of a new Stage. I'm not entirely sure how you'd do the zooming with this, but I think the scaling stuff should work.
Related
I'm wondering how the orthographic camera in LibGDX is positioned.
Is X bottom left or center or on right(etc)? And how it is with the Y?
I know its a simple question, but I'm messing around with my cam at this moment and I need some help :D
Libgdx camera coordinates is always CENTER of your screen.
For example if your viewportWidth and viewportHeight like
(800, 480)
it's coordinates will be
(400, 240)
In LibGDX, we have lots of coordinate systems (not only LibGDX, this applies to other engines/frameworks too). Camera is also a game object like other objects and thus is positioned like other objects.
The only difference about cameras is that they don't have width and height in the same sense of other objects. They are always a zero size point and can capture a rectangle (which is called viewport) centered on this point.
In your game if you use only one camera, what you see is the viewport that the only existent camera captures. So, if a sprite is on (0, 0) and also your camera is on (0, 0), you'll see that sprite exactly on the center of your screen.
Here's an example project using orthographic camera.
I'm working on a scroll-box in minecraft.
The scroll-box has one problem, some controls will render outside of the box, so i decided to look up if it's possible to prevent that.
I found stencils, but it doesn't work out, maybe i did something wrong?
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_STENCIL_TEST);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glClearStencil(0);
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
and this is the line of rendering the scroll-box background:
Vector4d color = new Vector4d(140, 140, 140, 255);
RenderHelper2D.drawGradientRect(1, 1, this.width-1, this.height-1, color, color);
http://i.imgur.com/Ycg7AKo.png (It's the black outlined gray pattern)
GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP );
render all objectives inside the scroll-box (the buttons). Which shouldn't be shown outside of the box.
gui.drawForeground(renderer);
and reset everything
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColorMask(true, true, true, true);
GL11.glDisable(GL11.GL_STENCIL_TEST);
I think you are looking for glScissor
It lets you basically assign a rectangular cropping window on your screen, and whatever you draw, nothing will ever be drawn outside of this rectangle.
Don't forget to call glEnable(GL_SCISSOR_TEST) before and glDisable(GL_SCISSOR_TEST) after you draw your scroll box. It won't work without the enable, and it won't stop without the disable ;)
Keep in mind that the values supplied to glScissor are integers for the origin and the width and height of the desired cropping window, the origin being defined as the lower left. Thus,
glEnable(GL_SCISSOR_TEST)
glScissor(0,0,100,100)
:: DRAW YOUR CONTROLS HERE ::
glDisable(GL_SCISSOR_TEST)
will create a 100x100 cropping window in the lower left corner of your screen.
You can use stencilbuffers if you want, but those are for more complicated tasks. Since UI usually works with rectangles, glScissor is perfect for it.
I'am trying to make libgdx game, adn i've got 2 problems now:
1. When im using camera.setToOrtho(false, GAME_WIDTH, GAME_HEIGHT); my textrure of player is distored, one eye is bigger than another.
2. Im using this camera and viweport:
camera= new OrthographicCamera(GAME_WIDTH,GAME_HEIGHT);
camera.setToOrtho(false, GAME_WIDTH, GAME_HEIGHT);
viewport = new StretchViewport(GAME_WIDTH,GAME_HEIGHT,camera);
and when i do :
touchPos.set(Gdx.input.getX(1),Gdx.input.getY(1),0);
game.camera.unproject(touchPos);
System.out.println(touchPos.x+" "+ touchPos.y);
I get 0 0 in right top corner but my character witch cords 0 0 is drawing in left bottom corner.
When i use:
game.camera = new OrthographicCamera(820,480);
game.viewport = new FillViewport(820,480,game.camera);
i must use game.batch.setProjectionMatrix(game.camera.combined);
when i use this code i've got corectly working unproject method and coordinate system but i've got distored texture.
When i use:
camera = new PerspectiveCamera();
viewport = new StretchViewport(900, 470, camera);
i've got distored texture and bad coords system. and i can 't use :game.batch.setProjectionMatrix(game.camera.combined);
It is distorted because you are using a fixed width and height for the camera, so it simply stretches to fit whatever size window/screen you're putting it on.
Incidentally, StretchViewport does the same thing (distorts the scene to fit the dimensions you gave it to the window). But you just created a viewport without actually calling update() on it, so it's not doing anything.
You most likely want to use ExtendViewport or FillViewport to avoid stretching, but other options are available. Read about them here.
Your viewport won't properly respond to screen rotations (or desktop window resize) unless you put viewport.update(width,height) into the resize method. And you have to call update on it at least once regardless, using the actual screen dimensions. This is most convenient by simply putting viewport.update(width,height) into the resize method.
I have a rectangular group that holds a bunch of sprites. Sprites are moving (say up). As they reach the top, they collide with the boundary. I have set up logic that kills the sprites as they exit the group. However, the way it is now, I can see the sprite leaving the group. I want to make it so that as the sprite is crossing the boundary, it's gradually disappearing until it's out (and dead).
Here's a crude mockup of what I want to achieve.
I was playing around with cameras thinking I have to modify the viewport, but it's not working. What's the proper way of achieving this effect?
Thanks!
EDIT:
My camera was set up like this:
camera = new OrthographicCamera(width, height);
camera.setToOrtho(false, width, height);
camera.position.set(width/2, height/2, 0);
Right now it's operating from the group's parent level (layer). Width and height are Gdx.graphics.getWidth(), etc.
My update():
camera.position.x = (width / 2) - resolver.getxPixelOffset()*parallax;
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
g.drawGroup(batch);
batch.end();
I moved my camera controls to my group class. I then changed the width and height to groupWidth and groupHeight. Since the group is not the entire screen, I figured it has to be smaller. This made the group massive. I don't want to change the size (or zoom?) of the group :(
I haven't tested this myself, but I believe the proper way of doing this would be using scissors. Basically, the scissors allow you to clip a region out of your picture, and only allow things in that region to be drawn, so you would probably do something like similar to what they do in the demo here:
Rectangle scissors = new Rectangle();
Rectangle clipBounds = new Rectangle(x,y,w,h);
ScissorStack.calculateScissors(camera, spriteBatch.getTransformMatrix(), clipBounds, scissors);
ScissorStack.pushScissors(scissors);
spriteBatch.draw(...);
spriteBatch.flush();
ScissorStack.popScissors();
You may need to draw and flush your background image (if you have one) before you draw with the scissors.
In the two attached pictures, the desktop screenshot of libgdx functions as expected. The screenshot from my Galaxy Nexus is unfortunately not as expected. I am attempting to create a simple motion blur or trail effect.
Rendering as I expected on my desktop.
Not rendering as I expected on my Galaxy nexus.
The circle textures are drawn in a for loop during rendering and the effect is achieved with a pixmap using the RGBA of 0, 0, 0, 0.1f that is drawn before the circles.
screenClearSprite creation
Pixmap screenClearPixmap = new Pixmap(256, 256, Format.RGBA8888);
screenClearPixmap.setColor(Color.rgba8888(0, 0, 0, 0.1f));
screenClearPixmap.fillRectangle(0, 0, 256, 256);
screenClearTexture = new Texture(screenClearPixmap);
screenClearSprite = new Sprite(screenClearTexture);
screenClearSprite.setSize(screenWidth, screenHeight);
screenClearPixmap.dispose();
Render
batch.begin();
font.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 0, 20);
screenClearSprite.draw(batch);
for (int i = 0; i < circleBodies.size(); i++) {
tempPos = circleBodies.get(i).getPosition();
batch.draw(circleTexture, (tempPos.x * SCALE) + screenWidthHalf
- circleSizeHalf, (tempPos.y * SCALE) + screenHeightHalf
- circleSizeHalf);
}
batch.end();
So, what did I do wrong? Perhaps there is a better way to get the 'motion blur' effect of movement?
Here is a different approach, where you clear your screen each time with solid color and no alpha.
This means that you will have to modify your code some. The good thing about this, is that the way you are doing it has some flaws: It will blur everything in motion, not just the balls. And can quickly produce ugly results/artefacts unless you are careful.
Do the same as you are doing now, but instead of drawing the balls to the batch, draw them onto a texture/bitmap/whatever. Then each frame add an alpha-blended image over the balls-image, and then draw the balls in their current position on top of that. Then add that image to your screen. Very much like you are doing now, except you draw to something else and keep it. This way you don't have to rely on the viewport you are drawing onto, and can keep everything separated.
This method is similar to drawing to an accumulation buffer.
Instead of doing it the way you are doing, you can keep track of the n latest positions of each ball. And then draw all of them each frame, with different alpha. This is very easy to implement. Can result in many drawing calls if you have many balls or a large n, but if it's not too much it shouldn't limit your fps and gives nice control.
Perhaps there is a better way to get the 'motion blur' effect of
movement?
in order to make motion blur in my game i use another approch "The particle effect" it works realy fine with me and i didn't have Android/Desktop problems or with different android devices
all you have to do is to use "Particle Effect Editor" of Libgdx and make your effect then load it in your project finally draw it at the same position you draw your object (and alos draw your object)
Tips to make the right effect file with Paticle Editor :
set (use) the same image of the object that you want to blur it motion in the particle effect
try to limit the count : the max number of particle allowed
Disable the "velocity" and "Angle"
parameter
Particle effect help to do motion effect
Hope this will help someone !