Im trying to rotate a body around its center in box2d. The rotation of the sprite works, but what the body does is rotate around its top left point.
Code for rotating the sprite:
public void drawBitMap(Bitmap bit, float x, float y, float width, float height, float rotation){
Sprite sprt = null;
if (!sprts.containsKey(bit)) {
sprt = new Sprite(bit.texture);
sprts.put(bit, sprt);
}else{
sprt = sprts.get(bit);
}
sprt.setOrigin(width/2,height/2);
sprt.setRotation(rotation);
sprt.setPosition(x,y);
sprt.setSize(width,height);
sprt.draw(this);
}
Code for rotating body:
body.setTransform(x, y, rotation * MathUtils.degreesToRadians);
Images of what is happening:
It probably has something to do with the definition of the origin of the body or fixture. Can you show me the code you used to create the body and fixture?
EDITED
Ok, I've checked your JSON and it's exactly what I thought. In those JSONs the fixture was defined with the center of the body at its bottom left corner.
The point (0,0) is the center of the body, and the fixture you are defining has that point at its bottom left corner, that's why it rotates around its bottom left corner.
This might sound confusing so I'm going to give you a simple example: a square.
A square of size 1 that has this same problem would have its vertices defined at (0,1), (1,1), (1,0) and (0,0).
As stated above, the point(0,0) is the center of the body so, in order to alineate the centers of the fixture and body, the vertices should be defined AROUND the point that is the center of the body(0,0).
The correct square would have the following vertices: (-0.5,0.5), (0.5,0.5), (0.5,-0.5), (-0.5,-0.5).
Related
What I'm trying to do:
Create a compass when given a direction in degrees (0 - 360). Like so:
What I have done:
I have managed to get the SVG image to point in the right direction but I can't seem to get it to rotate around the circle. To attempt a solution around the circle, I have decided to try get the positioning using the ellipse tool and this formula. This is what it looks like at the moment:
(notice how the arrow faces a different direction to the ellipse, in the circle, on the axis - given the center point is the middle of the green circle)
void setDirection(float value, int radius) {
fill(secondaryColour);
float origin_x = (1280 - (width-400)/2);
float origin_y = height/2;
float x = origin_x + radius * cos(radians(value));
float y = origin_y +radius * sin(radians(value));
//grey circle
ellipse(x, y, 20, 20);
//arrow SVG
pushMatrix();
translate(200, 300);
rotate(radians(value));
scale(0.5);
shape(arrow);
popMatrix();
}
Please note: value is in degrees and radius is the radius I want the arrow to sit on. What am I doing wrong with the ellipse? and how can I bring them both together?
I found that the starting angle started on the white line, but I was assuming it would start on the red (similar to the angle of the arrow). To resolve the issue I needed to subtract 90 degrees from the variable value before converting it into radians.
I'm having problems plotting hitboxes in the center of rotating triangle sprites. When I spawn the triangles, I set the collision rectangle like this:
bullet.collisionRect.width = flashingTriangleSprite.getWidth() - 20;
bullet.collisionRect.height = flashingTriangleSprite.getHeight() - 14;
bullet.scale = 0.287f;
Updating is done as follows:
bullet.position.y += bullet.velocity.y;
// center collision rect over triangle sprite
bullet.collisionRect.x =
bullet.position.x + ((flashingTriangleSprite.getWidth() / 2) - bullet.collisionRect.getWidth() / 2);
bullet.collisionRect.y =
bullet.position.y + ((flashingTriangleSprite.getHeight() / 2) - bullet.collisionRect.getHeight() / 2);
if (bullet.scale < 1)
{
bullet.scale += 0.011f;
}
if (bullet.driftDirection == Globals.Direction.LEFT)
{
bullet.rotation -= 3.804f;
bullet.position.x -= bullet.velocity.x;
}
else // drift right
{
bullet.rotation += 3.804f;
bullet.position.x += bullet.velocity.x;
}
This is the result: http://imgur.com/rIvIT8K
As you can see, the hitboxes are not centered. In fact, the hitboxes seem to change position within the triangle sprites depending on the rotation of the triangle sprite. Any ideas what I'm doing wrong?
When determining your hitbox centre position you are targeting the centre of the triangle sprite (a square), but that is not the perfect centre of the drawn triangle.
Therefore your hitbox is always closer to one of the vertices of the triangle (depending on the rotation). Also, your hitboxes are never rotated with the triangle, instead they always appear to be standing vertically.
To place the hitbox in the middle of the triangle you should aim for 1/3 of the height of the sprite (if the triangle has one side flat at the bottom in the base sprite image) and when you are updating the sprite, attempt to update the hitbox rotation to match the sprite rotation.
You could also try making a more accurate triangle hitbox using the PolygonShape, but that's up to you.
I am using androidplot with PanZoom attached:
PanZoom.attach(plot);
Therefore I can zoom in and out as it should.
What I want next is to draw a circle at a given point.
Right now I use the strokewidth to set the dimension of the circle.
But when I zoom in and out, the circle size remains the same, although it should scale according to the zoom level. So imagine I zoom in infinitely, the circle should at a certain amount of zoom level cover the whole screen.
But it does not.
How can I achieve this?
I was thinking aboud increasing the strokewidth of the circle according to the zoomlevel but I was neither able to get the zoomlevel nor to get the domain levels on the left and right side of the plot.
EDIT:
In xml folder I create a file e.g. circle.xml:
<?xml version="1.0" encoding="utf-8"?>
<config
fillPaint.color="#00000000"
linePaint.color="#00000000"
linePaint.strokeWidth="0dp"
pointLabelFormatter.textPaint.color="#FFFFFF"
vertexPaint.color="#371cd1d4"
vertexPaint.strokeWidth="20dp"/>
and in java
sigmaLabelFormatter = new LineAndPointFormatter();
sigmaLabelFormatter.setPointLabelFormatter(new PointLabelFormatter());
sigmaLabelFormatter.configure(activity.getApplicationContext(), R.xml.circle);
sigmaLabelFormatter.setPointLabelFormatter(null);
Zoom only affects the drawing of XYSeries data; if you draw directly on the canvas, it will be drawn exactly where you specify on the canvas regardless of pan/zoom.
One thing you can do though is to make series to represent your circle and draw the circle there. This will make the circle respond to both pan and zoom actions. The tricky part will be picking enough points to ensure that the circle appears smooth at your highest supported zoom level.
I found a solution to my problem, since I finally managed:
to get the domain levels on the left and right side of the plot.
or to be more precise to get the width of the plot.
Since the dimensions of the plot is in meters, I do the calculation as follows:
private float calculateDP(float px){
return px / (densityDpi / densityDefault);
}
private float pixelsPerMeter(float value){
float w = plot.getGraph().getWidgetDimensions().canvasRect.width();
float w2 = plot.getBounds().getWidth().floatValue();
return value * (w / w2);
}
private void init(Activity activity){
densityDpi = activity.getResources().getDisplayMetrics().densityDpi;
densityDefault = android.util.DisplayMetrics.DENSITY_DEFAULT;
}
private void onCreate(){
// ... lots of stuff
labelFormatter.getVertexPaint().setStrokeWidth(calculateDP(pixelsPerMeter(2)));
}
Might it help somebody out there...
Rectangle rEnemy = new Rectangle();
rEnemy.setBounds(0,0,40,40);
Rectangle rPlayer = new Rectangle();
rPlayer.setBounds(200,0,40,40);
my question: how can i make detection/intersection for rPlayer using something like "line" long for 100px?
example: rEnemy is at (0,0), rPlayer is at (100,0) and now rPlayer is intersecting line. there is a method rPlayer.intersect(rEnemy); but i what keep them 100px away from each other and get detection. of course i mean line which is aplicable for others positions of our rectangles because rPlayer and rEnemy are still in move.
I'm not exactly sure what you want, it sounds like you want to check if they are 100px away but intersecting on the x (or y) coordinate, not a 100px radius.
If you're trying to detect if they are within that bounds, you could merely make 1 or 2 rectangles that extend 100px in the x and y coordinates of either the enemy or player and check if the other piece intersects that.
But it would probably be better to just add 100px to the x coordinate of the enemy and check if the player comes within that boundary, that way you aren't drawing more rectangles. I just mentioned that before because I thought it might be easier to visualize.
I just slove this by creating 3rd rect starting from rEnemy cords and making it width and height to rPlayer cords, then:
double calculate = Math.pow(Math.abs(rPlayer.x-rEnemy.x-Camera.posX), 2)+Math.pow(Math.abs(rEnemy.y-rPlayer.y+Camera.posY), 2);
int distance = (int)Math.sqrt(calculate);
variable distance is value of px which separate rPlayer and rEnemy at any position in shortest way.
I use libGDX for a 3D game. In this game an 3D arrow should indicate a certain direction in 3D space. As the player is moving, the direction of the 3D arrow is updated for every frame.
I want to place the arrow in the direction, the camera is looking 3 units before the camera, so that the arrow is always visible. Therefore I added the camera direction to the current camera position and used this as translation part for the arrow. The direction is calculated by substracting the arrow position from the target.
All this works fine, the arrow is displayed at the right position and it moves. The problem is, it sometimes points to the target, and sometimes not.
Here my code:
Vector3 targetPosition = new Vector3(1, 1, 10);
Vector3 cameraPosition = gameController.getCamera().position.cpy();
Vector3 cameraDirection = gameController.getCamera().direction.cpy();
Vector3 up = gameController.getCamera().up.cpy();
Vector3 arrowPosition = cameraDirection.scl(3).add(cameraPosition);
Vector3 arrowDirection = targetPosition.cpy();
arrowDirection = arrowDirection.sub(arrowPosition).nor();
Matrix4 transformationMatrix = new Matrix4();
// calculate orthogonal up vector
up.crs(arrowDirection).crs(arrowDirection);
arrowModel.transform = transformationMatrix.setToLookAt(arrowDirection,
up).trn(arrowPosition);
To avoid that the vectors are calculated wrong, some debug lines were added:
modelBuilder.begin();
MeshPartBuilder partBuilder = modelBuilder.part("lines", GL20.GL_LINES,
Usage.Position,
new Material(ColorAttribute.createDiffuse(Color.GREEN)));
Vector3 linePos = arrowPosition.cpy();
partBuilder.line(linePos.cpy().add(arrowDirection), linePos);
partBuilder.line(linePos.cpy().add(up), linePos);
debugModel = new ModelInstance(modelBuilder.end());
As a result, I see a correct green line for the up vector (current up vector of the camera), and a green line pointing correctly to my target, the green cube. The arrow does something other:
http://www.directupload.net/file/d/3638/2ka7kvvj_jpg.htm
In the picture the arrow is quite near the right direction (green line), there are other situations, where it points in the completely wrong direction.
I used quite a lot combinations of .translate, .trn, .setToLookAt, and .rotate but all of them showed similar, wrong results.
Do you have an idea what went wrong here?