I have some sprite objects at different positions on the screen. When I draw a shape around one or several of those objects, I want to know which object that are inside. For this I'm using the Region class and the contains() method. The drawn shape is stored as a path. For now I have only made some code to check for any the objects position, but it's not working? It seems like it's not finding any positions despite that I have a shape around them. What have I done wrong? Or is there a better way?
// Create path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
}
// Draw path
canvas.drawPath(path, paint);
Region region = new Region();
region.setPath(path, region);
// Loop throw all circle objects
for (int i=0; i<5;i++) {
int x = circleManager.getCirclePositionX(i);
int y = circleManager.getCirclePositionY(i);
if(region.contains(x, y))
Log.i("YES!", "");
}
Related
I'm trying to detect a collision between a small rectangle around the cursor and a "Connector", which is basically just a line between two points.
Now, I've decided to use the Intersector.intersectLinePolygon(p1, p2, polygon) method to do so, but when I run the code. It detects a collision everytime any of the rectangle X or Y points are in the same range as the line's bounding box and I can't really get my head around it. The desired result is the collision reporting only when the rectangle is actually touching the line.
Vector3 worldPos = cam.unproject(new Vector3(mouseX, mouseY, 0));
Rectangle rect = new Rectangle(worldPos.x-4, worldPos.y-4, 8, 8);
Boolean connectorIntersected = false;
for (int i = 0; i < nodeConnectorHandler.getAllConnectors().size(); i++) {
//Getting two points that make the connector line
Node n1 = nodeConnectorHandler.getAllConnectors().get(i).getFrom();
Node n2 = nodeConnectorHandler.getAllConnectors().get(i).getTo();
float x1 = n1.getCX();
float y1 = n1.getCY();
float x2 = n2.getCX();
float y2 = n2.getCY();
//Making a polygon out of rect
Polygon p = new Polygon(new float[] {
rect.getX(),
rect.getY(),
(rect.getX()+8f),
rect.getY(),
(rect.getX()+8f),
(rect.getY()+8f),
rect.getX(),
(rect.getY()+8f)
});
//Checking if the line intersects the polygon (representing the rectangle around the cursor)
if (Intersector.intersectLinePolygon(new Vector2(x1,y1), new Vector2(x2,y2), p))
{
selectedIndex = nodeConnectorHandler.getAllConnectors().get(i).getID();
System.out.println("ConnectorIntersected!");
connectorIntersected = true;
}
break
}
The code reports a collision everytime the rectangle is in these areas (shown in yellow, aprox):
photoshopped image link
The red line inbetween those 2 dots is the "connector"
Cursor is right below the line. It reports a collision in those yellow areas spanning across the whole game world.
I suppose I'm either not using the function properly or that I've made some obvious mistake. Or is this how the function should react? I really don't know. Thanks for any help :)
Ok, apparently I used the wrong method. intersectSegmentPolygon works as expected. My bad ¯_(ツ)_/¯.
I started learning LibGdx and Java recently, and it has been going well so far.
I'm facing an issue with collision detection.
I have two sprites which can be represented as two shapes, a polygon and a circle, which will collide/intersect at any given moment. Once these two shapes collide, something will get triggered.
So far, this is what I have done. It kinda works but it is not accurate. This is called inside the Render() function:
public boolean CollectPowerUp(PowerUps powerUp) {
if (powerUp.position.dst(position) < Constants.PLAYER_HEIGHT -3) {
Gdx.app.log("Collected PowerUp", "TRUE");
EnablePowerUp(powerUp);
return true;
}
return false;
I have searched many websites, and most of the solutions include other softwares like 2DCube or PhysicsEditor. Is it possible to perform this intersection solely by using LibGdx and Java? If so, what should I look into?
Thanks
Intersector class having many static method that can be used for collision detection.
If your polygon is rectangle you can use :
Intersector.overlaps(Circle c, Rectangle r)
else
Polygon polygon=new Polygon();
polygon.setVertices(new float[]{0,0,.......});
Circle circle=new Circle(x, y, radius);
float points[]=polygon.getTransformedVertices();
for (int i=0;i<points.length;i+=2){
if(circle.contains(points[i],points[i+1])){
System.out.println("Collide");
}
}
EDIT
Above code only detect collision if polygon vertices are inside circle, what if
circle is completely inside polygon
some part of circle is inside polygon but vertices are outside the circle
Create a polygon for circle that act as circle in view and polygon in model
float radius=100;
FloatArray floatArray=new FloatArray();
int accuracy=24; // can be use 1 for complete circle
for (int angle=0;angle<360;angle += accuracy){
floatArray.add(radius * MathUtils.cosDeg(angle));
floatArray.add(radius * MathUtils.sinDeg(angle));
}
Polygon circle=new Polygon(floatArray.toArray()); // This is polygon whose vertices are on circumference of circle
float[] circularPoint=circle.getTransformedVertices();
for (int i=0;i<circularPoint.length;i+=2){
if(polygon.contains(circularPoint[i],circularPoint[i+1])){
System.out.println("Collide With circumference");
break;
}
}
There's a nice article on collision detection on www.gamedevelopment.blog which shows how to detect collisions with most shapes. This is the Libgdx circle, polygon collision detection method shown in the article.
public boolean contains (Polygon poly, Circle circ) {
final float[] vertices = poly.getTransformedVertices(); // get all points for this polygon (x and y)
final int numFloats = vertices.length; // get the amount of points(x and y)
// loop through each point's x and y values
for (int i = 0; i < numFloats; i += 2) {
// get the first and second point(x and y of first vertice)
Vector2 start = new Vector2(vertices[i],vertices[i + 1]);
// get 3rd and 4th point (x and y of second vertice) (uses modulo so last point can use first point as end)
Vector2 end = new Vector2(vertices[(i + 2) % numFloats], vertices[(i + 3) % numFloats]);
// get the center of the circle
Vector2 center = new Vector2(circ.x, circ.y);
// get the square radius
float squareRadius = circ.radius * circ.radius;
// use square radius to check if the given line segment intersects the given circle.
return Intersector.intersectSegmentCircle (start, end, center, squareRadius);
}
}
There are many useful methods in the Intersector class which can be used for collision detection.
I'm trying to click on a tile and change its color. So far I have this:
if(Gdx.input.isTouched()){
Vector3 click = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(click);
Cell clicked = path.getCell((int)click.x, (int)click.y);
clicked.getTile();
}
Once clicked has its tile coordinates (assuming I did this correctly) I now want to draw a blue square on that tile. How would I do this? I have testTile.png in my assets folder if that helps. I have drawn other pictures to the screen using batch.draw();. If anymore information is needed please feel free to ask.
path is the TiledMapTileLayer.
The way I will approach this problem is having a list of custom class storing the locations where the blue square needs to be drawn and the sprite which needs to be drawn. (Storing sprite in list will give you more flexibility)
So basically in your render method you will draw these tiles in by looping the List.
Example code : (Could not think of a better name than SpriteMap)
public class SpriteMap {
int posX;
int posY;
Sprite sprite;
public SpriteMap(int posX, int posY, Sprite sprite) {
this.posX = posX;
this.posY = posY;
this.sprite = sprite;
}
//ignoring getters
}
Let's say you have a list of SpriteMap in your class where you are going to render and also have access to the list in isTouched() method.
List<SpriteMap> spriteMapList = new ArrayList<SpriteMap>();
Now inside your isTouched
if(Gdx.input.isTouched()){
Vector3 click = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(click);
spriteMapList.add(new SpriteMap((int)click.x, (int)click.y, new Sprite(THE_BLUE_BOX_TEXTURE));
}
Now in your render method all you have to do is loop the list and draw each and every sprite from list from SpriteMap objects.
//Pseudo code inside render after batch.begin();
for(SpriteMap spriteMap : spriteMapList) {
spriteMap.sprite().setPosition(spriteMap.posX, spriteMap.posY);
spriteMap.draw(batch);
}
NOTE Re-use the blue box texture. Also make sure you draw blue box after you have drawn the map else it will get hidden behind the map.
ANOTHER NOTE The positions x and y from clicked may need to be adjusted for the sprite to be drawn on the exact tile. So do change that accordingly. I have directly used X and Y from click but you may have to change them.
Hope that helps.
i have been testing to create a function which would do something, if two objects touch(if one contains or it is just touching the another one). I found this:
public boolean inBounds(float cx, float cy, int size)
{
Rectangle rec1 = new Rectangle(x, y, this.size, this.size);
Rectangle rec2 = new Rectangle(cx, cy, size, size);
if(rec1.contains(rec2)) return true;
return false;
}
}
So, this is a touch function in my Entity class. So, in my update function which i am calling in render function, i have:
if (e instanceof Worm && player1.inBounds(e.x, e.y, e.size))
{
entities.remove(i); //remove object from the scene
i--;
player1.incScore(); //increase score
}
This works perfectly, but only if my charracter is biger than that object, i need it everytime, no only if charracter is biger than object. So what to do now? i Found a function that i can use like if (rec1.overlaps(rec2)) return true; but now, it works, yes.. but the texture of my object is not so ultimate(this is the object: http://img24.cz/images/08705660216361901876.png ), so it looks bad. if the object is near the player, it activates my function, i want to have it only if the object is in the player, so i can create better texture, which is really hard for me, or i can ... I dont know what i can to do, so, help me please. :D
Ok.
First.
Use temporary rectangles, don't create new one every frame!
You are checking rectangle.contains(otherRectangle); which tells you if otherRectangle is inside the rectangle.
You want to check if the rectangle overlaps the other one.
private Rectangle tmpRect1=new Rectangle();
private Rectangle tmpRect2=new Rectangle();
And in your method
public boolean inBounds(float cx, float cy, int size)
{
tmpRect1.set(x, y, this.size, this.size);
tmpRect2.set(cx, cy, size, size);
return tmpRect1.overlaps(tmpRect2); // returns true if rectangles are overlapping, and false if not
}
Yes, but it doesnt fix my problem. my problem was that, that if i am using the overlaps function, it looks unreal. Because(look at http://img24.cz/images/08705660216361901876.png ), you can see that the top of the image is clean, there is not my fish, my fish is only in the middle of image, so it looks bad, if the player is under or over the fish, it gives me a score(because it is overlapping(because of that non-ultimate image)). The contain function was better, because it looked reallistic. So i wanted a help, how do i can make it better.
I am making an explosion. The explosion is supposed to hit all the enemys within it's rectangle (x, y, x + w, y + h). Both the explosion and the enemies inherits from a Sprite class that has a getBounds() method that returns their rectangle. When I create the explosion item I in the constructor loops trough the enemies to check if the rectangles intersects with rectangle.intersects(rectangle2). But seemingly when there are multiple targets that are SUPPOSED to be intersected sometimes the check ignores some of them...
Here's som code:
In the constructor of the class Explosion, inherits class Sprite
List<Zombie> zombies = mGamePlay.getZombieHandeler().getZombies();
Rect r = getBounds();
for(int i = 0; i < zombies.size(); i++)
{
Rect zR = zombies.get(i).getAnimation().getBounds();
if(!zombies.get(i).isDead() && r.intersect(zR))
zombies.get(i).doDamage(new int[]{damage, 0, 0});
}
Inside class Sprite:
public Rect getBounds()
{
return new Rect(mPosX, mPosY, mPosX + mWidth, mPosY + mHeight);
}
Rect.intersect() will modify the source rectangle and set it to the intersection of the two rectangles if they intersect. This is mentioned in the javadoc. This means that after the first successful intersection test, subsequent intersection tests will likely fail (they will pass only for zombies that intersect each other with the original intersection rectangle.)
Instead you should use the Rect.intersects() (with an 's' at the end.)