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
}
Related
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.
In a game I am creating with slick2d to learn Java, I have multiple levels each with one Footballer and multiple other units I want the footballer to be able to interact with. I also want the other units to interact with each other (for example multiple Balls colliding with eachother) (note, some of these units are sometimes of the same class as one another e/g multiple Defenders). I am unsure, however how to detect these interactions and update the units appropriately. For example, I have my Footballer:
public class Footballer extends Unit {
public Footballer(float x, float y){
super("res/ballerpicture", x, y)
}
}
And within this class I have an update function which overrides the update function in the Unit class (allowing me to move the one Footballer according to my input - this is working without issue other than collision detection).
I could then, for example, have loaded on my map 5 balls:
public class Ball extends Unit {
public Ball(float x, float y){
super("res/ballpicture", x, y)
}
}
For an example, I would like to know how to update any one of the balls upon collision with the Footballer, moving them one tile away from the player each time they collide.
My Unit class includes a move method which moves the unit based on an integer direction (left = 1, right = 2 etc...).
Apologies if I have oversaturated this question or haven't included enough information - I'm relatively new to java.
What you are looking for is collision detection.
All objects which are able to interact with each other can have a hitbox, that's in the easiest way one geometrical shape which represents the body of an object. We could for example assume that your ball has a circle as hitbox with the radius of 8 px and your footballer has a hitbox of a rectangle with width 32 px and height 32 px.
When both objects are now moving you have to check whether the boundaries of your hitbox are intersecting with each other, if so: do something, if not keep moving.
In Slick2D all shapes have a method called intersects(Shape s), it returns true if the boundaries of two shapes are intersecting. So basically you just have to implement hitboxes for your objects (make sure to update the hitbox when your object is moving) and then check for intersecting. There are a lot of different ways of implementing collision detection and the internet is providing a lot of ressourcing regarding that topic. I also recommend to take a look at the Shape documentation of Slick2D. It's hard to write a solution for you since I don't know your code but I'm sure you will figure it out and Slick2D provides an easy preimplemented solution for your problem with the intersecting method.
It could look somewhat like the following:
Edit, for multiple balls:
//in your update method
for(Ball ball : allBalls){
if(footballer.getHitbox().intersects(ball.getHitbox()){
//get direction of footballer
ball.move(...)
}
}
im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.
Ok so I have a ArrayList which contains all the tiles that need to be drawn to the screen and I have the player that is moved with the arrow keys, but I am unsure how I could implement collision detection with this, Would it be efficient to check if the current tile is filled and if so stop, This is my first time creating a game from scratch so any help is greatly appreciated!
EDIT:
The tiles are 32x32 images which are held in a ArrayList basically if you guys can help me with the y-axis collision i should be fine with the rest.
Tile class contains x, y, and the tile type
EDIT2:I havent tried anything yet, I don't really know where to start but basically i need some sort of Collision on tile, e.g While player is moving if collide on tile do something but i dont know how to check if i have collided or not
Below I have an example of a bouncing ball, which will test for the end of the JPanel, and do something
//x = X-Axis Location //This tests for a collision of the JPanel on the left side or the right side
public boolean isLeavingSideToSide(JPanel jp)
{
if( x <=0 || x+ width >= jp.getWidth())
{
BounceEvent be = new BounceEvent(this);
notifyListeners(be);
return true;
}
else
return false;
}
BounceEvent is created to allow for the notifyListener, which calls the bounced method.
public void notifyListeners(BounceEvent be)
{
for(BounceListener bl : listeners)
{
bl.bounced(be);
}
}
My Bounced method changes the color of the ball (Does some action)
public void bounced(BounceEvent be) {
Ball b = be.getBall();
Color c = b.getColor();
int x = 256;
int newColor1 = (int) (Math.random() * x);
int newColor2 = (int) (Math.random() * x);
int newColor3 = (int) (Math.random() * x);
b.setColor(new Color(newColor1,newColor2,newColor3));
}
Hopefully this will help you get started.
Collision detection isn't matter for beginners, nor can it be fully explained in a Stackoverflow post; if you're still struggling with arrays, try to make simple games, where collision is detected by calculating the distance between objects like circles.
There are many ways to handle collision detection, but you have to be more specific:
what kind of tile-based game are you planning to develop?
I strongly suggest you to read this article, by Katy Coe, which gives a summary of a few implementations. The following methods are explained in the aforementioned blog.
The simplest and most intuitive method is the Pixel Colour Approach, where players can move on tiles with a specific color value, but it can be used only with a limited color palette. The Mask Approach is essentially the same as PCA, but it hides black and white layers behind custom graphics; the latter is computationally expensive and not generally recommended.
The Grid-Based Approach is probably what you're looking for. Each element of the map corresponds to a tile of the grid (described by a 2D array). The player moves in a discrete space, although animation might fake fluid movements.
The Pixel Tile Method describes collisions by sorrounding characters with n control points; this approach let the developer use non-squared characters in a tiled world.
The Bounding Box Method is a simpler implementation of PTM, where the player is wrapped in a rectangle. The program checks whether any of the four corners of the rectangle intersect with any wall.
Discrete Collision Detection, or its improved version, Speculative Contacts, are used in more complex games and you surely don't need those now.
Don't try to learn all at once, start with the simplest implementation you can think of.
Otherwise, you would soon get discouraged and would not appreciate the pro/cons of each technique.
I've recently found this great tutorial about tile-based games with Macromedia Flash, but you can easily apply those techniques using your language of choice. READ IT!
If you want an alternative to Katy's articles, Rodrigo Monteiro comes in help.
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