Libgdx: how to draw rectangle around group elements of Scene2D - java

I want to know how to check collision between elements inside a group and other element of the games, in other word, I want to know how to draw a rectangle around elements of the group, cause so far every time I try, the rectangle is always in the wrong position, I tried using stageToLocalCoordinates but the result was always messed up (sometimes I get the rectangle in the correct position but when I move the group the rectangle seems to have a "mirror effect" {move in the opposite direction} )

Use ShapeRenderer..
Make a function in all of your elements of the group that is returning a Rectangle.
public Rectangle getBounds()
{
return new Rectangle(x,y,width,height);
}
Now in the class with your stage, before drawing your elements (actors) draw the rectangle.
shapeRenderer.setProjectionMatrix(stage.getCamera().combined);
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.setColor(Color.BLUE); // put any color you want
// for each actor of your stage do this
shapeRenderer.rect(actor.getBounds().x,actor.getBounds().y,actor.getBounds().width,actor.getBounds().height);
Edit:
To convert a rectangle to a polygon you can use this method made by me some time ago
public static float[] rectangleToVertices(float x, float y, float width,
float height) {
float[] result = new float[8];
result[0] = x;
result[1] = y;
result[2] = x + width;
result[3] = y;
result[4] = x + width;
result[5] = y + height;
result[6] = x;
result[7] = y + height;
return result;
}
And
Polygon poly=new Polygon(rectangleToVertices(.....));
Put your polygon in your gamescreen class.
In the render method set the polygon position..

Related

Dragging rotated text inside android canvas does not work as expected

There is something I am missing inhere so I hope you can share some light on me.
I am drawing some text inside canvas. For this I have a class Word
public class Word {
private int x;
private int y;
private String text;
}
The app allows the user to rotate the text, and I handle the rotation withing onDraw
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY)
...
canvas.drawText(word.getText(), word.getX(), word.getY())
....
canvas.restore();
}
The problem I get is when the user drags the canvas and there is a rotation set. When angle=0 the movement is going as expected.
#Override
public boolean onTouchEvent(MotionEvent event) {
case MotionEvent.ACTION_DOWN:
initialX = (int) event.getX();
initialY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
int xMovement = currentX - initialX;
int yMovement = currentY - initialY;
dragWords(xMovement, yMovement);
.....
and on dragWords for each word I do:
private void dragText(int xMovement, int yMovement){
for (Word word : words) {
word.setX(word.getX() + xMovement);
word.setY(word.getY() + yMovement);
}
invalidate();
}
When rotation angle is 0, moving up/down/left/right makes the words move by the same distance. As angle gets bigger, the words start to move in different dirrections, for instance at 60, it is starting to go diagonally up, when 180 it only moves up/down and not left/right.
I think I need to calculate some sort of a difference based on angle and add it to xMovement/yMovement... but how should I do this ?
LE: Here is an image on how it behaves:
The blue lines is how the text is moving on drag while the orange is the finger dragging on the screen. When angle is 0 it works quite well, when angle increases, it starts to move diagonally on left/right, while when angle is even bigger, it only moves up and down and does not respond to left/right
If I understand correctly, the issue is that Canvas.rotate() does not only rotate the text direction, but rather the whole canvas. Therefore, the x-y coordinates of the words are also rotated from the specified pivot point.
In order to match the dragging movement, you can use a Matrix for this, more specifically the inverse matrix of the one you're using to rotate the canvas. It will be used to convert the x-y coordinates of the words to their original, pre-rotate locations.
For example, calculate this once, and update it whenever angle, centerX, or centerY changes.
// rotMatrix is the same operation applied on the canvas.
Matrix rotMatrix = new Matrix();
rotMatrix.postRotate(mAngle, centerX, centerY);
// Invert it to convert x, y to their transformed positions.
Matrix matrix = new Matrix();
rotMatrix.invert(matrix);
Then, when drawing each word:
int wordX = ...
int wordY = ...
String text = ...
float[] coords = new float[] { wordX, wordY };
matrix.mapPoints(coords);
canvas.drawText(text, coords[0], coords[1], paint);
In the ellipses part in the following code:
dragWords(xMovement, yMovement);
..... <<<--------------------- I hope you are updating initialX and initialY
initialX = currentX;
initialY = currentY;
Otherwise, your x and y values will not correspond correctly with the amount of distance moved during the touch gesture.
As user matiash indicated, you should use Matrix#mapPoints(float[]) to transform your x and y values. Declare and initialize a Matrix:
Matrix correctionMatrix;
// Your view's constructor
public MyView() {
....
correctionMatrix = new Matrix();
}
Here's how your onDraw(Canvas) should look like:
#Override
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY);
...
// Neutralize the rotation
correctionMatrix.setRotate(-angle, centerX, centerY);
// Initialize a float array that holds the original coordinates
float[] src = {word.getX(), word.getY()};
// Load transformed values into `src` array
correctionMatrix.mapPoints(src);
// `src[0]` and `src[1]` hold the transformed `X` and `Y` coordinates
canvas.drawText(word.text, src[0], src[1], somePaint);
....
canvas.restore();
}
This should give you the desired results - movement in the X and Y axis irrespective of canvas rotation.
You can obviously move the call to setRotate(float, float, float) to a better place. You only need to call it once after changing the angle value.

