I am trying to draw a dynamic radar, but I can't get the cone shape to draw properly. I can get the two lines to work fine, but I can't get the shading between them to work.
My Goal:
What I am getting:
And this is my code:
paint.setColor(Color.WHITE);
RectF oval = new RectF(0,0,200,200);
canvas.drawArc(oval,(float)globalAzimuth+26, (float)globalAzimuth-26,false,paint);
globalAzimuth is the direction the phone is facing. The radar spins as the phone does. The lines spin fine and synchorinized, but the arc just gets bigger and is obviously terribly off.
Does anyone know how to do this?
It looks like you're treating the parameter sweepAngle as a stop angle. It should be the number of degrees to sweep, clockwise from startAngle.
From the docs:
sweepAngle : Sweep angle (in degrees) measured clockwise
Edit : It looks like you could use a constant 52 as the sweep angle, since you're just going 26 degrees in either direction from globalAzimuth(although your lines appear closer together than 52 degrees, so I'm not sure). If you do, you'll need to keep in mind that it goes clockwise, so your startAngle should be globalAzimuth - 26, rather than plus.
Related
I'm trying to make a small circle move in another bigger circle as a ball moving in circle relative to Android phone tilting. I'm doing this in Godot but I think the principle is the same in all game engines probably. I make a scene in Godot and add two sprites as the two circles as the following picture. I get the accelerometer 3D vector, use x and y values and calculate the angle in x and y plate (relative to y axis i.e Vector2(0, 1) ) and rotate the mentioned scene to that degree using an animation, using this code
func _process(delta: float) -> void:
var vec3 = Input.get_accelerometer()
accelVec = Vector2(-stepify(vec3.x, 0.1), -stepify(vec3.y, 0.1))
var angle = accelVec.angle_to(Vector2(0, 1))
rotateTween.interpolate_property(self, "rotation", rotation, angle, 0.2,
Tween.TRANS_LINEAR)
rotateTween.start()
return
But the problem lies in here that when the x value of accelerometer 3D vector changes from a positive to negative value i.e when the ball is at top of the circle and is going to go to the other half of the circle, it actually moves from bottom of the circle to the desired point rather than from top of the circle.
I hope I explained the problem well, though I doubt it.
I added the Gif that shows actual test on an android phone here Testing in Android.
Any idea how to solve this problem?
Thanks in advance.
This is because Tween is interpolating linear values. It doesn't know it's working with angles, or that they should wrap around.
So when you're at -179 degrees and you tween to 179--a difference of 2 degrees--Tween just sees -179 -> 179 and goes through the whole circle.
You probably don't need a Tween here at all because _process() happens every frame.
I will have an oval in the plane.The x and y co-ordinates of the center of oval and radius of the oval is known.Using a particle to move around the plane,have to verify whether the oval is circled(by moving the particle through all the sides of the oval).
How can I verify whether the oval is circled by the particle?
Consider centre of oval is (0, 0deg) in polar coordinates.
I am assuming your particle doesn't go inside the boundary of oval(from your words side of oval).
Minimize min and max with start position(atan(yParticle-yOvalCentre, xParticle-xOvalCentre)) of particles. Everytime particles goes towards min update min angle and similar for max. Once max - min > 360, you have completed the circle.
When you decided to start painting oval around circle, you created the starting vector from circle center to point (let's call it mouse point).
(mouseX-circleX, mouseY-circleY) = start vector
So, initial angle between current and starting vector will be 0 (until you move your mouse).
Mohit suggested you to check whether your current vector achieved some delta (359 deg is enough) between minimal and maximal angle value (angle can vary between -180 .. 180).
I'm not sure about his formula, though. I think it's better to find angle between starting vector (ax,ay) and current (bx,by) using the fact that
[a,b] = |a|*|b|*sin(alpha) = ax*by - ay*bx
(a,b) = |a|*|b|*cos(alpha) = ax*bx + ay*by
atan( [a,b] / (a,b) ) = atan(tan(alpha)) = alpha
So, calculate current angle on every mouse move and update min/max values, until max-min < 359
If you want to check it simultaneously for several circles, do it simultaneously for array of starting vectors and min/max values)
UPD I've noted big problem here, after painting 180 degrees around circle you'll achive -180 point immediately. So I think the best thing to do is to accumulate some summary value of signed delta angles between current and prevous "MouseMove" callback. So, when summary value will become 359 or -359 that mean you maked valid clock or counter-clockwise rotation.
I am drawing an arc with a border by painting two arcs, one over the other the first being slightly larger.
The issue is with "slightly larger" this can end up with the border not always being even all the way round.
Both the arcs I am drawing have the same radius, I simply make it larger by adding a degree to the start and two degrees to the end (necessary to ensure the borders on either end of the arc are equal) and increasing the stroke width.
In the supplied picture the thicker border edge is the smallest I can possibly make it while it is still visible. (-1 degree off the inner arc)
I have considered drawing the arc outline with four separate calls two straight lines for either end and two arcs. This seems quite inefficient for what I want to achieve.
I am wondering if anyone has any suggestions about how else I could draw a border thats even, minimizing the number of draw/canvas rotation calls if possible.
Relevant code sample for current solution:
Paint mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setStyle(Style.STROKE);
mFillPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mFillPaint.setColor(Color.TRANSPARENT);
mFillPaint.setStrokeWidth(mValueWidth);
mOutlinePaint.setStyle(Style.STROKE);
mOutlinePaint.setStrokeWidth(mBorderWidth);
mOutlinePaint.setColor(Color.WHITE);
mRect.set(mHalfXSubRadius, mHalfYSubRadius, mHalfXAddRadius, mHalfYAddRadius);
canvas.drawArc(mRect, ARC_START-1, MAX_ARC+2, false, mOutlinePaint);
canvas.drawArc(mRect, ARC_START, MAX_ARC, false, mFillPaint);
U shouldnt make your arc bigger, instead try to draw the same sized arc (in white), X pixel right,down,up,left,corners as well (total of 8 drawings).
where X is the border size u want.
after that draw the main arc (in gray) in the middle.
psuedo code:
paint=white;
drawArc(x,y+2);
drawArc(x,y-2);
drawArc(x+2,y+2);
drawArc(x+2,y-2);
drawArc(x-2,y+2);
drawArc(x-2,y+2);
drawArc(x+2,y);
drawArc(x-2,y);
paint=gray;
drawArc(x,y);
i have a rotated arc drawn using android 2d graphics
c.drawArc(new RectF(50, 50, 250, 250), 30, 270, true, paint);
the arc will rotate while the game is running ,
i wanna know how i can detect if any other game objects(rects ,circles) collide with it ??
this is the first time for me to write a game :)
i saw something like this in http://hakim.se/experiments/html5/core/01/
Thanks in advance
Arc collisions are slightly harder then normal collisions, but using boolean algebra you can easily check if a given point is inside your arc.
Take a look at the following picture.
There are 3 objects here. The black sphere, this visualizes your arc, if something collides with it, it might be inside your arc. The red sphere on top of the black sphere, this visualizes the 'inside' of the arc, if something is inside the red sphere, it's definately not 'inside' the arc. Now there is also the green triangle that Visualizes the 'cut-off' of your arc, anything inside the green triangle is also definately not in your arc.
Testing if something is inside the black sphere is easy. (object's distance to center of sphere <= radius of sphere). Same for the red sphere. The green triangle is a bit tricky, you first have to construct this. Find the start and end radians of your arc. and rotate a unit vector by start radians. Then rotate a unit vector by end radians. Lengthen both these vectors by 2 * the radius of the black sphere. Now use the center point of your arc and the positions of two vectors with added the center position as the 3 points of the triangle. You can then use one of the point-triangle collision solvers: http://www.bing.com/search?q=point+triangle+collision&go=&form=QBLH&scope=web
So remember: collision with arc = (collision with black sphere) && !(collision with red sphere) && !(collision with green triangle).
When I call drawCircle (ex. canvas.drawCircle(x, y, r, mPaint);) and I use Paint Style STROKE to initialize the parameter mPaint, the result doesn't quite make a full 360 degrees (2*PI radian) circle in all cases. Sometimes you get a full circle (as I would expect) and sometimes only an arc.
Does someone have an idea what would cause this to happen ?
I don't know what cases work and which don't (yet). I've noticed the ones that don't work seem to be the larger circles I'm drawing (>100.0 radius). Could be size related. I am using floating point for x, y and r. I could try rounding to the nearest int when in the drawing code.
Are you doing anything else to the canvas before the drawCircle? This could happen if, for example you are scaling the canvas or transforming it before you draw the circle.