I'm working on a desktop only project using the libgdx game library, and I'm looking to implement a way for when the user scrolls horizontally to pan the camera. I'd like to avoid using libgdx's scene2d if possible. However, I can't see to find a way to capture horizontal scrolls. Is there anyway to detect a horizontal mouse scroll in Libgdx? I'd like to avoid using libgdx's scene2d if possible. And if there is not, is there a way to do it using plain java, without using awt, swing, or javafx?
Horizontal mouse scrolls? There is no such thing unless you are using a mouse with multiple scroll wheels. Usually the mouse has one scroll wheel.
However, if you mean moving the mouse horizontally, you should be able to capture that using getDeltaX(). Note that it's a raw input, so you will want to divide it by the screen's width in order to make movement the same on any monitor you use. You may also want to include a sensitivity multiplier so that the user may choose how fast panning is.
It's often helpful to allow rotation of the camera using the same input by checking whether a key is held down. Consider this pseudocode:
void updateCamera() {
if (LeftShiftPressed()) {
RotateCamera(getNormalizedX());
} else {
PanCamera(getNormalizedX());
}
}
float getNormalizedX() {
return float(getDeltaX()) / float(getScreenWidth())
}
void PanCamera(float x_movement) {
// pan by x_movement * pan_multiplier
}
void RotateCamera(float x_movement) {
// rotate by x_movement * rotation_multiplier
}
Related
Take a look at this screenshoot:
I want to split my UI to two parts, controls and game draw area, but I don't want the controls to overlap the draw area, I want the 0,0 of the game draw area, start above the controls area.
Is that possible to do with Libgdx?
As you said you want each view to have its own coordinate system thus splitting the screen technique as answered by Julian will do the trick, but it's not all to properly use it.
To make it fully works, you should have 2 separate OrthographicCamera one for game draw view, and another for control view. I suggest also to create 2 Viewport mapping to each camera as well. In my experience, when working in multiple camera situation, always create associate Viewport for it. Better for changes that could introduce in the future (i.e. adapt to any screen resolution), debugging purpose like checking touching, position etc.
So combine splitting technique with camera/viewport management, you will have robust system to work for each area independently.
Code
I provided the following code as it's used and working in my game, but changed variable names to fit your need. It's in Kotlin, but should be relatively easy to see it as Java.
You initialize things first for game area stuff.
// create a camera
gameAreaCamera = OrthographicCamera()
gameAreaCamera.setToOrtho(false, GAME_WIDTH, GAMEVIEW_HEIGHT)
gameAreaCamera.update()
// create a viewport associated with camera
gameAreaViewport = ExtendViewport(GAME_WIDTH, GAMEVIEW_HEIGHT, gameAreaCamera)
Next, for control area stuff.
// create a camera
controlAreaCamera = OrthographicCamera()
controlAreaCamera.setToOrtho(false, GAME_WIDTH, CONTROLVIEW_HEIGHT)
controlAreaCamera.update()
// create a viewport associated with camera
controlAreaViewport = ExtendViewport(GAME_WIDTH, CONTROLVIEW_HEIGHT, controlAreaCamera)
PS: Notice width and height of each view. It's set to occupy area as per your intention.
Now you should have something like this in render() method.
override fun render() {
// clear screen
Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT)
// draw game area
drawGameArea()
// draw control area
drawControlArea()
}
For your drawGameArea() assume that sb is your SpriteBatch that you maintain it in the current class,
private fun drawGameArea() {
// the following twos to let system know we will operate against game area's camera
// set the projection matrix
sb.projectionMatrix = gameAreaCamera.combined
// set gl viewport
Gdx.gl.glViewport(0,0,GAME_WIDTH, GAMEVIEW_HEIGHT)
// draw your stuff here...
sb.begin()
...
sb.end()
}
That would goes in the same way for drawControlArea()
private fun drawControlArea() {
// the following twos to let system know we will operate against control area's camera
// set the projection matrix
sb.projectionMatrix = controlAreaCamera.combined
// set gl viewport
Gdx.gl.glViewport(0,GAMEVIEW_HEIGHT,GAME_WIDTH, CONTROLVIEW_HEIGHT)
// draw your stuff here...
sb.begin()
...
sb.end()
}
Note Gdx.gl.glViewport() we supply it with target rectangle area to draw things on.
Viewports are not directly used, but it's more to tell the system which kind of screen resizing strategy to fit your game's graphic into screen, and for better debugging purpose. You can read more here.
Two frequently used options you will use most is ExtendViewport and FitViewport. If you want the game to be appeared and cover entire area of the screen without affect aspect-ratio with no black-bars (black on left-side or right-side), ExtendViewport is likely to be what you want, or if you want the similar effect but with black-bars thus game screen will be the same for every player (thus provide no advantage over player with wide-screen) then FitViewport is your choice.
Checking Hit On UI
I guess you will need this, so I should include it too.
Whenever you need to check whether such UI element is clicked (or tapped) by user, then you can have the following in its corresponding update() method to check whether touching position is within bound of such object's bounding area or not.
The following code safely and work very well with ExtendViewport, but it also should work the same with other Viewport as the code doesn't require any specific information from ExtendViewport. So it's generic.
fun update(dt: Float, cam: Camera: viewport: Viewport) {
// convert screen coordinate to world coordinate
val location = Vector3(Gdx.input.getX(), Gdx.input.getY(), 0f)
cam.unproject(location, viewport.screenX.toFloat(), viewport.screenY.toFloat(), viewport.screenWidth.toFloat(), viewport.screenHeight.toFloat())
if ((Gdx.input.isTouched() &&
boundingRect.contains(location.x, location.y)) {
// do something here...
}
}
You can use two cameras and position them as shown in your image. I think this post could give you a hint: Split-Screen in LibGDX
I'm developing a game in libGDX, and the levels in my grid contains a grid actor which contains mirrors inside (see my game). The problem is that the grid is too big and I want to be able to see all the stage.
I'm using an OrthographicCamera and an ExtendViewport.
I tried using frustrum (I don't really know what it is): I create four BoundingBox (left, right, top and down) which are placed out of the grid. I set the camera position to the middle of the grid actor and i make a loop zooming the camera until the boxes are in the frustrum, but I don't know if it is the best solution...
I think you want to use a FitViewport, which will make sure you don't 'spill' off the screen.
FYI, the frustum is used to determine depth of your camera- how far it can see. I agree that that won't help you in this situation.
I have created an experiment to evaluate various cursors( Bubble Cursor, Area Cursor). Although I have generated the response time and accuracy for each interaction I was interested in knowing user touch patterns and visualize it in heat maps. I could find several API's for iphone, javascript, etc. Since Java Swing package isn't meant to be for touch screen, I couldn't find a way to generate them. Only way I could thing of is to find the touch point pixels and then use some visual tools to generate heatmaps in x-y plane. Any better solution is much appreciated.
Starting from this example, I added the following code to the mouse handler and dragged the mouse diagonally across the image to get the effect pictured below. For simplicity, I used darker() on each pass, but a transformation in HSB space may also be appealing, for example.
#Override
public void mouseMoved(MouseEvent e) {
…
Color color = new Color(img.getRGB(x, y));
int c = color.darker().getRGB();
img.setRGB(x, y, c);
repaint();
…
}
Alternatively, look at using JFreeChart with an XYBubbleRenderer or an XYShapeRenderer, seen here. Add a ChartMouseListener to highlight the selected bubble, as shown here for a StackedXYBarRenderer.
Also consider the prefuse visualization library. As the mouse moves over each entry in prefuse.demos.Congress, illustrated below, the highlight, tooltip and detail text change.
This is a widely known issue that can even sometimes appear on even high-budget professional titles, that when you set the window type to "borderless" and you have an extended display your mouse can "slide off-screen" if the mouse is not constrained to the limits of the display the game is running on currently.
I was wondering how LibGDX can tackle this.
Is there some direct way to constraint mouse movement?
Or does one need to do continuous iterative calculations on mouse position or something?
Libgdx offers built-in function for trapping mouse cursor inside window. Function you are looking is Gdx.input.setCursorCatched(true).
Taken from the docs:
void setCursorCatched(boolean catched)
Only viable on the desktop. Will confine the mouse cursor location to the window and hide the mouse cursor. X and y coordinates are still reported as if the mouse was not catched.
Parameters:
catched - whether to catch or not to catch the mouse cursor
Or checkout documentation by yourself here.
LibGDX is built on top of LWJGL, so you should be able to use the Mouse.setGrabbed() method.
More info in the API: http://www.lwjgl.org/javadoc/org/lwjgl/input/Mouse.html#setGrabbed(boolean)
And here's a discussion on what changes when you call Mouse.setGrabbed(): http://lwjgl.org/forum/index.php?topic=5150.0
How can i do a fixed sprite that don't move with my camera (for example: a life bar in the left up corner)?
I have already tried to do this in the hard way and i would like to see if there is a simple way to do this.
Is there a simple way to do that or i need to do this in relative to the player position?
And i am sorry for my broken english, I would be very grateful to those who answer me.
thankyou.
Usually for the task of UI you would use an extra scene2d Stage and implement custom subclasses Actor which you add to the Stage and set their fixed position via Actor.setPosition(). There are already several predefined UI elements in the scene2d.ui package. To simulate a healthbar you could either use a ProgressBar, or you implement your own HealthBar extends Actor, which renders a Sprite of your choice.
The stage is stationary by default and has its own Camera. As long as you do not manipulate that camera anyhow, you can just draw the stage with all elements via stage.draw() and it will always remain at the same place (what you would expect from an ingame HUD).