How does one draw a Rectangle around an Actor with a given Texture? The Rectangle should scale, move and rotate along with the Actor.
Current implementation:
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(Color.RED);
Vector2 _BL = localToStageCoordinates(new Vector2(getX(), getY()));
Vector2 _BR = localToStageCoordinates(new Vector2(getX() + getWidth(), getY()));
Vector2 _TL = localToStageCoordinates(new Vector2(getX(), getY() + getHeight()));
Vector2 _TR = localToStageCoordinates(new Vector2(getX() + getWidth(), getY() + getHeight()));
float xmin = MyMathUtils.min(_BL.x, _BR.x, _TL.x, _TR.x);
float ymin = MyMathUtils.min(_BL.y, _BR.y, _TL.y, _TR.y);
float xmax = MyMathUtils.max(_BL.x, _BR.x, _TL.x, _TR.x);
float ymax = MyMathUtils.max(_BL.y, _BR.y, _TL.y, _TR.y);
shapeRenderer.rect(xmin, ymin, xmax-xmin, ymax-ymin);
shapeRenderer.setColor(Color.BLUE);
shapeRenderer.circle(_BL.x, _BL.y, 2);
shapeRenderer.circle(_BR.x, _BR.y, 2);
shapeRenderer.circle(_TL.x, _TL.y, 2);
shapeRenderer.circle(_TR.x, _TR.y, 2);
shapeRenderer.end();
The problem is that Rectangle doesn't fit well after moving the Actor. I think it has to do with a bad Coordinate Transformation.
I would like to do something like this:
Matix4 m = actor.computeTransform();
shapeRenderer.setTransformMatrix(m);
but the computeTransform() is available in Group (which is an Actor), but not in Actor itself.
Related
I am struggling to draw this shape on an android canvas. I already used all what one could find in here. but it works on some angles and not on others.
Let's say that this shape can be drawn given a certain angle (in the example = 90°)
We also have the coordinates of the three points of the shape (A,B and C)
Here is the code I currently use :
// (cx,cy) is the point A
// (pos2LegX, pos2LegY) is the point C
// radDirection is the drawn example 90°
float radDirection = (float) (Math.toRadians(this.rad));
float pos2LegX = (float) (cx + radius * Math.sin(radDirection)) ;
float pos2LegY = (float) (cy - radius * Math.cos(radDirection)) ;
// (arcPosX, arcPosY) is the point B
float arcPosX = pos2LegX + (float) ((radius/2) * Math.abs(Math.cos(radDirection))) ;
float arcPosY = pos2LegY - (float) ((radius/2) * Math.abs(Math.sin(radDirection))) ;
// the rect to use with the drawers
final RectF oval = new RectF();
oval.set(pos2LegX , pos2LegY - radius/4, pos2LegX + radius/2, pos2LegY+ radius/4);
// draw the shape
// draw AC
canvas.drawLine(cx,cy,pos2LegX, pos2LegY ,paint);
// draw the arc CB
int startAngle = (int) (180 / Math.PI * Math.atan2(arcPosY - pos2LegY, arcPosX - pos2LegX));
canvas.drawArc(oval,startAngle,180,false,paint);
// draw BA
canvas.drawLine(arcPosX,arcPosY,cx,cy,paint);
This may work for example if radDirection = 180 but if radDirection = 000 it gives this :
But here, the shape should be in opposite direction with arc concave to the center cx, cy.
Any solution would be a big help for me.
Thanks in advance :)
p.setColor(Color.parseColor("#D32F2F"));
RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background, p);
icon = getBitmapFromVectorDrawable(MainActivity.this, R.drawable.ic_clear);
RectF icon_dest = new RectF((float) itemView.getRight() - 2 * width, (float) itemView.getTop() + width, (float) itemView.getRight() - width, (float) itemView.getBot
c.drawBitmap(icon, null, icon_dest, p); //[1]
p.setTextSize(50);
p.setColor(Color.WHITE);
c.drawText("Cancel",*/Insert x and y here*/,p);
So far I have that.
I'm trying to drawText directly under the bitmap I drawed. ([1]). However I'm not sure how to get the coordinates of the bitmap and adjust it so that it's centered below it.
The above image is what I'm trying to achieve. Contents of the app has been censored.
In conclusion, how do I get the coordinates for the text that I'm trying to get?
I'm using onChildDraw method of the ItemTouchHelper for a RecyclerView.
You can use paint.getTextBounds() to get the bounds of the text that you are about to draw on the canvas. Once you get the bounds of the text, you can calculate the position to draw the text based on the icon's position.
Edit:
This aligns the text below the icon at the X position same as the icon:
float textX = icon_dest.left;
float textY = icon_dest.bottom + some_padding;
canvas.drawText("Cancel", textX, textY, textPaint);
This aligns the center of the icon and the center of the text in a same vertical line:
Rect textBounds = new Rect();
textPaint.getTextBounds("Cancel", 0, length, textBounds);
float iconCenterX = icon_dest.left + (icon_dest.width() / 2);
float textHalfWidth = (textBounds.right - textBounds.left) / 2;
float textX = iconCenterX - textHalfWidth;
float textY = icon_dest.bottom + somePadding
canvas.drawText("Cancel", textX, textY, textPaint);
My goal is to have an image face wherever the mouse cursor is, here is my code for obtaining the rotation angle (within my Ship class) :
public void reOrient() {
Point m = MouseInfo.getPointerInfo().getLocation();
// getBoard().getPanel() is the JPanel on which the image will be drawn
Point c = getBoard().getPanel().getLocationOnScreen();
int x = m.x - c.x, y = m.y - c.y;
float angle = (float) (Math.atan2(getY() - y, x - getX()));
setOrientation(angle);
}
Then within my paint method on my JPanel :
AffineTransform reset = new AffineTransform();
reset.rotate(0, 0, 0);
g2d.rotate(ship.getOrientation(), ship.getX() + 26,
ship.getY() + 26);
g2d.drawImage(ship.getImage(), ship.getX(), ship.getY(), this);
g2d.setTransform(reset);
My issue is that when I move my mouse counterclockwise the image rotates clockwise...any ideas?
SpriteBatch batcher = new SpriteBatch();
batcher.draw(TextureRegion region,
float x,
float y,
float originX,
float originY,
float width,
float height,
float scaleX,
float scaleY,
float rotation)
What is the meaning of originX, originY, scaleX, scaleY, rotation? Also can you please give me an example of their use?
Why don't you look into docs ?
As stated in docs, origin is bottom left corner, originX, originY are offsets from this origin.
For example if you want object rotate around his center, you will do this.
originX = width/2;
originY = height/2;
By specifing scaleX, scaleY, you scale the image, if you want to make Sprite 2x larger, you will set both scaleX and scaleY to number 2.
rotation specifies rotation around origin in degrees.
This code snippet draws texture rotated by 90 degrees around its center
SpriteBatch batch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("data/libgdx.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
int textureWidth = texture.getWidth();
int textureHeight = texture.getHeight();
float rotationAngle = 90f;
TextureRegion region = new TextureRegion(texture, 0, 0, textureWidth, textureHeight);
batch.begin();
batch.draw(region, 0, 0, textureWidth / 2f, textureHeight / 2f, textureWidth, textureHeight, 1, 1, rotationAngle, false);
batch.end();
or take a look at tutorial here.
I have a simple game animation made in java. It is of three planets rotating around an axis. Each planet is an instance of the class Planet and they have an update method which, every time it is run, the orbit's rotation angle increases and the position is updated acording to the angle and a few predetermined variables like distance from the "sun". From here, you can determine the position of the planet with simple trigonometry. In this case:
Sin(angle) = op/hyp = y/distance
therefore
Sin(angle)*hyp = op
Cos(angle) = ady/hyp = x/distance
therefore
Cos(angle)*hyp = ady
where the hypothenuse is the distance to the sun and the adyacent and oposite sides are the x and y values respectively. I figured this would work, until I tried it out. It gave me an eliptical rotation. Here is the code that updates the planet's rotation (orbit center is the sun's center position):
position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
What could be wrong?
EDIT:
I realized this problem by placing an object with its center in the position specified by orbit center
Here is the full code of the planet class:
public class Planet
{
protected Image image;
protected Vector2 position;
protected final Vector2 orbitCenter;
protected float rotation;
protected Vector2 imageSize;
protected final float rotationSpeed;
protected final float orbitDistance;
protected float orbitAngle;
protected final float orbitAngleSpeed;
public Planet(Image image, float orbitDistance, float rotationSpeed, Vector2 orbitCenter, float orbitAngleSpeed)
{
this.image = image;
this.position = new Vector2(orbitCenter.x, orbitCenter.y - orbitDistance);
this.orbitCenter = orbitCenter;
this.rotation = 0;
this.imageSize = new Vector2(image.getWidth(null), image.getHeight(null));
this.rotationSpeed = rotationSpeed;
this.orbitDistance = orbitDistance;
this.isMouseOver = false;
this.isPressed = false;
this.orbitAngle = 0;
this.orbitAngleSpeed = orbitAngleSpeed;
}
public void Update()
{
orbitAngle += orbitAngleSpeed;
if(orbitAngle > Math.PI * 2)
orbitAngle %= Math.PI * 2;
position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
}
public void Draw(Graphics2D g)
{
g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
g.drawImage(image, (int)position.x, (int)position.y, null);
g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
}
}
Here is the class that tests the planet class. You can download the jar it needs to work from here: foxtailgames.net/AppletSource.jar. Here is the tester class (you will probably have to import a few things though if you do it in eclipse or netbeans it will give you the imports):
public class PlanetTest extends AppletCore
{
public void resizeScreen() {resize(800, 800);}
Image center;
Planet p;
public void LoadContent()
{
p = new Planet(loadImage("images/GameMenuCircles/Planet1.png"), 100f, 0.02f, new Vector2(400, 400), 0.005f);
center = loadImage("images/GameMenuCircles/Center.png");
}
public void Update(GameTime gameTime)
{
p.Update();
}
public void Draw(Graphics2D g, GameTime gameTime)
{
g.drawImage(center, 400 - center.getWidth(null)/2, 400 - center.getWidth(null)/2, null);
p.Draw(g);
g.setColor(Color.green);
g.drawLine(400, 400, 500, 400);
g.drawLine(400, 400, 400, 500);
g.drawLine(400, 400, 300, 400);
g.drawLine(400, 400, 400, 300);
g.setColor(Color.white);
}
}
Your rotation is set to 0 in the above so i assume you are not rotating the picture at the moment. What i think is happening is the orbit circle you are producing is fine, but the location you are drawing the planet is off.
Below is an image of how Swing would draw the circle, so the overlap you experience is because of this.
You need to adjust the position you draw the circle by how half the width so it sits over the center of the orbit.
EDIT: You've alter some code but what you need to change is the draw method of he planet:
public void Draw(Graphics2D g) {
g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
g.drawImage(image, (int)position.x, (int)position.y, null); //here
g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
}
This line needs to be:
g.drawImage(image, (int)position.x - imageSize.width, (int)position.y - imageSizee.height, null); //here
You might compare your result to this AnimationTest that uses the same parametric equation of a circle. Because the orbital radius is a function of the enclosing panel's dimensions, the orbit is circular only when w equals h. Resize the frame, or set HIGH = WIDE, to see the effect.