Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Аналоговые часы на as3 - вопрос по реализации! (http://www.flasher.ru/forum/showthread.php?t=146059)

tsarapkabel 27.10.2010 23:25

Аналоговые часы на as3 - вопрос по реализации!
 
Вложений: 1
Приветиус!

Сделал часы, но до конца недоработал, меня уже давно терзают сомнения по поводу правильности реализации!

Это одно из моих первых "произведений", поэтому выглядит довольно странно.

Контейнеры создаются для того, чтобы "сместить точку регистрации" для более правильного вращения.

Код AS3:

package {
        import flash.display.Sprite;
        import flash.events.Event;
        import mx.core.BitmapAsset;
 
 
 
        public class KanjiClock extends Sprite {
 
                [Embed(source = "kanji_clock.jpg")] //подключаем jpg
                var ClockDial:Class;
 
                private var secHand:Sprite;
                private var minHand:Sprite;
                private var hourHand:Sprite;
 
                private var secContainer:Sprite;
                private var minContainer:Sprite;
                private var hourContainer:Sprite;
 
 
                public function KanjiClock ():void {
 
                        var dial:BitmapAsset = new ClockDial(); //объявляем переменную от Embed source
                        stage.addChild (dial);        //добавляем циферблат (jpg) на сцену
 
                        var centerCircle:Sprite = new Sprite(); //центральный кружок
                        centerCircle.graphics.beginFill (0x000000);
                        centerCircle.graphics.drawCircle (148, 148, 7);
                        centerCircle.graphics.endFill();
 
                        secContainer =  new Sprite(); //контейнер для секундной стрелки
                        secContainer.x = 148;
                        secContainer.y = 148;
                        secContainer.rotation = 180;
 
                        minContainer =  new Sprite(); //контейнер для минутной стрелки
                        minContainer.x = 148;
                        minContainer.y = 148;
                        minContainer.rotation = 180;
 
                        hourContainer =  new Sprite(); //контейнер для часовой стрелки
                        hourContainer.x = 148;
                        hourContainer.y = 148;
                        hourContainer.rotation = 180;
 
                        secHand = new Sprite(); //секундная стрелка
                        secHand.graphics.lineStyle (.1, 0x000000);
                        secHand.graphics.beginFill (0x0066CC);
                        secHand.graphics.drawRect (0, 0, 4, 100);
                        secHand.graphics.endFill();
                        secHand.x = - 2;
                        secHand.y = 0;
 
                        minHand = new Sprite(); //минутная стрелка
                        minHand.graphics.lineStyle (.1, 0x000000);
                        minHand.graphics.beginFill (0x650099);
                        minHand.graphics.drawRect (0, 0, 6, 80);
                        minHand.graphics.endFill();
                        minHand.x = - 3;
                        minHand.y = 0;
 
                        hourHand = new Sprite(); //часовая стрелка
                        hourHand.graphics.lineStyle (.1, 0x000000);
                        hourHand.graphics.beginFill (0x660000);
                        hourHand.graphics.drawRect (0, 0, 8, 60);
                        hourHand.graphics.endFill();
                        hourHand.x = - 4;
                        hourHand.y = 0;
 
                        //добавляем стрелки в их контейнеры
                        secContainer.addChild (secHand);
                        minContainer.addChild (minHand);
                        hourContainer.addChild (hourHand);
 
                        //добавляем на stage контейнеры со стрелками и кружок в центр
                        stage.addChild (hourContainer);
                        stage.addChild (minContainer);
                        stage.addChild (secContainer);
                        stage.addChild (centerCircle);
 
                        stage.addEventListener (Event.ENTER_FRAME, onEnterFrame, false, 0, true);
 
 
                        function onEnterFrame (e:Event):void {
 
                                var currentDate:Date = new Date();
                                var sec:Number = currentDate.getUTCSeconds();
                                var min:Number = currentDate.getUTCMinutes();
                                var hour:Number = currentDate.getUTCHours();
 
                                //добавляем вращение контейнерам
                                secContainer.rotation = 180+6*sec;
                                minContainer.rotation = 180+6*min + sec*0.1;
                                hourContainer.rotation = 180+30*(hour+4) + min/2;
                        }
 
                }
 
        }
 
}

Насколько это безграмотно?

Нужен ли здесь метатег Embed или можно было обойтись простым loader'ом?

Да и вообще буду рад любому мнению! :drinks:

udaaff 27.10.2010 23:39

То что UTC — это так надо?

deamoK 27.10.2010 23:40

Не догнал зачем контейнеры Оо
В спрайте самом и рисовать
Для часов, имхо, лучше использовать Timer, а не ИнтеФрейм, тк сомневаюсь, что у вас частота кадров 1фпс

tsarapkabel 28.10.2010 01:00

Вложений: 1
2 udaaff

* В дальнейшем планировал добавить стандарт: Нью-Йорк, Токио и Лондон.
А вообще согласен - для данного случая можно и местное взять.


2 deamoK

* Частота кадров стоит 24 (как-то не задумываясь поставил).
Если можно - поподробнее, чем Timer лучше, почему не setInterval или не EnterFrame?

* В спрайте и рисую, просто если вращать спрайт, то вращение будет не совсем правильным для стрелки толщиной более 1 пикселя.
Представь как вращается стрелка вокруг красной точки (см рисунок).

Wolsh 28.10.2010 02:22

А нарисовать стрелку так чтобы ее ось была в (0, 0) - никак? Отрицательные координаты никто не отменял)))