Libgdx - Get Intersection Rectangle from Rectangle.overlap(Rectangle)

Is there any way to know the intersection Rectangle area between two Rectangles in libgdx like the Rectangle in c# http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.rectangle.intersect.aspx ?
I need to get the intersection rectangle area between that two rectangles but the overlap method in libgdx only return boolean value whether two rectangles are intersect or not.
I have read Intersector class but it provides nothing to do that.
Indeed, LibGDX does not have this functionality built in, so I would do something like this:
/** Determines whether the supplied rectangles intersect and, if they do,
* sets the supplied {#code intersection} rectangle to the area of overlap.
*
* #return whether the rectangles intersect
*/
static public boolean intersect(Rectangle rectangle1, Rectangle rectangle2, Rectangle intersection) {
if (rectangle1.overlaps(rectangle2)) {
intersection.x = Math.max(rectangle1.x, rectangle2.x);
intersection.width = Math.min(rectangle1.x + rectangle1.width, rectangle2.x + rectangle2.width) - intersection.x;
intersection.y = Math.max(rectangle1.y, rectangle2.y);
intersection.height = Math.min(rectangle1.y + rectangle1.height, rectangle2.y + rectangle2.height) - intersection.y;
return true;
}
return false;
}
You can use the Intersector class.
import com.badlogic.gdx.math.Intersector;
Intersector.intersectRectangles(rectangle1, rectangle2, intersection);
I'd like to add a slight variation to the answer of nEx Software. This one will work even if you want to store the resulting value in one of the source rectangles:
public static boolean intersect(Rectangle r1, Rectangle r2, Rectangle intersection) {
if (!r1.overlaps(r2)) {
return false;
}
float x = Math.max(r1.x, r2.x);
float y = Math.max(r1.y, r2.y);
float width = Math.min(r1.x + r1.width, r2.x + r2.width) - x;
float height = Math.min(r1.y + r1.height, r2.y + r2.height) - y;
intersection.set(x, y, width, height);
return true;
}
Here is an example usege:
Rectangle r1 = new Rectangle();
Rectangle r2 = new Rectangle();
// ...
intersect(r1, r2, r1);

Drawing rectangles at an angle

What is a method in Java that draws a rectangle given the following:
The coordinates of the center of the square
The angle of the rectangle from vertical, in degrees
To draw a rectangle in the way you suggest you need to use the class AffineTransform. The class can be used to transform a shape in all manner of ways. To perform a rotation use:
int x = 200;
int y = 100;
int width = 50;
int height = 30;
double theta = Math.toRadians(45);
// create rect centred on the point we want to rotate it about
Rectangle2D rect = new Rectangle2D.Double(-width/2., -height/2., width, height);
AffineTransform transform = new AffineTransform();
transform.rotate(theta);
transform.translate(x, y);
// it's been while, you might have to perform the rotation and translate in the
// opposite order
Shape rotatedRect = transform.createTransformedShape(rect);
Graphics2D graphics = ...; // get it from whatever you're drawing to
graphics.draw(rotatedRect);
For the first point, you can just figure out the coordinates of the center of the square by using a distance formula, (int)Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); them divide by 2. you can do this for the width and height. I don't know enough about Java draw to give you better answers based on what was in your question but I hope that helps.
For the second, you would need to just create a polygon right?

Flipping a polygon that contains many polygons to create an upside down mirror of everything

