How to implement rotating rectangle around circle in libGDX Box2D? - libgdx

I want to implement rotating rectangle around cicrle in such way, that circle has no rotation, and rectangle has. All object's are Box2D Body objects. Here is picture, what I want to have:
In my case rectangle touches circle, but I think it doesn't matter.
At first I tried to do it with two Fictures for same Body, but there was a problem with rotation: I couldn't have one ficture with rotation and another without.
I think, it should be somehow connected with joints, but I don't know what exactly Joint I should use. Maybe are there another solutions?

I think DistanceJointDef will do the tricks
you could put the radius if the circle as the distance with a little margin if you want
you also have to reduce the friction of bodies so the rectangle can move smoothly
DistanceJointDef djd = new DistanceJointDef();
djd.bodyA = bodyRactangle;
djd.bodyB = bodyCirlce;
djd.length = radius + margin;
world.createJoint(djd);
bodyRactangle is a dynamic body
bodyCirlce is a static body
try that for a start, hope it is helpful
Good luck !!

Related

Scale, Position & Rotate Parent object to make child object take up entire stage

Using the first photo below, let's say:
The red outline is the stage bounds
The gray box is a Sprite on the stage.
The green box is a child of the gray box and has a rotation set.
both display object are anchored at the top-left corner (0,0).
I'd like to rotate, scale, and position the gray box, so the green box fills the stage bounds (the green box and stage have the same aspect ratio).
I can negate the rotation easily enough
parent.rotation = -child.rotation
But the scale and position are proving tricky (because of the rotation). I could use some assistance with the Math involved to calculate the scale and position.
This is what I had tried but didn't produce the results I expected:
gray.scaleX = stage.stageWidth / green.width;
gray.scaleY = gray.scaleX;
gray.x = -green.x;
gray.y = -green.y;
gray.rotation = -green.rotation;
I'm not terribly experienced with Transformation matrices but assume I will need to go that route.
Here is an .fla sample what I'm working with:
SampleFile
You can use this answer: https://stackoverflow.com/a/15789937/1627055 to get some basics. First, you are in need to rotate around the top left corner of the green rectangle, so you use green.x and green.y as center point coordinates. But in between you also need to scale the gray rectangle so that the green rectangle's dimensions get equal to stage. With uniform scaling you don't have to worry about distortion, because if a gray rectangle is scaled uniformly, then a green rectangle will remain a rectangle. If the green rectangle's aspect ratio will be different than what you want it to be, you'd better scale the green rectangle prior to performing this trick. So, you need to first transpose the matrix to offset the center point, then you need to add rotation and scale, then you need to transpose it away. Try this set of code:
var green:Sprite; // your green rect. The code is executed within gray rect
var gr:Number=green.rotation*Math.PI/180; // radians
var gs:Number=stage.stageWidth/green.width; // get scale ratio
var alreadyTurned:Boolean; // if we have already applied the rotation+scale
function turn():void {
if (alreadyTurned) return;
var mat:flash.geom.Matrix=this.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs*green.x,-gs*green.y);
mat.rotate(-1*gr);
this.transform.matrix=mat;
alreadyTurned=true;
}
Sorry, didn't have time to test, so errors might exist. If yes, try swapping scale, translate and rotate, you pretty much need this set of operations to make it work.
For posterity, here is what I ended up using. I create a sprite/movieClip inside the child (green) box and gave it an instance name of "innerObj" (making it the actually content).
var tmpRectangle:Rectangle = new Rectangle(greenChild.x, greenChild.y, greenChild.innerObj.width * greenChild.scaleX, greenChild.innerObj.height * greenChild.scaleY);
//temporary reset
grayParent.transform.matrix = new Matrix();
var gs:Number=stage.stageHeight/(tmpRectangle.height); // get scale ratio
var mat:Matrix=grayParent.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs * tmpRectangle.x, -gs * tmpRectangle.y);
mat.rotate( -greenChild.rotation * Math.PI / 180);
grayParent.transform.matrix = mat;
If the registration point of the green box is at one of it's corners (let's say top left), and in order to be displayed this way it has a rotation increased, then the solution is very simple: apply this rotation with negative sign to the parent (if it's 56, add -56 to parent's). This way the child will be with rotation 0 and parent -> -56;
But if there is no rotation applied to the green box, there is almost no solution to your problem, because of wrong registration point. There is no true way to actually determine if the box is somehow rotated or not. And this is why - imagine you have rotated the green box at 90 degrees, but changed it's registration point and thus it has no property for rotation. How could the script understand that this is not it's normal position, but it's flipped? Even if you get the bounds, you will see that it's a regular rectangle, but nobody know which side is it's regular positioned one.
So the short answer is - make the registration point properly, and use rotation in order to display it like in the first image. Then add negative rotation to the parent, and its all good :)
Edit:
I'm uploading an image so I can explain my idea better:
 
As you can see, I've created a green object inside the grey one, and the graphics INSIDE are rotated. The green object itself, has rotation of 0, and origin point - top left.
#Vesper - I don't think that the matrix will fix anything in this situation (remember that the green object has rotation of 0).
Otherwise I agree, that the matrix will do a pretty job, but there are many ways to do it :)

As3 sprite rotationX and rotationY