tsarapkabel 28.10.2010 02:48

А как же я её потом вращать буду? Я для того и пихаю её в контейнер с отрицательными координатами.
Если я неправильно понял, покажите пожалуйста пример!

Wolsh 28.10.2010 09:46

Код AS1/AS2:

minHand.graphics.drawRect (-3, -3, 6, 80);

Добавлено через 20 минут
Точнее в Вашем случае
Код AS3:

secHand.graphics.drawRect (-2, 0, 4, 100);
minHand.graphics.drawRect (-3, 0, 6, 80);
hourHand.graphics.drawRect (-4, 0, 8, 60);

и никаких контейнеров не надо.

tsarapkabel 28.10.2010 16:03

Wolsh, спасибо большое, код сократился малость.

Код AS3:

package {
        import flash.display.Sprite;
        import mx.core.BitmapAsset;
        import flash.events.Event;
 
 
        public class KanjiClock extends Sprite {
 
                [Embed(source = "kanji_clock.jpg")] //подключаем jpg
                var ClockDial:Class;
 
                private var secHand:Sprite;
                private var minHand:Sprite;
                private var hourHand:Sprite;
 
 
                public function KanjiClock ():void {
 
                        var dial:BitmapAsset = new ClockDial(); //объявляем переменную от Embed source
                        stage.addChild (dial);        //добавляем циферблат (jpg) на сцену
 
                        var centerCircle:Sprite = new Sprite(); //центральный кружок
                        centerCircle.graphics.beginFill (0x000000);
                        centerCircle.graphics.drawCircle (148, 148, 7);
                        centerCircle.graphics.endFill();
 
                        secHand = new Sprite(); //секундная стрелка
                        secHand.graphics.lineStyle (.1, 0x000000);
                        secHand.graphics.beginFill (0x0066CC);
                        secHand.graphics.drawRect (-2, 0, 4, 100);
                        secHand.graphics.endFill();
                        secHand.x = 148;
                        secHand.y = 148;
 
                        minHand = new Sprite(); //минутная стрелка
                        minHand.graphics.lineStyle (.1, 0x000000);
                        minHand.graphics.beginFill (0x650099);
                        minHand.graphics.drawRect (-3, 0, 6, 80);
                        minHand.graphics.endFill();
                        minHand.x = 148;
                        minHand.y = 148;
 
                        hourHand = new Sprite(); //часовая стрелка
                        hourHand.graphics.lineStyle (.1, 0x000000);
                        hourHand.graphics.beginFill (0x660000);
                        hourHand.graphics.drawRect (-4, 0, 8, 60);
                        hourHand.graphics.endFill();
                        hourHand.x = 148;
                        hourHand.y = 148;
 
                        //добавляем стрелки на stage и кружок в центр
                        stage.addChild (hourHand);
                        stage.addChild (minHand);
                        stage.addChild (secHand);
                        stage.addChild (centerCircle);
 
                        stage.addEventListener (Event.ENTER_FRAME, onEnterFrame, false, 0, true);
 
                        function onEnterFrame (e:Event):void {
 
                                var currentDate:Date = new Date();
                                var sec:Number = currentDate.getUTCSeconds();
                                var min:Number = currentDate.getUTCMinutes();
                                var hour:Number = currentDate.getUTCHours();
 
                                //добавляем вращение стрелкам
                                secHand.rotation = 180+6*sec;
                                minHand.rotation = 180+6*min + sec*0.1;
                                hourHand.rotation = 180+30*(hour+4) + min/2;
                        }
 
                }
 
        }
 
}

А кто что думает по поводу Embed/loader?

EnterFrame для обновления оптимален?