I have created a polygon with 6 vertices. Lets call this one, outside polygon. Inside the outside polygon I created smaller polygons. I want to flip all of it vertically one point at the time.
I know the vertices of the outside polygon and I have an ArrayList<Polygon> for the inner polygons. I was able to flip the outside polygon. but how do I flipped the inner polygons keeping their relative positions in the new one? I know the center of the outside polygon and the flipped version.
correction: I needed to flip horizontal.
I flipped the outer polygon (triangle shape), and I was able to move the inner polygons. but the distance is incorrect. this is a picture of what I have done,
(https://docs.google.com/drawings/d/1cPYJqxTWVu5gSHFQyHxHWSTysNzxJvNuJIwsgCQInfc/edit) https://docs.google.com/drawings/d/1cPYJqxTWVu5gSHFQyHxHWSTysNzxJvNuJIwsgCQInfc/edit
I tried this:
for (Polygon p : polygonList) {
Polygon tempP = new Polygon(p.xpoints, p.ypoints, p.npoints);
firstPointinPolygon = new Point(p.xpoints[0], p.ypoints[0]);
// find frist point in the polygon
float adjacent = (float) firstPointinPolygon.getX() - 400;
float opposite = (float) firstPointinPolygon.getY() - 400;
float hypotenuse = (float) Math.sqrt(opposite * opposite + adjacent * adjacent);
float cosine = adjacent / hypotenuse;
float sine = opposite / hypotenuse;
float endX = 400 * cosine;
float endY = 400 * sine;
float endXDelta =400-endX;
float endYDelta=400-endY;
Polygon pM = move(tempP, endX, endY);
polygonListMirror.add(pM);
tempP = new Polygon();
}
public Polygon move(Polygon p, double xMove, double yMove) {
// Change the values of the points for the Polygon
for (int i = 0; i < p.xpoints.length; i++) {
p.xpoints[i] += xMove;
p.ypoints[i] += yMove;
}
return p;
}
But did not get the result, I expected. What am I doing wrong? The end result should be like the picture in this link:
(https://docs.google.com/drawings/d/1vYdWkCelWW1_NUypNhtmckBYfEMzCf6bMVtoB-AyPkw/edit) https://docs.google.com/drawings/d/1vYdWkCelWW1_NUypNhtmckBYfEMzCf6bMVtoB-AyPkw/edit
I think something like this will do it:
Polygon outerPolygon, oldOuterPolygon;
ArrayList<Polygon> innerPolygons;
// set up objects
for (Polygon polygon: innerPolygons)
{
for (int i = 0; i < polygon.ypoints.length; i++)
{
polygon.ypoints[i] = center(outerPolygon) - polygon.ypoints[i] + center(oldOuterPolygon);
}
}
If you just to flip it vertically where it stands, such that the y-coordinate of top-most and bottom-most points just switch around, center for both should be the same (thus you can just say 2*center).
I'm pretty sure you can replace center(outerPolygon) and center(oldOuterPolygon) with any point from the applicable Polygon, as long as both use the same point.

question about drawing with out java2D

I have another question, this is also extra credit and not homework. This time I need to create a border with out using java2d. The instructions are...
Write a method called drawRectangleBorder having six parameters which does not use the graphics package. It draws a rectangular border starting at the x and y coordinates given as the first two parameters, having a width and height given by the third and fourth parameters, the width of the border given by the fifth parameter in the color given by the sixth parameter. The parameter list is: x, y, width, height, borderWidth, color
I used a previous method I made to create a border around the outside of a picture but the best I can make it do now is a couple scattered boxes. The most recent version will not show anything
public void drawRectangleBorder(
int x, int y, int width, int height, int border, Color newColor) {
int startX = 0;
int startY = 0;
// top and bottom
for (startX = x; x < width; x++) {
for (startY = y; y < border; y++) {
// top pixel
this.getPixel(startX, startY).setColor(newColor);
// bottom pixel
this.getPixel(startX + width, startY + height).setColor(newColor);
} // for-y
} // for-x
// left and right
for (startX = x; x < border; x++) {
for (startY = y; y < height; y++) {
// left pixel
this.getPixel(startX, startY).setColor(newColor);
// right pixel
this.getPixel(startX + width, StartY + height).setColor(newColor);
} // for-y
} // for-x
return;
} // end drawRectangleBorder
Again I thank you for any input.
You can alter the pixels in a java.awt.BufferedImage as shown here.
I might be too sleepy but I think your forgetting to set the pixel back into this (whatever this is ^^)
I'm guessing this.getPixel sends your back a copy so you might want to do something like
Pixel p = this.getPixel( startX, startY );
p.setColor(newColor);
this.setPixel(startX, startY, p);

Categories

Resources