LibGDX implement scrollable HexMap - java

I'm currently trying to implement a scrollable hexmap with LibGDX. The framework has some nice map apis but they seem to be pretty useless for what I want to do :(
An example of the map view that I would want. The pink rectangle
represents the area actually visible on the screen while everything
around will get cropped
This is a basic rundown of what my map needs to be able to do:
The map needs to be an Actor on the screen that can simply be drawn
on a stage and be disposable. (Already have that)
The map needs to be scrollable. Meaning clicks and drags need to be
registered.
The individual map tiles need to be clickable. When a tile is
clicked, I would like to know what tile it was. (Edit: I can currently register clicks on the actor but I would have to manually calculate what tile was actually clicked. Is there a better way for this?)
Then, the map needs to know what tile is being displayed in the top
left or right position to determine how many tiles to request from
the QuadTree and essentially what to draw on screen.
The map data is stored in a quadtree. In the end there is a method I
will have to call with what tiles I want to draw and the Quadtree
will return the tiledata to me.
And last but not least: Tiles that reach outside the map boundries
should be cropped (less priority)
Now. This is what I currently have:
http://pastebin.com/aqjSNPy3 (THe class is 200 lines long, not gonna spam this in here :) )
I can already draw the map actor on screen. It looks ugly as hell but what the heck. Not important now.
I think the most important thing for now would be to register clicks on tiles, figure out how many tiles to display/ request and maybe do something with the camera to make it scrollable?
I'm really kinda out of answers here. Help will be highly appreciated.
Thanks alot!

Okay i am trying to help. I currently work with a normal OrthogonalTiledMapRenderer and i am sure you could get some good points at the Render class. For exmaple how you check if a tile is visible. Just take a look at the repository of libgdx.
At first. The dispose is never called in any way. You can call it yourself if you really dont need your Screen anymore. You dispose your assets in it if you use it.
So how to get a click detection. You can add Listener to every Actor for example like this:
actor.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("down");
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("up");
}
})
You can add more Listener like this. For example the ActorGestureListener() to detact pinches and so on.
Make sure that you use the cam.unprojectright so the touchevents are fired correct.
resource: libgdx/wiki/scene2d#Inputlistener
Your current method hit has an other functionality:
Hit detection
The Actor hit method receives a point and returns the deepest actor at
that point, or null if no actor was hit. Here is the default hit
method:
public Actor hit (float x, float y, boolean touchable) {
if (touchable && getTouchable() != Touchable.enabled) return null;
return x >= 0 && x < width && y >= 0 && y < height ? this : null; }
The coordinates are given in the actor's coordinate system. This
simply returns the actor if the point is inside the actor's bounds.
More sophisticated checks could be used, eg if the actor was round.
The touchable boolean parameter indicates if the actor's touchability
should be respected. This enables hit detection for purposes other
than touch on actors that are not touchable.
When hit is called on the stage, hit is called on the stage's root
group, which in turn calls hit on each child. The first non-null actor
found is returned as the actor deepest in the hierarchy that contains
the given point.
Hit detaction
You do not need to override this. Its for a stage togive a touch to the Actors if i get that right.
So how do get it scrollAble? You need to detect slide events(as shown above). If there is such event you need to move your camera around or you move your stage/tilemap (by the value of the movement maybe even while the slide is detected). Both has the same effect. At a Pinch you could change the zoom of the camera by the pinch value for example. I do move my camera in every render cycle so always centers my Character:
this.gameCam.position.x = this.character.getX()
+ this.character.sprite.getWidth() / 2;
this.gameCam.position.y = this.character.getY()
+ this.character.sprite.getHeight() / 2;
Also take a closer look to this repository! It's a working Hexmap from a game:
Hexmap refares to this game:
Mathematiles and found at Libgdx Post
I hope this helps a bit! Maybe start with an regulare Tilemap System befor you start with hexagon. It seems to be a bit harder. But there are alot of tutorials that explain the theorie and how to start creating such system. Even for libgdx.
Generally i would say you should wait with that project till they give us the Hextile API. They are working on it but it does take some time i am sure.
Regards

Related

How to enable a player to move freely in a 2D JavaFX game?