:umnik2:

КорДум 28.10.2010 16:10

Цитата:

EnterFrame для обновления оптимален?
А разве непонятно? обновлять информацию 22-26 раз в секунду или один раз?
Таймер на 1 секунду оптимальнее. Но будут наблюдаться некоторые глюки, как то: между тиками может быть разница больше, чем в одну секунду. Ну и меньше, тоже. Причем это только визуально, время показывать будет правильно в любом случае.
При enterFrame будет плавность тиков, то есть, будут равные интервалы между этими тиками.

deamoK 28.10.2010 18:14

Цитата:

2 deamoK

* Частота кадров стоит 24 (как-то не задумываясь поставил).
Если можно - поподробнее, чем Timer лучше, почему не setInterval или не EnterFrame?

* В спрайте и рисую, просто если вращать спрайт, то вращение будет не совсем правильным для стрелки толщиной более 1 пикселя.
Представь как вращается стрелка вокруг красной точки (см рисунок).
вот пример, наклепал часы без контейнеров и с таймером:

Код AS3:

package  
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.TimerEvent;
        import flash.utils.Timer;
 
        public class SimpleTest extends Sprite
        {
                private var minHand:Shape;
                private var secHand:Shape
                private var timer:Timer;
                private var date:Date;
                private var border:Shape;
                private var hourHand:Shape;
 
                private var sec:int;
                private var min:int;
                private var hour:int;
 
                public function SimpleTest()
                {
                        secHand = new Shape();
                        minHand = new Shape();
                        hourHand = new Shape()
                        border = new Shape()
                        timer = new Timer(1000);
 
                        border.graphics.lineStyle(1, 0xCCCCCC);
                        border.graphics.drawCircle(0, 0, 110);
                        border.graphics.beginFill(0);
                        border.graphics.drawCircle(0, 0, 5)
 
                        secHand.graphics.beginFill(0xFF0000);
                        secHand.graphics.drawRect(-1, -100, 2, 120);
 
                        minHand.graphics.beginFill(0);
                        minHand.graphics.drawRect(-2, -80, 4, 80);
 
                        hourHand.graphics.beginFill(0xCCCCCC)
                        hourHand.graphics.drawRect(-3, -60, 6, 60)
 
                        addChild(hourHand);
                        addChild(minHand);
                        addChild(secHand);
                        addChild(border);
 
                        x = y = 300;
                        timer.addEventListener(TimerEvent.TIMER, onTick);
                        timer.start();
                        onTick()
                }
 
                private function onTick(e:TimerEvent = null):void
                {
                        date = new Date();
                        sec = date.getSeconds();
                        min = date.getMinutes();
                        hour = date.getHours();
 
                        secHand.rotation = sec * 6;
                        minHand.rotation = min * 6 + sec / 10;
                        hourHand.rotation = hour * 30 + min / 2;
                }
        }
}


tsarapkabel 29.10.2010 05:05

Всё понятно, но такой вариант породил одну проблемку:


Если я делаю так
Код AS3:

addChild (dial);        //добавляем циферблат (jpg) на сцену
 
addChild (hourHand);
addChild (minHand);
addChild (secHand);
 
x = y = 148;

