A Flash Developer Resource Site

Results 1 to 19 of 19

Thread: help with rotations for clocks and angles

  1. #1
    Member
    Join Date
    Aug 2008
    Posts
    78

    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.


    minutehand.addEventListener(MouseEvent.CLICK, mouseClickHandler);
    minutehand.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);

    hourhand.addEventListener(MouseEvent.CLICK, hourClickHandler);
    hourhand.addEventListener(MouseEvent.MOUSE_MOVE, hourMoveHandler);

    var mouseposx:int;
    var mouseposy:int;
    var dragablemin = false; // start with it still
    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)
    }

    }
    Attached Files Attached Files

  2. #2
    KoolMoves Moderator blanius's Avatar
    Join Date
    Jul 2001
    Location
    Atlanta GA
    Posts
    5,244
    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)

  3. #3
    Member
    Join Date
    Aug 2008
    Posts
    78

    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
    Attached Files Attached Files
    Last edited by jarnold; 01-03-2010 at 12:48 AM.

  4. #4
    KoolMoves Moderator blanius's Avatar
    Join Date
    Jul 2001
    Location
    Atlanta GA
    Posts
    5,244
    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+

  5. #5
    Member
    Join Date
    Aug 2008
    Posts
    78
    Quote Originally Posted by blanius View Post
    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
    Attached Files Attached Files

  6. #6
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    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 ?

  7. #7
    KoolMoves Moderator blanius's Avatar
    Join Date
    Jul 2001
    Location
    Atlanta GA
    Posts
    5,244
    Quote Originally Posted by w.brants View Post
    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.

  8. #8
    Member
    Join Date
    Aug 2008
    Posts
    78
    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
    Attached Files Attached Files
    Last edited by jarnold; 01-04-2010 at 08:47 PM.

  9. #9
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    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 .

  10. #10
    Member
    Join Date
    Aug 2008
    Posts
    78
    [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.

    minutehand.addEventListener(MouseEvent.CLICK, mouseClickHandler);
    minutehand.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);

    hourhand.addEventListener(MouseEvent.CLICK, hourClickHandler);
    hourhand.addEventListener(MouseEvent.MOUSE_MOVE, hourMoveHandler);

    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
    }

  11. #11
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    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;
    addChild(sBase);
    
    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;
    addChild(sHour);
    
    var sMinutes:Sprite = new Sprite();
    sMinutes.mouseEnabled = false;
    sMinutes.x = cx;
    sMinutes.y = cy;
    addChild(sMinutes);
    
    var sDot:Sprite = new Sprite();
    sDot.buttonMode = true;
    sDot.x = cx;
    sDot.y = cy;
    addChild(sDot);
    
    // create filters
    
    var glow:GlowFilter = new GlowFilter(0x80ff80, 0.7, 8, 8);
    var shade:DropShadowFilter = new DropShadowFilter(4, 45, 0, 0.7);
    
    // 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);
    sHour.addChild(shHandle);
    
    // 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);
    sDot.filters = [shade];
    
    // 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);
    sMinutes.addChild(smHandle);
    
    // 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;
    addChild(tInfo);
    
    // main code
    
    var h, m:Number;
    var hTarget, mTarget:Number;
    
    var moving:*;
    sDot.addEventListener(MouseEvent.CLICK, resetTime);
    shHandle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
    smHandle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
    stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
    stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
    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){
    		sHour.filters = [shade, glow];
    		sMinutes.filters = [glow, shade];
    	} else {
    		sHour.filters = [shade];
    		sMinutes.filters = [shade];
    	}
    }
    
    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();

  12. #12
    Member
    Join Date
    Aug 2008
    Posts
    78
    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

  13. #13
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    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.

  14. #14
    Member
    Join Date
    Aug 2008
    Posts
    78
    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

  15. #15

  16. #16
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    @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

  17. #17
    Member
    Join Date
    Aug 2008
    Posts
    78
    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";

    addChild(txt_TextField_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){
    sHour.filters = [shade, glow];
    //score = score++;
    //counter = counter++;
    // if (counter = 5)
    //finish.txt = "you scored", score.txt;
    // call reset function
    sMinutes.filters = [glow, shade];

    } else {
    sHour.filters = [shade];
    sMinutes.filters = [shade];
    }
    }

    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();
    Last edited by jarnold; 01-06-2010 at 05:11 AM.

  18. #18
    Senior Member
    Join Date
    Dec 2002
    Location
    Netherlands
    Posts
    1,632
    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.

  19. #19
    Member
    Join Date
    Aug 2008
    Posts
    78
    Thanks for the advice - very helpful.
    john

Posting Permissions

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




Click Here to Expand Forum to Full Width

HTML5 Development Center