News:

If you need instructions on how to get through the hotels, check out the enclosed instruction book.

Main Menu

Circles, arcs, and element position

Farted by zl, June 17, 2013, 03:28:50 PM

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

zl

In my game, you mouse over a word, and a series of options appear in a circular arc around it.



However, when you mouse over a word near the edge of the screen, some options are cut off or hidden.



What I'd like is for the options to instead be strung along the portion of the arc that's still on-screen, like so:



But dynamically determining that arc has me stumped =\  The initial word could be at any side of the screen, so the arc could be any portion of a circle.

Any ideas?

VCRClock

I am a really inexperienced coder, so maybe my idea is inefficient and not very good. It seems like the most elegant solution to this might involve actually knowing math. :(

Assuming you can already draw arcs and position words along them automatically, I'd detect the visible portion of the arc by:
- Getting the stage coordinates of the center of the circle.
- Getting the diameter of the circle (if it varies).
- Using the circle's center coordinates as one point of a right triangle, the diameter as the hypotenuse, and an angle from the center of the circle, figure out if that point of the arc is still on the screen.

You could check a fixed number of points (such as 30Ëš intervals or something), or you could just start by checking the visibility at 120Ëš intervals, then if you get a point that's not on the screen, check at the midpoint between that and the next visible point recursively until you get a visible point. Then you would check the point between that visible point and the closest non-visible one... How many times to do this, of course, is up to you and depends on what you need out of the arc.

- Get the angle-from-center of the most extreme visible points, and there's the beginning and end of your arc.

Forgive me if this post is sort of garbled and incoherent.
<Marlin Clock> This thread seems proof positive that divisiveness at any level is usually bad for the Clock Crew.
<PhantomCatClock> are we talking about the same clock crew

zl

That strikes me as a workable approach! Thank you!

RomanClock

Quote from: VCRClock;1951348I am a really inexperienced coder, so maybe my idea is inefficient and not very good. It seems like the most elegant solution to this might involve actually knowing math. :(

Assuming you can already draw arcs and position words along them automatically, I'd detect the visible portion of the arc by:
- Getting the stage coordinates of the center of the circle.
- Getting the diameter of the circle (if it varies).
- Using the circle's center coordinates as one point of a right triangle, the diameter as the hypotenuse, and an angle from the center of the circle, figure out if that point of the arc is still on the screen.

You could check a fixed number of points (such as 30Ëš intervals or something), or you could just start by checking the visibility at 120Ëš intervals, then if you get a point that's not on the screen, check at the midpoint between that and the next visible point recursively until you get a visible point. Then you would check the point between that visible point and the closest non-visible one... How many times to do this, of course, is up to you and depends on what you need out of the arc.

- Get the angle-from-center of the most extreme visible points, and there's the beginning and end of your arc.

Forgive me if this post is sort of garbled and incoherent.

Those are the basic steps! Here's some code that could help you out, its not exactly what you want but it might help you if you were stuck. You can copy and paste it into a blank file to see what it does. Click the stage to draw a circle/arch on the stage.

import flash.events.MouseEvent;
import flash.display.Sprite;

stage.addEventListener(MouseEvent.CLICK, clicky);
var angle:int=18;
var size:int=50;
var look:Sprite = new Sprite();
look.graphics.lineStyle(1, 0x000000, 1);
addChild(look);

function clicky(me:MouseEvent)
{
look.x=me.stageX;
look.y=me.stageY;
look.graphics.clear();
look.graphics.lineStyle(1, 0x000000, 1);

var done:Boolean=false;
var cirx:Number;
var ciry:Number;
var wasOff:Boolean=false;
look.graphics.moveTo(size, 0);
//draw while on the stage;
for (var i:int = 0; i<=360/angle; i++)
{
cirx = Math.cos(i*angle*(Math.PI/180))*size;
ciry = Math.sin(i*angle*(Math.PI/180))*size;
if (wasOff)
{
look.graphics.moveTo(cirx, ciry);
}
if (cirx+look.x>0 && cirx+look.x<stage.stageWidth && ciry+look.y>0 && ciry+look.y<stage.stageHeight)
{
look.graphics.lineTo(cirx, ciry);
wasOff=false;
}
else
{
wasOff=true;
}
}
}
lemayo lol :soups:

zl

Quote from: RomanClock;1951394Here's some code that could help you out,

So helpful! Thank you! :D

zl

Well didn't take long for me to take that fine piece of code and turn it into a wreck.

Roman's very nice bit of code traces the on-screen arc.  

All I need to do is get the length of that arc, divide by the number of options, and space out the options by that amount.  This seems to be roughly working.

But I'm having trouble figuring out the starting angle of the arc.  My options come out all properly spaced, but rotated so they're off the correct arc and hidden offscreen.

However, it doesn't look like a consistent error - sometimes it's 90Ã,°, sometimes -90Ã,°, sometimes...I just don't know.

It's complicated further in that I want these options to appear one at a time, correctly spaced for the current number of visible options.  That is, if there are ten options, and 5 have appeared so far, they should be spaced across the entire arc, not half of it.

So, embarrassing as it is, I think I ought to share the code.  

function loadOptions(centerX:Number,centerY:Number,options:Array,delay:Number = .2,cumulative:Boolean = false):void{

var arcSize:Number = 0;
var startAngle:Number = 0;
var angle:int = 18;
var size:int=80;
var look:Sprite = new Sprite();
look.graphics.lineStyle(1, 0x000000, 1);
addChild(look);

look.x=centerX;
look.y=centerY;
look.graphics.clear();
look.graphics.lineStyle(1, 0xFFFFFF, 1);

var done:Boolean=false;
var cirx:Number;
var ciry:Number;
var wasOff:Boolean=false;
look.graphics.moveTo(size, 0);
//draw while on the stage;
for (var i:int = 0; i<=360/angle; i++)
{
cirx = Math.cos(i*angle*(Math.PI/180))*size;
ciry = Math.sin(i*angle*(Math.PI/180))*size;

if (wasOff)
{
look.graphics.moveTo(cirx, ciry);
}
if (cirx+look.x>thoughtLeftBorder && cirx+look.x<thoughtRightBorder && ciry+look.y>thoughtTopBorder && ciry+look.y<thoughtBottomBorder)
{
look.graphics.lineTo(cirx, ciry);
arcSize+=angle;
if(wasOff){
startAngle=i*angle;
}
wasOff=false;
}
else
{
wasOff=true;
}
}
trace(&quot;size: &quot;+arcSize+&quot;, start: &quot;+startAngle);
var wordAngle:int=arcSize/options.length;
var cumuDelay:Number = 0;
var newDelay:Number = 0;
for(var k:Number = 0;k<options.length;k++){
trace(k);
var paramArr:Array = new Array();
paramArr.push(k);
trace(paramArr[0]);
TweenLite.delayedCall(newDelay,addOption,paramArr);
cumulative?newDelay+=delay+cumuDelay:newDelay+=delay;
cumuDelay += delay;
}
function addOption(index:Number)
{
trace(&quot;adding option&quot;+index);
//trace(index[0]);
var wordAngle:Number = startAngle -90+ arcSize/(index+1)*(index) * Math.PI / 180;
options[index].x = -thoughtCon.x + centerX + 35 * Math.cos(wordAngle);
options[index].y = -thoughtCon.y +centerY + 35 * Math.sin(wordAngle);
//options[index].stationary=false;
for(var j=0;j<index+1;j++){
var wordAngle:Number = startAngle + arcSize/(index+1)*(j) * Math.PI / 180;
TweenLite.to(options[j],4,{x:-thoughtCon.x+centerX + size * Math.cos(wordAngle),
y:-thoughtCon.y+centerY + size * Math.sin(wordAngle),
ease:Elastic.easeOut});
}
//TweenLite.delayedCall(.5,setStationary,new Array(options[index]));
}
}


And here's what this makes: http://files.myfrogbag.com/jcjo3z8d45ywx3r/Goblin%20Diplomat.swf

AstronautClock