Context
I am making a top-down game in JavaFX. I have a standard setup with scene, ParallelCamera, a stage set to fullscreen, and I am using the AnimationTimer for gameloop. I render gameobjects directly with the GraphicsContext.drawImage()
The problem
When moving the player (and attached camera) to the sides, enough that they are in a space that was not visible on screen at the start of the game, all text nodes disappear and MouseEvent.getSceneX() stops working correctly (the returned value seems to be snapped to the initial rectangle of the screen).
What I have tried
Read JavaFX documentation and looked at example projects, but they all seem to dodge the feature of having a player that actually moves about. Any help to how this should be handled within the JavaFX world would be appreciated.
Below is a picture of the problem. The red line shows where the right edge of the screen is at the start of the game. It matches up with where the text node is cut off. The text reads "FPS: 120". If I move back to the left, the text displays as it should. The same line coincides with where the MouseEvent.getSceneX() stops working as expected.
Code for camera movement:
public static void moveCamera(double x, double y)
{
// Moves the UI-group by the same amount so it stays in the camera view
camera.relocate(camera.getLayoutX() + x, camera.getLayoutY() + y);
uiElements.relocate(uiElements.getLayoutX() + x, uiElements.getLayoutY() + y);
}
The uiElements is a Group node which is parent to the fpstext, the idea is to move that whole node as much as the camera so all UI stays fixed in the camera view.
Code for drawing objects:
public void update(double deltaTime)
{
// Rendering
if (sprite == null)
{
this.setSprite(img_src);
}
else
{
Main.gc.drawImage(sprite, tf.xPosition(), tf.yPosition(), tf.width(), tf.height());
}
}
This update function is on a "RendererComponent" owned by an "Entity", these are called from a loop in the main gameloop. Objects rendered in this way is not subject to the same clipping as the fpsText.
While making a minimal demo I was able to come up with a way to fix the problem. The MouseEvent.getSceneX() was always returning a point relative to the window view. This still seems strange, since the MouseEvent.getTarget() returns the canvas, which is 4 times larger than the window size. Nevertheless, in calculating the point of a click, instead of doing just getSceneX(), I did (owner.tf().xPosition() + owner.tf().width()/2) - Main.WINDOW_WIDTH/2 + screenX. This returns values as I would expect.

Check if Node(instance of Class) is Clicked

Hey I am working on a small project in the aim to accelerate my learning and have come into a problem , I have an arraylist of class instances each with and x,y location and each have been mapped to fit inside a window , and am wondering how I may go about implementing functionality which would allow user to click on a node( an ellipse on screen at the mapped x,y value from a instance of class) and for my program to somehow have a toggle to display information about this node in another part of the screen , I have looked for code examples and havent found one that I can get working with my senario here is my class
class Ship{
float yPos;
float xPos;
Ship(String line){
String[] parts = line.split(",");
xPos = float(parts[4]);
yPos = float(parts[5]);
}
}
I am taking in data from a csv file and splitting it etc,
I have alot of code so if my example isnt enough I will add specific parts if needed,
Thanks in advance ,
Kind Regards,
Andrew
You have to add logic for detecting whether the mouse is inside the object.
Exactly how you do this depends on how your object is shaped.
If your object is a circle, you can simply use the dist() function to check whether the mouse is inside the circle.
If your object is a rectangle, then you just have to check whether the cursor position is inside that rectangle. Draw out a few examples on a piece of paper to help figure this out.
If your object is in a grid, then you can map the cursor position to a grid position.
If your object is more complicated, like a polygon, then your logic will have to be more complicated. Google is your friend with this one.
In any case, you're going to have to try something, put together an MCVE (note: this should not be your whole sketch, it should be a small example that we can copy and paste to run ourselves) and ask a more specific question. Good luck.

Java Read Raw Mouse Input