I have a bit problem with rotationX and rotationY.
It's cool if i just do a roationX and rotaionY below
_eventParent.rotationY =_differentX;
_eventParent.rotationX =_differentY;
However once i have assign a mouse move to the _eventParent. The roationX and roationY change perspectively while the mouse is moving. so instead the item remain the same size. it increase and decrease size prospectively. any idea why is it doing this? is there a possibility to stop this behavior?
Thanks
Please find the image below.
Perspective allows part of your shape to look closer to you than other parts. The problem is that perspective has a center, or "vanishing point" and by default, it is fixed. As you move your shape farther away from the vanishing point, the perspective changes, causing your shape to widen or narrow.
You can fix this by updating the vanishing point so that it is always at the same coordinates as your shape. Since the shape will always be at the vanishing point, the perspective shouldn't change.
To do this, create a perspectiveProjection for your shape:
_eventParent.transform.perspectiveProjection = new PerspectiveProjection();
PerspectiveProjection is located in the flash.geom package, so don't forget to import it.
Then whenever you update your shape's position, update it's vanishing point:
_eventParent.transform.perspectiveProjection.projectionCenter =
new Point(_eventParent.x, _eventParent.y);
You might need to offset the vanishing point by a set number of pixels to get the perspective looking the way you want it to.
Correct me if I misunderstood your question. Your question is that if you apply rotation to the movieClip object, then why does the size appear to be changing?
For simplification, Let's not apply rotation on both X and Y axis. Let's take a rectangular movie clip and onMouseMove we do ++myMovieClip.rotationX;
Now, this statement is going to apply rotation on the object about the X-axis and one would get a perspective of the movie clip flipping across X -axis and this flipping will show as change in size of the object.
The same applies to rotating across y-axis.

How do I make my hitTestObject() more precise?

I'm doing some collision detection with a circle and a square and whenever the circle comes in contact with the square it bounces away changing its X coordinate by *-1. However, the Hit Area of the circle is a square, so even when it collides with the white area around the circle , the affect still occurs.
My question is, is there a way to modify the hit area to closer resemble my circle?
Thanks
Bitmap hit testing is pixel based (instead of boundary-based, like Sprite-based hit testing), so it is inherently more precise.
Here are the Adobe docs on it.
Here is a nice tutorial on it.
And here is a nice code snippet on it:
if (firstObjectBitmapData.hitTest(new Point(firstObject.x, firstObject.y), 255, secondObjectBitmapData, new Point(secondObject.x, secondObject.y), 255))
{
trace("hit!");
}

Draw a rectangle using the graphics class, but move the registration point

I have the following code to create a Sprite with a rectangle in it:
container = new Sprite();
container.graphics.beginFill(0x00CCFF, .5);
container.graphics.lineStyle(1, 0x00CCFF);
container.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
container.graphics.endFill()
addChild(container);
The only thing is, I'd like the registration point to be in the middle (not the top left corner). Is there a way to set up the registration point in the middle of the rectangle, but still have the position of the rectangle be correct?
i.e. not moved over so that the top left corner of the rectangle is in the "middle" of where I want the rectangle to be...
The closest you can do is:
container.graphics.drawRect(rect.x-rect.width/2, rect.y-rect.height/2, rect.width, rect.height);
But I think that is what you are saying you don't want to do. Although, there might be a way it can be done with a Matrix.
Edit:
It looks like this other StackOverflow post might have some more answers for you regarding using a transform matrix, and a few other possibilities.

as3: draw circle with a hole in it using only actionscript

Okay so basically I want to draw a circle in as3 that has a 'hole' in it (like a donut). Something like this, but without the outlines:
http://www.steel.ie/DugganSteel/Pictures/Hollow-circle.gif
This doesn't work:
SPRITE.graphics.beginFill(0xFFFFFF);
SPRITE.graphics.drawCircle(0,0,10);
SPRITE.graphics.endFill();
SPRITE.graphics.drawCircle(0,0,5);
I mean this seems like it'd be simple but I can't find any information on it. I should also mention that I'm trying to only draw 3/4 of the circle, like 3/4 of donut. So I was planning on drawing a transparent circle and square over the original circle, I know this seems kinda of weird since you'd expect something transparent to show whats underneath it.
Its actually really simple. See the following code:
var p:Point = new Point(100, 100);
graphics.beginFill(0xFF0000);
graphics.drawCircle(p.x, p.y, 100);
graphics.drawCircle(p.x, p.y, 50);
Intersections cancel each other out until you call endFill
Goodluck!
You can just make the line thickness the desired donut width and avoid using beginFill
set graphics.lineStyle
To make it only go 3/4 of the way around you could use curveTo to draw the 3 quarters.
The above method by Tyler works, however if an easier way to do it is to simply begin drawing the inner circle first. Basically Flash doesn't actually fill in the color until you call endFill() (again as mentioned by Tyler), so you start drawing on the inner circle, then the outer circle then on endFill() Flash fills in the gap.
SPRITE.graphics.beginFill(0xFFFFFF);
SPRITE.graphics.drawCircle(0,0,5);
SPRITE.graphics.drawCircle(0,0,10);
SPRITE.graphics.endFill();
Hope this clears things up for you.
Introduction to Flash drawing API, will help you understand a bit more :
http://www.senocular.com/flash/tutorials/flash10drawingapi/