то x = y = 148 срабатывает и для dial, который должен стоять в нуле. :(


Если пихнуть его на stage
Код AS3:

stage.addChild(dial);        //добавляем циферблат (jpg) на сцену
 
addChild (hourHand);
addChild (minHand);
addChild (secHand);
 
x = y = 148;

то всё добавляется правильно, но стрелок я не вижу за dial'ом. :(


Пока вариант решения такой
Код AS3:

stage.addChild (dial);        //добавляем циферблат (jpg) на сцену
 
secHand.x = secHand.y = 148;
minHand.x = minHand.y = 148;
hourHand.x = hourHand.y = 148;
 
stage.addChild (hourHand);
stage.addChild (minHand);
stage.addChild (secHand);

однако приходится шесть раз присваивать одно и тоже значение и класть всё на stage.


Может есть более разумный вариант как разместить стрелки по центру, а dial в нуле?

КорДум 29.10.2010 08:31

Почему именно на stage?

tsarapkabel 29.10.2010 21:25

В принципе неважно куда. Главное чтобы стрелки были в центре, а циферблат в нуле.

deamoK 30.10.2010 00:46

Цитата:

Сообщение от tsarapkabel (Сообщение 946467)
В принципе неважно куда. Главное чтобы стрелки были в центре, а циферблат в нуле.

Помоему удобно использовать ноль как центр...

Код AS1/AS2:

package  
{
        import flash.display.Bitmap;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.TimerEvent;
        import flash.utils.Timer;
 
        public class SimpleClock extends Sprite
        {
                private var minHand:Shape;
                private var secHand:Shape
                private var timer:Timer;
                private var date:Date;
                private var border:Bitmap;
                private var hourHand:Shape;
 
                private var sec:int;
                private var min:int;
                private var hour:int;
 
                [Embed(source="D:/Pictures/trad.png")]
                private var borderClass:Class
 
                public function SimpleClock()
                {
                        secHand = new Shape();
                        minHand = new Shape();
                        hourHand = new Shape()
                        border = new borderClass();
                        timer = new Timer(1000);
 
                        border.x = -border.width / 2;
                        border.y = -border.height / 2
 
                        secHand.graphics.beginFill(0xFF0000);
                        secHand.graphics.drawRect( -1, -50, 2, 70);
                        secHand.graphics.beginFill(0xFF0000);
                        secHand.graphics.drawCircle(0, 0, 5)
 
                        minHand.graphics.beginFill(0);
                        minHand.graphics.drawRect(-2, -40, 4, 40);
 
                        hourHand.graphics.beginFill(0xCCCCCC)
                        hourHand.graphics.drawRect(-2, -30, 4, 30)
 
                        addChild(border);
                        addChild(hourHand);
                        addChild(minHand);
                        addChild(secHand);                       
 
                        x = y = 350;
                        timer.addEventListener(TimerEvent.TIMER, onTick);
                        timer.start();
                        onTick()
                }
 
                private function onTick(e:TimerEvent = null):void
                {
                        date = new Date();
                        sec = date.getSeconds();
                        min = date.getMinutes();
                        hour = date.getHours();
 
                        secHand.rotation = sec * 6;
                        minHand.rotation = min * 6 + sec / 10;
                        hourHand.rotation = hour * 30 + min / 2;
                }
        }
}

Можно перемещать контейнер куда угодно, все стрелки с циферблатом будут на месте

tsarapkabel 30.10.2010 20:53

Спасибо, deamoK, всё понял!

Благодарю всех участников обсуждения за помощь! :victory:

Psy486 15.11.2010 09:30

Вложений: 1
Добрый день! (хотя если учесть только один выходной, не очень и добрый =))
Я по честному нашел поиском тему и решил новые темы не плодить, да просить прям тута.

У меня такая проблемка с аналоговыми часами, для меня странная.
Раньше использовал АС2, а тут проект притащили на АС3 и надо часики сделать.
Часики-то сделал, но к сожалению их надо повернуть влево на 45°
Когда я их проворачиваю, получается, что флешу это до задницы и он стрелки ставит относительно стандартной вертикали.
Как сделать так, чтоб он ставил стрелки относительно часов и как бы я их ни проворачивал, он брал за основу положение стрелок или еще как-то (я не совсем понимаю что ему надо.)
Часики прилагаю.

КорДум 15.11.2010 09:51

Psy486, исходник не смотрел, но вероятно вы добавляете стрелки НА циферблат, а не В контейнер с циферблатом.

Добавлено через 7 минут
Исходник посмотрел. Фу-фу-фу, плохой исходник - код в кадре, классы не используются вообще. И да, по поводу контейнера я был прав. Посмотрите, как реализованы часы в этой теме. И не пишите код в кадрах.

Psy486 15.11.2010 10:14

КорДум О как. Ну я АС3 вообще не использовал никогда и потому не вразумию как правильно =)
ОК, спасибы, пойду сейчас код тут смотреть и интегрировать О_о

Добавлено через 2 часа 41 минуту
Чего-то не знаючи АС3 сталкиваюсь с некоторыми проблемами...
Может есть у кого такой хороший исходник часиков, которые как ни верти, а правильные, чтоб я на примере глянул как на самом деле делать надо?
Буду афигительно благодарен и скажу спасибо от всей души!!!

deamoK 15.11.2010 13:36

5ью постами выше, есть код
Цитата:

Можно перемещать контейнер куда угодно, все стрелки с циферблатом будут на месте
, вертеть тоже можно

КорДум 15.11.2010 13:40

Psy486, судя по всему, вы не писали никогда на ас2, только на ас1. А там подходы достаточно похожие. Классы ас2 и классы ас3 очень схожи, если в ас2, вместо прямого назначения обработчикам события методов, назначать эти методы через Delegate с ссылкой на главный объект, к которому присобачен класс (this, как правило). Так что...что тут посоветовать - книгу Мука?


Часовой пояс GMT +4, время: 15:18.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.