A Flash Developer Resource Site

# Thread: help with rotations for clocks and angles

1. ## help with rotations for clocks and angles

Happy New Year everyone,
I'm trying bits of code to come to terms with AS3 within KM7. Eventually this will be used for students to move the arms of a clock to the correct time. Later in another project I want to move one arm to a specific angle for maths.
The problem is the mc rotates from the middle not the end and it needs to also go backwards.
Any help appreciated.

var mouseposx:int;
var mouseposy:int;
var dragablehour = false;

function mouseClickHandler(evt:MouseEvent):void{ //test to see if it can be moved
if(dragablemin == false){
dragablemin = true;
} else if(dragablemin == true){
dragablemin = false;
}

trace(dragablemin);
}

function mouseMoveHandler(evt:MouseEvent):void{ // this shows rotation forward but from centre of mc not the end
if(dragablemin == true){
minutehand.rotation += 3; // mouse moves minute hand forward (+= 3) but "swaps' when passing over hour hand. How can this be stopped and
} // (-= 3 moves it backwards so how can we have both - when student makes mistake)

}

function hourClickHandler(evt:MouseEvent):void{
if(dragablehour == false){
dragablehour = true;
} else if(dragablehour == true){
dragablehour = false;
}

trace(dragablehour);
}

function hourMoveHandler(evt:MouseEvent):void{ // rotates from the centre not the end
if(dragablehour == true){
hourhand.rotation += 3; // same as before you want the student to be able to go backwards if they made a mistake (-= 3)
}

}  Reply With Quote

2. Move the clock hands inside their Movie Clips so the the end is at the center point, Also draw the hands straight UP so that coincides with zero roatation, then as you rotate the angles will be 90 for 3 and 360 for 12, you will have to reset the angle when passing 360 as it will continue to count (i.e. rotation of 360+45 for 3 oclock)  Reply With Quote

3. ## Thanks

Thanks for the reply Bret, I'll have a go. Any thoughts about the option of going forwards or backwards?
Updated the fun.
ja  Reply With Quote

4. I would consider using a different approach.

When you click on an object set a variable to indicate a "selected" status or make a set of radio buttons to select which hand to use.

Then track the mouse movement and if moving left go rotation- moving right rotation+  Reply With Quote

5. Originally Posted by blanius I would consider using a different approach.

When you click on an object set a variable to indicate a "selected" status or make a set of radio buttons to select which hand to use.

Then track the mouse movement and if moving left go rotation- moving right rotation+
Hi Bret,
Can you explain that to me? I've made a simpler clock using

minutehand.addEventListener(MouseEvent.CLICK, onClick); // tried putting this in a button to move forward but like student clicking on hand.

function onClick(event:MouseEvent):void
{minutehand.rotation += 30; }

but can't have a function that moves it back ( think this is what you mean).
Also would have that this is a great place for the KM slider but can't assign the values here.
Have included the fun if you have the time to look at it.
thanks
ja  Reply With Quote

6. Wouldn't it be easier and more logical to let the user move the arms to set the time like you do with a normal clock ?  Reply With Quote

7. Originally Posted by w.brants Wouldn't it be easier and more logical to let the user move the arms to set the time like you do with a normal clock ?
I think that's what he was trying to do in the first place.  Reply With Quote

8. Thanks for the reply. The .fun shows both hands move forward now - had the same function for both hands before. Can't have it moving backwards or check to see if the student entered the time correctly, though.
Really would like to understand the slider as well.
ja  Reply With Quote