I'm looking for a way in Java to read in raw mouse input and not just the event listeners. I'll tell you what I'm doing. Essentially, there is a game where if you move the mouse to the right, I want Java to send key signals of the 'd' key being pushed down, and when the mouse is moved to the left, the 'a' key being held down. But, when you move the mouse, the game quickly corrects the mouse position and sends it right back into the middle of the screen. So, if you use mouse listener, you get one event of the mouse being moved to the right, then another quickly following of the mouse being move back to the left. I want to know if I can get data from the mouse without those corrections in the position. Thanks!
A little code might make the situation clearer, but here's what you can do.
While there are a number of APIs (LWJGL's Mouse interface, as one example) that allow you to directly poll the mouse position, it sounds like overprogramming in your case. First, keep a private field with a reference to that last mouse position. We'll call it x here.
Use a MouseMotionListener, and have it call the same method from mouseMoved and mouseDragged. That method should look something like this.
void controlMethod(MouseEvent event) {
int newX = event.getXOnScreen();
int dx = this.x - newX;
if(dx > 0) **D Key Event**
else if(dx < 0) ***A Key Event**
x = newX;
}
That should do the job for you. The only thing you might want to look out for is the mouse straying off of the MouseMotionListener's area; but there are always ways around things like that, and it seems a bit tangential.
As a final note, if you end up with wild swings in mouse control at the beginning of your game loop, consider setting the class field x to an Optional, and use Optional.ifPresent(...) for the dx logic. This will also protect you from data nullification, such as from a focus loss, and I recommend making it a practice.
Best of luck!

How to change the position of a shape on touch in LibGdx

basically I am making a game using LibGdx that will involve a ball and ground. The objective is to keep the ball in the air as long as possible by touching it.
So far I have only used box2d and not put any sprites over the shapes. But I cant seem to get the touch working correctly.
Here's what I have so far in regards to this feature:
This is setting up a class that extends the Input processor as I only want to use the touchDown method.
Gdx.input.setInputProcessor(new InputController(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button){
if((screenX == ball.getPosition().x) && (screenY == ball.getPosition().y)){
movement.y = speed;
}
return true;
}
});
Ball is a body which is set to the world of the ball shape. Speed is a float variable. I then have
ball.applyForceToCenter(movement, true);
In the render method movement is a vector 2 which is not defined until the touch where it should increase the y position by 500.
Could anyone help as this didn't work :(
Your first issue is that you're testing to see if the point clicked is exactly the position of the ball. This is highly unlikely, and almost certainly not what you want. Instead, you want to test to see if the point clicked hits anywhere in the ball.
Your second issue is that you need to transform your device coordinates to box2d coordinates. The device and box2d use different coordinate systems, so comparing the two doesn't make sense.
To solve the first issue, you can loop through all of the fixtures in the body and use the method fixture.testPoint(x, y) to see if the point hits the fixture. Since your body only has one fixture, you can just use this code for the test:
body.getFixtureList().get(0).testPoint(x, y);
Solving the second issue is a bit trickier. Ideally, your game should be using a camera to handle rendering. If it doesn't, you should get one. With the camera, you can unproject the device coordinates to get camera coordinates like this:
Vector3 mouseCoords = new Vector3(screenX, screenY, 0);
camera.unproject(mouseCoords);
//mouseCoords.x and mouseCoords.y will now be relative to the camera
Then, you have to convert to box2d coordinates:
mouseCoords.scl(WORLD_TO_BOX);
where WORLD_TO_BOX is the scaling from world coordinates to box coordinates, which you should already have setup. You can then use mouseCoords.x and mouseCoords.y in the testPoint method.
EDIT: Code below shows how to loop through all fixtures in a body. This isn't necessary if you only have one fixture, however.
for(Fixture fixture : body.getFixtureList())
{
//Do something to fixture
}

Using JPanel to draw straight lines and get point coordinates

I am at a total loss right now. I haven't worked much with building GUIs in Java, I've been reading all about swing and JPanel, and I think what I am trying to do is possible, I just haven't figured out how.
I'm trying to build a GUI in which you can draw straight lines within a certain drawing area, I would like to be able to get the start/endpoint coordinates in order to perform some math with those points. Any help would be greatly appreciated!
I will leave the code to you so here is the algorithm:
1. Create a JFrame and add a JPanel to it.
2. Add a mouse listener for the JPanel
3. Every time the mouse is pressed, get the x and y of the click. (starting points)
4. When the mouse is dragged , record x and y continuously.
5. When mouse is released, record the x and y. (ending points)
6. You could either use the drawLine() method of Graphics class or use draw() of Graphics2D in this case you will need a Line2D.Double -- the arguments remain the same - start x, start y, end x and end y
here is an image to explain a lil bit better:
Start with Performing Custom Painting and 2D Graphics.
Basically, you going to need a mouse listener to monitor the user interaction with your panel, check out How to write mouse listeners for more infor still.
Depending on your needs, if you need to maintain all the click points of the user, you would need to store them in something like a List, or if you just need to know the start and end points, the you just need a couple of Point objects.
You would be able to use these to paint onto your surface and performing your required calculations.
Remember, in this context, the points are contextual to the container they were generated on. That is 0x0 will be the top left of the container
Updated
You could also take advantage of the Shape API, using a Line2D to represent the two points. This would make it easier to distinguish between distinct lines/points
This is harder than just "draw straight lines with (x1,y1) and (x2, y2)" approach.
You need a Line(your custom) object that is dynamically created and placed on the JPanel which is listening for MouseEvents The canvas area being the JPanel itself. You also need to separate the MODEL from the VIEW so that your custom canvas JPanel will draw itself properly with an override for paintComponent()
The question is slightly vague, so I can't provide any code.
you need to add the mouse listener on JPanel.
then:
public void mouseClicked(MouseEvent me){
if(click==1){
int x1=me.getX();
int y1=me.getY();
click=click+1;
}
else{
int x2=me.getX();
int y2=me.getY();
click=1;
}
}
drawLine(x1,y1,x2,y2)
To draw line with mouse move you can also add mouse motion listener.

Categories

Resources