I rotated my sprite 90 degrees and I want to do the same with my rectangle to be able to use them for collision, but the rotate() method is not available on rectangles.
This is what I did:
treeSpr=new Sprite(new Texture(Gdx.files.internal("tree.png")));
treeSpr.setPosition(250,700);
treeSpr.rotate(90f);
//Rectangle
treeRect=new Rectangle(treeSpr.getX(),treeSpr.getHeight(),
treeSpr.getWidth(),treeSpr.getHeight());
The other answer is basically correct; however, I had some issues with the positioning of the polygons using that method. Just some clarification:
LibGDX does not support rotated Rectangles when using the Intersector for collision dectection. If you need rotated rectangles, you should use the Polygon for collision detection instead.
Building a Rectangular Polygon:
polygon = new Polygon(new float[]{0,0,bounds.width,0,bounds.width,bounds.height,0,bounds.height});
Don't forget to set the origin of the Polygon if you are going to rotate it:
polygon.setOrigin(bounds.width/2, bounds.height/2);
Now you can rotate the collision polygon:
polygon.setRotation(degrees);
Also, somewhere in your code, you will likely want to update the position of the collision polygon to match your sprite:
polygon.setPosition(x, y);
We can even draw our polygon on screen (for debug purposes):
drawDebug(ShapeRenderer shapeRenderer) {
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.polygon(polygon.getTransformedVertices());
shapeRenderer.end();
}
Collision Detection:
The overlapConvexPolygons() of the Intersector:
boolean collision = Intersector.overlapConvexPolygons(polygon1, polygon2)
As mentioned in the other answer, this method only works if:
using convex polygons, which the rectangle is
performing polygon to polygon checks, e.g.: you cannot mix rectangles and
polygons
Rotation
You could create a Polygon from the rectangle or from the sprite (supplying the vertices in order for the polygon constructor) and use it's rotate(float degrees) method:
treePoly = new Polygon(new float[] {
treeRect.x, treeRect.y,
treeRect.x, treeRect.y + treeRect.height,
treeRect.x + treeRect.width, treeRect.y + treeRect.height,
treeRect.x + treeRect.width, treeRect.y
});
treePoly.rotate(45f);
Collision Detection
Collision checks then could be done via the Intersector class:
Intersector.overlapConvexPolygons(polygon1, polygon2)
Keep in mind though, this method only works if:
you use convex polygons, which the rectangle is
you do polygon to polygon checks, e.g.: you cannot mix rectangles and polygons
I think something like it can help, I can not test now,
//Rectangle
treeRect=new Rectangle(treeSpr.getX(),
treeSpr.getY(),
treeSpr.getHeight(), //now is change width by height
treeSpr.getWidth()); //now is change height by width
Note: may You need to adjust the origin of the rotation for both
you can use a render ShapeRenderer to see if the result is as expected:
add for test in variable class
private ShapeRenderer sRDebugRectangel = new ShapeRenderer();
add for test in update or draw
sRDebugRectangel.begin(ShapeType.Filled);
sRDebugRectangel.identity();
sRDebugRectangel.rect(yourRectangle.getX(),
yourRectangle.getY(),
yourRectangle.getWidth(),
yourRectangle.getHeight());
sRDebugRectangel.end();
can look at my answer to this question to use a shaperrender otherwise known as:
Libgdx, how can I create a rectangle from coordinates?
Related
I have not found answer for this question anywhere, so let's go.
What i expect:
I want to render rocket. Rocket is flying from given start point with evaluated angle. I'm evaluating angle like this:
getVelocity().angle() - 90f
My problem is to calibrate rocket position on top of the rocket. Image below shows how should it work:
In the top picture is how libgdx render not rotated texture region. In the bottom picture is what i expect: I want to move and rotate texture region with given angle to have (x,y) coordinate on the top of rocket.
What i have:
I tired to write method to draw sprite how i expect but i failed. I think it is caused due to fact that i don't understand documentation of this method.
Following manual:
void com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(TextureRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation)
Draws a rectangle with the bottom left corner at x,y and stretching the region to cover the given width and height. The rectangle is offset by originX, originY relative to the origin. Scale specifies the scaling factor by which the rectangle should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the rectangle around originX, originY.
My code:
public static void drawRotatedTex(SpriteBatch pmRenderer, TextureRegion pmTex, float pmPosX, float pmPosY, float pmAngle)
{
pmRenderer.begin();
pmRenderer.draw(
pmTex, pmPosX, pmPosY, -pmTex.getRegionWidth()/2, pmTex.getRegionHeight(), pmTex.getRegionWidth(), pmTex.getRegionHeight(), 1f, 1f, pmAngle);
pmRenderer.end();
}
Results:
It is moment of collision. As we can see coordinates are offset in relation to rocket.
I don't ask about full solution. For me will be sufficient if someone explain me (on drawing or something) like this method works.
EDIT
Moderation suggested that this question is duplicate of:
libgdx: Rotate a texture when drawing it with spritebatch
I read this topic, but it is not my solution. I know how to rotate my sprite by i don't have idea why coordinates of rocket are offset in relation to rocket top.
EDIT
Invocation of my drawRotatedTex from rocket class:
#Override
public void render(Renderer pmRenderer, float pmX, float pmY) {
SpriteBatch lvSpritebatch = pmRenderer.getSpriteBatch();
Sprite lvSprite = null;
if(mIsExploding)
{
if((lvSprite = mExplosion.getTexture()) != null)
{
lvSpritebatch.begin();
lvSpritebatch.draw(lvSprite, pmX + lvSprite.getWidth()/2, pmY - lvSprite.getHeight()/2);
lvSpritebatch.end();
}
}
else
{
lvSprite = mAnimation.getTexture();
RendererTools.drawRotatedTex(lvSpritebatch,lvSprite,pmX,pmY,getVelocity().angle() - 90f);
}
}
It is not very clear what you are asking, if it's only about moving the origin you would not need that much text. Anyway, I will take a shot at it.
If you want to accomplish what you have in your picture you setup your sprite like this:
sprite.setOrigin(s.getWidth()/2, s.getHeight()); //Centers sprite on top of image.
If I now rotate it in the draw method it rotates around the top center.
sprite.rotate(5);
sprite.draw(batch);
Despite being rotated around the center top of itself it remains position remains the same. If I would set the origin far away from the image and rotate it then the image would travel very far but the position remains the same. Still if you would move it's position 10 pixels to the right the image (wherever it may be) will be moved to the right.
Hope this helps.
I'm using rectangles for collision detection and a rectangle is created every 3 seconds, I wan't the rectangle to move upward just like my sprite but .translateY() method can't be used on rectangle.
this is what I did to my sprites stored on ArrayList:
for(Sprite sprite:mySprite){
sprite.translateY(deltaTime*movementSpeed);
}
and this is what I did on rectangles which does not work:
for(Rectangle rect:myRect){
rect.setY(deltaTime*movementSpeed);
}
it is possible that your rectangle is being drawn in posciciĆ³n you tell them, but setY is not the same, which translateY, simple explanation:
if for example deltaTime = 1 aprox. and movementeSpeed = 5.
you always drawing the rectangle in the same position, with minimal variation in delta maybe just not appreciated:
your position is rect.setY(5); all time.
try this
for(Rectangle rect:myRect){
rect.setY(rect.getY() + (deltaTime*movementSpeed));
}
I hope this help.
I am developing a 2d game; I am currently developing a system of movement of the camera on the map, I used the following method: my camera has own coordinates - x,y;
I have ArrayList with all my sprites for map with their coords from 0 to mapSize, every sprite has a Draw function, which looks simply like
g2d.drawImage(texture, getX(), getY(), getX() + getSizeX(), y + getSizeY(), 0, 0, getSizeX(), getSizeY(), null);
I'm always drawing all my sprites, without checking are they visible or not;
Whether there is a load on the computer at this drawing (when drawing textures that very far away from screen size)?
Do I need to check whether the object is visible before rendering?
My main DrawAll function contains():
public void DrawAll(graphics2D g2d){
g2d.translate(-playerCamera.getX(), -playerCamera.getY());
for (int i = 0; i < mapSprites.size(); i++) {
mapSprites.get(i).Draw(g2d);
}
g2d.translate(-playerCamera.getX(), -playerCamera.getY());
drawSomeStrings, etc....
}
This is not very good, because lines that were drawn after second translate may twitch when moving the screen.
Should I give translate up and do the offset coordinates manually in each object\sprite's Draw function?
graphics2D will clip your drawing. So it does not impact too much. If you have a lot of sprites, you should consider using a SpatialIndex to select which Sprite is in the screen. (https://github.com/aled/jsi)
I'm trying to make a game where the player ( the circle ) has to collect some stars. The stars will be at different positions and in order to get the stars the player must draw ramps in order to reach the stars. Picture below.
http://3w-bg.org/game/pic.PNG
The red line is where the user has drawn on the screen.
Ok so i capture the coordinates when the user touches and drags on the screen and then i use this coordinates to create a ChainShape for the line. The problem is that the line is drawn nowhere near the touched area. Picture below.
http://3w-bg.org/game/pic2.PNG
The world and the screen positions are not the same to my understanding. So how can i draw the chainshape line exactly where the user has touched. Tried camera.project/unproject but that didn't help.
Usually when using Box2D you should have some kind of pixel-to-meter ratio defined. This is done in order to keep the coordinates in your physics world smaller to keep numeric stability.
When using a Camera and a constant PIXEL_TO_METER to convert the values, you can convert your coordinates like this:
public static Vector2 screenToPhysics(Camera camera, Vector2 screenPos) {
Vector3 worldPos = camera.unproject(new Vector3(screenPos.x, screenPos.y, 0));
return new Vector2(worldPos.x, worldPos.y).scl(1f / PIXEL_TO_METER);
}
public static Vector2 physicsToScreen(Camera camera, Vector2 physicsPos) {
Vector3 worldPos = new Vector3(physicsPos.x, physicsPos.y, 0).scl(PIXEL_TO_METER);
Vector3 screenPos = camera.project(worldPos);
return new Vector2(screenPos.x, screenPos.y);
}
I already know about rectangle collision detection with rectangles, but this time I have 2 rotated bitmaps.
I mean, I have normal bitmaps + a float variable called "direction" and telling in which direction the bitmap must be rotated at drawing.
But how do I find out if 2 of those objects are bumping into each other? It would be enought, too, if you could say me how collision detection between 2 rotated rectangles works... Or maybe you could post some code...
Thank you if you can help (and thank you if you spent time on reading this or thinking about an answer)
Generally, you will needto use the Separating Axis Theorem to determine whether two rotated rectangles are colliding. But there is a simple way that you can tell whether the rectangles are colliding prior to using the SAT so that you don't have to do unneccesary processing. You can do a bounding circle check, where you prove that the rectangles dont intersect by proving that their bounding circles dont intersect.
The bounding circle of a rectangle shares its center and has a diameter equal to the length of either diagonal of the rectangle. Essentially, if the circles do not intersect, than the rectangles cannot intersect either.
I'm not sure how you are performing your rotations, but if you are using Shape/Area type objects, you can use AffineTransform to perform the rotation and then use intersects() on the Area of each rotated object to check if they collide, this saves you from implementing it yourself. Consider the following example:
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
public class Main {
public static void main(String args[]) {
//Create rectangle
Rectangle rect = new Rectangle(10, 10, 10, 10);
//Create transformation object
AffineTransform af = new AffineTransform();
//Rotate the rectangle by 45 degrees
af.rotate(Math.PI/4, rect.x, rect.y);
Rectangle rect2 = new Rectangle(20, 20, 20, 20);
AffineTransform bf = new AffineTransform();
bf.rotate(Math.PI/4, rect2.x, rect2.y);
//Create Area objects based off of the Rectangle objects
Area areaA = new Area(rect);
//Set the Area object to be the same as the Rectangle object
areaA = areaA.createTransformedArea(af);
Area areaB = new Area(rect2);
areaB = areaB.createTransformedArea(bf);
//Check if the objects collide by using their Area equivalent
if (areaA.intersects(areaB.getBounds())) {
System.out.println("Collision!");
}
}
}
You can obviously, modify this to suite your implementation - I'm hoping this points you in the right direction.