9. This is how I would approach it ( http://www.waterlijn.info/km/as3/Clock.html ) but is of course more fun to figure things out yourself.

There is some information on the slider in the KM docs but I don't know if that would be enough. Look at the docs for ScrollBar class.

If you want one click handler to move both forward and backward, you might want to know that when you handle a click event, you can check if the shift or ctrl key was also pressed. That way you can assign different behaviours to a normal click and a click + shift or a click + ctrl .  Reply With Quote

10. [QUOTE=w.brants;4226228]This is how I would approach it ( http://www.waterlijn.info/km/as3/Clock.html ) but is of course more fun to figure things out yourself.
QUOTE]

Fun is not the word I'd use, right now! Your example is great.
How did you link both arms together like a real clock and later test for the right answer? I see you've also got the arms going forward and backwards.
This is what I used originally before going to the simpler code.

var mouseposx:int;
var mouseposy:int;
var dragablemin = false;
var dragablehour = false;
var minutehand = 0;
var hourhand = 0;

function mouseClickHandler(evt:MouseEvent):void{ //test to see if it can be moved
if(dragablemin == false){
dragablemin = true;
} else if(dragablemin == true){
dragablemin = false;
}

trace(dragablemin);
}

function mouseMoveHandler(evt:MouseEvent):void{
if(dragablemin == true){
minutehand.rotation += 1; // mouse moves minute hand forward (+= 3) but "swaps' when passing over hour hand. How can this be stopped and
} // (-= 3 moves it backwards so how can we have both - when student makes mistake)
{hourhand.rotation +=3;} // moves hour hand
}  Reply With Quote

11. I used a script only solution also for drawing things.
Create a movie 600 x 400 pixels and attach this code to frame 1.
Code:
```// center of screen coordinates

var cx:int = 300;
var cy:int = 200;

// draw base of clock

var sBase:Shape = new Shape();
sBase.x = cx;
sBase.y = cy;

sBase.graphics.lineStyle(2, 0x808080);
sBase.graphics.beginFill(0xd8d8d8);
sBase.graphics.drawCircle(0, 0, 160);
sBase.graphics.beginFill(0x606060);
sBase.graphics.drawCircle(0, 0, 20);

for (var i:int = 0; i < 360; i += 6){
sBase.graphics.drawCircle(Math.cos(Math.PI * i / 180) * 150, Math.sin(Math.PI * i / 180) * 150,i % 30 ? 1 : 3);
}

// create the arms

var sHour:Sprite = new Sprite();
sHour.mouseEnabled = false;
sHour.x = cx;
sHour.y = cy;

var sMinutes:Sprite = new Sprite();
sMinutes.mouseEnabled = false;
sMinutes.x = cx;
sMinutes.y = cy;

var sDot:Sprite = new Sprite();
sDot.buttonMode = true;
sDot.x = cx;
sDot.y = cy;

// create filters

var glow:GlowFilter = new GlowFilter(0x80ff80, 0.7, 8, 8);

// draw the hour arm

sHour.graphics.lineStyle(4, 0x808080);
sHour.graphics.beginFill(0x606060);
sHour.graphics.moveTo(-4, 0);
sHour.graphics.lineTo(4, 0);
sHour.graphics.lineTo(0, -95);

// add a handle for dragging

var shHandle:Sprite = new Sprite();
shHandle.buttonMode = true;
shHandle.filters = [glow];
shHandle.graphics.beginFill(0x609060);
shHandle.graphics.drawCircle(0, -95, 8);

// draw the minutes arm

sMinutes.graphics.lineStyle(4, 0x808080);
sMinutes.graphics.beginFill(0x606060);
sMinutes.graphics.moveTo(-4, 0);
sMinutes.graphics.lineTo(4, 0);
sMinutes.graphics.lineTo(0, -130);

// draw the center dot

sDot.graphics.lineStyle(1, 0x808080);
sDot.graphics.beginFill(0x606060);
sDot.graphics.drawCircle(0, 0, 12);

// add a handle for dragging

var smHandle:Sprite = new Sprite();
smHandle.buttonMode = true;
smHandle.filters = [glow];
smHandle.graphics.beginFill(0x609060);
smHandle.graphics.drawCircle(0, -130, 8);

// textfield for info

var tInfo:TextField = new TextField();
tInfo.x = 10;
tInfo.y = 10;
tInfo.width = 160
tInfo.height = 80;
tInfo.defaultTextFormat = new TextFormat('_sans', 16, 0x606060, true);
tInfo.selectable = false;

// main code

var h, m:Number;
var hTarget, mTarget:Number;

var moving:*;
function mouseDown(e:MouseEvent):void { moving = e.currentTarget; }
function mouseUp(e:MouseEvent):void { moving = null; }
function mouseMove(e:MouseEvent):void {
if (moving){
var dx:Number = e.stageX - cx;
var dy:Number = e.stageY - cy;
if (Math.sqrt(dx * dx + dy * dy) > 30){
var a:Number = (450 + Math.atan2(dy, dx) * 180 / Math.PI) % 360;
if (moving == smHandle){
h = ((360 + sHour.rotation) % 360) / 30;
m = Math.round(a / 6);
if (m > 59) m = 0;
if (m == 0){
h = Math.round(h);
} else if (m > 30){
h = Math.ceil(h);
h -= (60 - m) / 60;
} else {
h = Math.floor(h);
h += m / 60;
}
sHour.rotation = h * 30;
sMinutes.rotation = m * 6;
} else {
h = a / 30;
m = Math.round(60 * (h % 1));
sHour.rotation = h * 30;
sMinutes.rotation = m * 6;
}
h = Math.floor(h);
if (h == 0) h = 12;
checkTime();
}
}
}

function checkTime():void {
tInfo.text = 'Target = ' + hTarget + ':' + String(100 + mTarget).substr(-2) + '\n\n';
tInfo.appendText('Time =  ' + h + ':' + String(100 + m).substr(-2));
if (h == hTarget && m == mTarget){
} else {
}
}

function resetTime(e:MouseEvent = null):void {
sHour.rotation = 0;
sMinutes.rotation = 0;
h = 12;
m = 0;
hTarget = 1 + Math.floor(Math.random() * 12);
mTarget = Math.floor(Math.random() * 60);
checkTime();
}

resetTime();```  Reply With Quote

12. wow, light years beyond me. The only way for me to learn is take simple code and try to use it. Is there any way my .fun can used to achieve a simpler version? I'm still not sure how to trigger the next question once the student has got the right time.
Thanks for the advice but way above me!
ja  Reply With Quote

13. Code written by someone else almost always looks more complicated.
I'll explain what I did.

When the user clicks one of the dots on the arms of the clock, that arm is set as moving for as long as the user keeps pressing. When the mouse is moved while one of the arms is indicated as moving, the mouse coordinate is compared with the coordinates of the center of the clock and the arm is set according to the angle those two coordinates make.  Reply With Quote

14. Thanks for the explanation. I'll sift through this - still too much for me! Once the point (time on clock face) was correct, (when the hands glow)how could you add a score (up to 5) and a question counter each time you reset (allow 5 resets before a score is given?)
As I've said before KM is frustrating because it makes you want to do more than you are capable of!!!! At least it stops the brain cells switching off!
All of the helper's time here appreciated.
ja  Reply With Quote

15. I just love watching you do what you do best Wilbert. That is off the chain   Reply With Quote

16. @Jarnold,
To keep track of score, you can define a variable outside of a function. That way it can be accessed by all functions. If the reset button is pressed, you could increase the total number so you know when it reaches five. If the time is set right, you can increase a counter for the amount of successes.
But I guess you would need a check button instead because at the moment you can simply turn the arms as much as you want until you reach the right time. It might make more sense to not show anything when it is right and make the arms show a red or green glow when a check button is pressed so there's no way to cheat.

@Chris,
Thanks   Reply With Quote

17. Hi again I can't get over how sophisticated this is instead of using a jpg for the clock face. Would I have to do something like this to have the hour numbers? Not my script.
var txt_TextField_12:TextField = new TextField();

txt_TextField_12.selectable = false;

txt_TextField_12.defaultTextFormat = format;

txt_TextField_12.autoSize = TextFieldAutoSize.CENTER;

txt_TextField_12.text = "12";

txt_TextField_12.x = stage.stageWidth/2 -txt_TextField_12.width/2 ;

txt_TextField_12.y = 25;

I think that you mean to have the counter here which then calls the reset function.
//var score:Number = 0;
//var counter:Number = 0;
//var finish:String ="";
f
unction checkTime():void {
tInfo.text = 'Target = ' + hTarget + ':' + String(100 + mTarget).substr(-2) + '\n\n';
tInfo.appendText('Time = ' + h + ':' + String(100 + m).substr(-2));
if (h == hTarget && m == mTarget){
//score = score++;
//counter = counter++;
// if (counter = 5)
//finish.txt = "you scored", score.txt;
// call reset function

} else {
}
}

function resetTime(e:MouseEvent = null):void {
sHour.rotation = 0;
sMinutes.rotation = 0;
h = 12;
m = 0;
hTarget = 1 + Math.floor(Math.random() * 12);
mTarget = Math.floor(Math.random() * 60);
checkTime();
}

resetTime();  Reply With Quote

18. That's more or less the idea Jarnold.

A few remarks :
- You can declare the variables as int since they have no decimals.
- Just ++ is enough for an increase.
- To compare values, use ==, not =.

var score:int = 0;
var counter:int = 0;
score++;
counter++;
if (score == counter){
// action
}

Maybe it would also be required to lock the arms of the clock once the correct time has been reached to prevent recounting the same task multiple times.  Reply With Quote

john  Reply With Quote

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

 » Home » Movies » Tutorials » Submissions » Board » Links » Reviews » Feedback » Gallery » Fonts » The Lounge » Sound Loops » Sound FX » About FK » Sitemap 