why does the collision between two rectangles not work? - java

I would like to understand one thing , below I saw that a collision between two rectangles works .
create method:
//nave
spaceShip = new Image(new TextureRegion(new Texture(Gdx.files.internal("rocket.png")),98,154));
spaceShip.setOrigin(spaceShip.getWidth()/2, spaceShip.getHeight()/2);
spaceShip.setBounds(spaceShip.getX(),spaceShip.getY(),spaceShip.getWidth(),spaceShip.getHeight());
spaceShip.setZIndex(3);
//meteora
meteora = new Image(new TextureRegion(new Texture(Gdx.files.internal("planet.png")),128,128));
meteora.setOrigin(meteora.getWidth()/2,meteora.getHeight()/2);
meteora.setPosition(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
meteora.setBounds(meteora.getX(),meteora.getY(),meteora.getWidth(),meteora.getHeight());
meteora.setZIndex(3);
Render method:
rect1 = new Rectangle(spaceShip.getX(),spaceShip.getY(),spaceShip.getWidth(),spaceShip.getHeight());
rect2 = new Rectangle(meteora.getX(),meteora.getY(),meteora.getWidth(),meteora.getHeight());
if(Intersector.overlaps(rect1,rect2)){
System.out.println("collision");
}
Now , my question is :
as I can see collisions with dynamic objects .
Let me explain, there will be different now created in a random time .
So how can I tell if a collision occurs with one of these objects and understand what it is .
Rectangle has no method .setName , I wanted to use this to figure out which object my ship touched .
Can anyone recommend a solution ?
Thank You
EDIT
add Image object
meteora = new Image(new TextureRegion(new Texture(Gdx.files.internal("planet.png")), 128, 128));
meteora.setOrigin(meteora.getWidth() / 2, meteora.getHeight() / 2);
meteora.setPosition(Gdx.graphics.getWidth() / 2, 100);
meteora.setZIndex(3);
Rectangle rect = new Rectangle(meteora.getX(),meteora.getY(),meteora.getWidth(),meteora.getHeight());
rectangles.add(rect);

I am not entirely sure what the question is, but in answer to what I think you are getting at:
Typically you would want to add all the new randomly created rectangles to a collection of rectangles, then you can iterate through this collection to check for collisions:
List<Rectangle> rectangles = new ArrayList<Rectangle>(); // a field in your class
// inside the method to create random rectangles
Rectangle tmp = new Rectangle(1,2,3,4);
rectangles.add(tmp);
// inside the method to check for collisions
for(Rectangle rect : rectangles) {
if(Intersector.overlaps(rect, shipRect) {
System.out.println("collision");
}
}
Note that your rect1 for your ship's bounds should be saved as a field (shipRect in this example) as well so that you can refer back to it at any time

Related

How to set size, position, and color, of one RadialGradient, or set XferMode on GradientDrawable

This is my first question here on Stackoverflow, so go easy on me. I'm trying to draw a radial bloom effect around a point, and found RadialGradient, as well as GradientDrawable. However neither fully gives a solution.
Here is how I'm doing the drawing right now:
//global
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
Paint mainP = new Paint();
Paint whiteP = new Paint();
whiteP.setColor(Color.WHITE);
RadialGradient gradient;
// in a drawing method with a canvas
gradient = new RadialGradient((int) x, (int) y, tempRadius, mainP.getColor(),
0x00000000, Shader.TileMode.CL
mainP.setShader(gradient);
mainP.setXfermode(xferMode);
canvas.drawCircle((int) x, (int) y, tempRadius, mainP);
gradient = new RadialGradient((int) x, (int) y, tempRadius/2, whiteP.getColor(),
0x00000000, Shader.TileMode.CLAMP);
whiteP.setXfermode(xferMode);
whiteP.setShader(gradient);
canvas.drawCircle((int) x, (int) y, tempRadius/2, whiteP);
This will give the expected result:
Screenshot
However the new RadialGradient builds up in memory every frame per dot. Which becomes a problem later obviously. The only public thing in that class is a constructor, so all you can do with RadialGradient is create a new one every time you need a new size, position or color. The reason I want to do it this way is because you assign the gradient to the Paint object your going to draw it with, which allows you to use it's setXferMode().
The other way, using the GradientDrawable, does allow you to just create one instance of itself, so you can change the size, position, and color, but the Paint object it uses to paint itself is private, so you can't set the XferMode on it. Which is necessary so that if you have more than one dot, they don't just paint over one another. It has a colorfilter, but it doesn't look like colorfilter worries about the destination, only a specified color and the source.
Since I am new, i can only post two links, and instead of posting just two pictures, I'll link back to the same question I wrote on reddit which has all the pictures for context. (and no answers yet, which is why I came here, ha ha)
https://www.reddit.com/r/learnandroid/comments/590uce/having_a_shader_issue_using_radialgradient_and/
So, how should this be done, I know I need one class or the other. From what I can tell, RadialGradient would be perfect if I didn't have to create a new one every time I needed a different size, position, or color. GradientDrawable would be equally great since you can just have one instance, but I need to be able to set the XferMode on the paint it uses. Is there another class, or am I missing something between the two of these?
Thanks!!
So, while I did find a solution, it still lead to more issues. The solution I found was partly here. The only thing it was missing was being able to change the color of the preallocated RadialGradient bitmap. So I came up with this:
// Global
int tempRadius;
Paint p = new Paint();
RadialGradient gradient;
Bitmap circleBitmap = Bitmap.createBitmap((int) (tempRadius * 2.0f), (int) (tempRadius * 2.0f),
Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(circleBitmap);
Rect gradBMPRect = new Rect(0,0,200,200);
Rect destRect = new Rect();
int[] hsv = {0,1,1};
PorterDuffColorFilter[] myColors = new PorterDuffColorFilter[360];
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
// Initialize
gradient = new RadialGradient(tempRadius, tempRadius, tempRadius, Color.WHITE, 0x00000000, Shader.TileMode.CLAMP);
circleBitmap = Bitmap.createBitmap((int) (100 * 2.0f), (int) (100 * 2.0f),
Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas(circleBitmap);
for(int i = 0; i < 360; i++){
hsv[0] = i;
myColors[i] = new PorterDuffColorFilter(Color.HSVtoColor(hsv), PorterDuff.Mode.MULTIPLY)
}
// update/draw
p.setDither(true);
p.setShader(gradient);
tempCanvas.drawCircle(100, 100, 100, p);
p.setXfermode(xferMode);
if(p.getColor() != mainP.getColor()) {
p.setColorFilter(myColors[hue]);
p.setColor(mainP.getColor());
destRect.set((int)x-tempRadius,(int)y-tempRadius,(int)x+tempRadius,(int)y+tempRadius);
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);
p.setColorFilter(null);
destRect.set((int)x-(tempRadius/2),(int)y-(tempRadius/2),(int)x+(tempRadius/2),(int)y+(tempRadius/2));
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);
With this the RadialGradient is used to create a greyscaled bitmap, then a pallette of 360 PorterDuffColorFilters is made using HSVtoColor. All 360 have their modes set to multiply. When drawing these the paint used to draw the bitmap is set use the ColorFilter specified by its hue. The colorfilter shades the greyscaled bitmap to whatever color the filter is. And no more memory leaks :)
This took longer to render the bitmap of a RadialGradient vs rendering a circle with a RadialGradient though. With 30 circles it took my Galaxy S5 15-20ms per frame draw, while the bitmaps took around 30-35ms. It could probably get worked out though with a little more work and adjustment.

Java. Collision detection

I write a simple collision detection using rectangles. I've to check overlapping in render method. Could you tell me what's faster the first way:
render()
{
Rectangle playerRectangle = new Rectangle(
playerTransformComponent.x,
playerTransformComponent.y,
playerDimensionsComponent.width,
playerDimensionsComponent.height);
for(Rectangle block : blocksList){
//check collision
}
}
Or the second way:
Rectangle playerRectangle = new Rectangle();
render()
{
playerRectangle.x = playerTransformComponent.x;
playerRectangle.y = playerTransformComponent.y;
playerRectangle.width = playerDimensionsComponent.width;
playerRectangle.height = playerDimensionsComponent.height;
for(Rectangle block : blocksList){
//check collision
}
}
The render() function is a loop, so the first way is obviously wrong - you create an object every frame - it's a loss of everything.
The second way is definitely faster.
I hope it helps!
staticcasty

Java iText Rotate a Link Rectangle

I need to rotate a link rectangle using Java iText.
The original link rectangle appears in red. The rotated link rectangle appears in green.
My code:
PdfReader reader = new PdfReader( "input/blank.pdf" );
PdfStamper stamper = new PdfStamper( reader, new FileOutputStream( "output/blank_stamped.pdf" ) );
Rectangle linkLocation = new Rectangle( 100, 700, 100 + 200, 700 + 25 );
PdfName highlight = PdfAnnotation.HIGHLIGHT_INVERT;
PdfAnnotation linkRed = PdfAnnotation.createLink( stamper.getWriter(), linkLocation, highlight, "red" );
PdfAnnotation linkGreen = PdfAnnotation.createLink( stamper.getWriter(), linkLocation, highlight, "green" );
BaseColor baseColorRed = new BaseColor(255,0,0);
BaseColor baseColorGreen = new BaseColor(0,255,0);
linkRed.setColor(baseColorRed);
linkGreen.setColor(baseColorGreen);
double angleDegrees = 10;
double angleRadians = Math.PI*angleDegrees/180;
stamper.addAnnotation(linkRed, 1);
linkGreen.applyCTM(AffineTransform.getRotateInstance(angleRadians));
stamper.addAnnotation(linkGreen, 1);
stamper.close();
But this code does not rotate the recangle.
Please take a look at the following screen shot:
I have added 5 annotations to a simple Hello World file.
The first two are link annotations. Their position is defined by the rectangles linkLocation1 and linkLocation2:
Rectangle linkLocation1 = new Rectangle(30, 770, 120, 800);
PdfAnnotation link1 = PdfAnnotation.createLink(stamper.getWriter(),
linkLocation1, PdfAnnotation.HIGHLIGHT_INVERT, action);
link1.setColor(BaseColor.RED);
stamper.addAnnotation(link1, 1);
Rectangle linkLocation2 = new Rectangle(30, 670, 60, 760);
PdfAnnotation link2 = PdfAnnotation.createLink(stamper.getWriter(),
linkLocation2, PdfAnnotation.HIGHLIGHT_INVERT, action);
link2.setColor(BaseColor.GREEN);
stamper.addAnnotation(link2, 1);
The green rectangle looks like a rotated version of the red rectangle, but that's not really true: we just defined the "clickable" area that way. I don't understand why you'd want to get this effect by introducing a rotation. Why? Because a rotation always needs a rotating point. Suppose that you would introduce a rotation, what would be your rotation point? The (0, 0) coordinate? That would lead to strange results, wouldn't it?
Introducing a rotation for does make sense for some types of annotations though. In my example, I introduced three stamp annotations:
Rectangle linkLocation3 = new Rectangle(150, 770, 240, 800);
PdfAnnotation stamp1 = PdfAnnotation.createStamp(stamper.getWriter(), linkLocation3, "Landscape", "Confidential");
stamper.addAnnotation(stamp1, 1);
Rectangle linkLocation4 = new Rectangle(150, 670, 240, 760);
PdfAnnotation stamp2 = PdfAnnotation.createStamp(stamper.getWriter(), linkLocation4, "Portrait", "Confidential");
stamp2.setRotate(90);
stamper.addAnnotation(stamp2, 1);
Rectangle linkLocation5 = new Rectangle(250, 670, 340, 760);
PdfAnnotation stamp3 = PdfAnnotation.createStamp(stamper.getWriter(), linkLocation5, "Portrait", "Confidential");
stamp3.setRotate(45);
stamper.addAnnotation(stamp3, 1);
In this case, I introduce a rotation angle using the setRotate() method. This rotates the CONFIDENTIAL stamp inside the rectangle we defined. As you can see, this makes sense because the annotation does have actual content: the rotation has an impact on the way you read the word CONFIDENTIAL. In the case of the clickable area of the link annotation, there is no such content to be rotated.
If this doesn't answer your question, please rephrase your question because I don't think anyone can answer it in its current state.
Update
Please take a look at ISO-32000-1 aka the PDF specification. You'll discover that a rectangle is defined using 4 values: the x and y coordinate of the lower-left corner of the rectangle and the x and y coordinate of the upper-right corner of the rectangle. These are the two starting points of the horizontal and vertical sides. You want a rectangle that has sides that aren't horizontal/vertical. Obviously that isn't possible as you'd need the coordinates of 4 corner points to achieve that (8 values, not 4). You can achieve this using a polygon defined by QuadPoints.
See ITextShape Clickable Polygon or path

BetterCharacterControl not applying RigidBody at the right Position

So Im new to JME3 and I have a few problems understanding the BetterCharacterControl.
When I try to apply a BetterCharacterControl to a box it always "expands" from the upper part of the box instead of the center. (A picture explains that better:)
I cant find any functions to change the location it gets applied at, I already tried to create a subclass in which I changed the RigidBody to the BoxCollisionShape directly but that seems to somehow screw up the isOnGround Method. Also if I want to use slopes later it would be nice to have the capsule shape.
Box box2 = new Box(10, 15, 10);
player = new Geometry("Player", box2);
player.setLocalTranslation(new Vector3f(0, 20, 0));
Material mat = new Material(assetManager,
"Common/MatDefs/Light/Lighting.j3md");
mat.setBoolean("UseMaterialColors", true);
mat.setColor("Ambient", ColorRGBA.Blue);
mat.setColor("Diffuse", ColorRGBA.Blue);
player.setMaterial(mat);
playerC = new BetterCharacterControl(12, 30, 0);
playerC.setJumpForce(new Vector3f(0, 700, 0));
player.addControl(playerC);
rootNode.attachChild(player);
bulletAppState.getPhysicsSpace().add(playerC);
On a different note, it seems like I i have to apply a huge vector for the jump force for it to do anything (I didnt change any gravity values)
Im glad for any help
i had this same problem. The way I resolved it is not usual. I coded a class and did inherit from BetterCharacterControl overwriting getShape() method as follows:
protected CollisionShape getShape() {
//TODO: cleanup size mess..
CapsuleCollisionShape capsuleCollisionShape = new CapsuleCollisionShape(getFinalRadius(), (getFinalHeight() - (2 * getFinalRadius())));
CompoundCollisionShape compoundCollisionShape = new CompoundCollisionShape();
//Vector3f addLocation = new Vector3f(0, (getFinalHeight() / 2.0f), 0); REMOVED LINE
Vector3f addLocation = new Vector3f(0, 0, 0); //NEW LINE
compoundCollisionShape.addChildShape(capsuleCollisionShape, addLocation);
return compoundCollisionShape;
}
This works because the original code is a composite created in such a way so that the child node is offset by the value: (getFinalHeight () / 2.0f). The new line adds not realize this shift, leaving the object in the center position of the box set. However, this way of solving the problem, it can create problems when actually a composite mesh is used in the final object.

Is there a way to add on to the points of a shape/or a way to grab the perimeter points? [duplicate]

i have made a transform and rendered a Polygon object with it(mesh is of type Polygon):
at.setToTranslation(gameObject.position.x, gameObject.position.y);
at.rotate(Math.toRadians(rotation));
at.scale(scale, scale);
g2d.setTransform(at);
g2d.fillPolygon(mesh);
now i want to return the exact mesh i rendered so that i can do collision checks on it. only problem is that if i return mesh it returns the un-transformed mesh. so i tried setting the transform to the Polygon object (mesh) like so:
mesh = (Polygon)at.createTransformedShape(mesh);
but unfortunately at.createTransformedShape() returns a Shape that can only be casted to Path2D.Double. so if anyone knows how to convert Path2D.Double to Polygon or knows another way to set the transformations to the mesh please please help.
If AffineTransform#createTransformedShape doesn't provide the desired result for Polygons (as it seems to be the case), you can split the Polygon into Points, transform each Point and combine into a new Polygon. Try:
//Polygon mesh
//AffineTransform at
int[] x = mesh.xpoints;
int[] y = mesh.ypoints;
int[] rx = new int[x.length];
int[] ry = new int[y.length];
for(int i=0; i<mesh.npoints; i++){
Point2d p = new Point2d.Double(x[i], y[i]);
at.transform(p,p);
rx[i]=p.x;
ry[i]=p.y;
}
mesh = new Polygon(rx, ry, mesh.npoints)

Categories

Resources