Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   упругая линия (http://www.flasher.ru/forum/showthread.php?t=121686)

N_Daemon 22.02.2009 23:31

Iv, могу конкретнее прямая вертикальная линия нижний конец линии зафиксирован, а верхний чтоб например можно было взять мышкой и согнуть как пластиковую указку например а потом при отпускании верхнего конца чтоб опять выпрямилась в исходное положение =) никто не может посоветовать что то конкретное =)

heapKiller 22.02.2009 23:39

Учебник физики возьмите F = kx - k - коэффициент x - смещение.
Рисуете линию из точек выводите зависимость смещения от растояния до места приложения силы т. д. и т. п. или Вы в школе физику прогуливали?

N_Daemon 23.02.2009 00:01

heapKiller, в школе я много че прогуливал интересы другие были. Каюсь конечно =) но школа давно кончилась

Iv 23.02.2009 03:06

ну жесть тут порядки наступили: пока писал закончилась сессия, хорошо, что смог кинуть в блокнот писанину. Вот она:

=======
Вооот. Вот тут школьные зануды-очкарики тебя и поимеют. За все их бесцельно прожитые в школе годы :)

Смотри, если у тебя палка и, если ее сгибать, то она, не поверишь, при сгибании будет приобретать кривизну параболы. Прикинь. Ну, если она одинаковая по всей длине. А парабола, не поверишь - это кривая Безье второго порядка. Вот такое совпадение. И это не всё. На твой вопрос отвечает человек, сильно увлекавшийся вопросом изучения кривых Безье в течение нескольких лет. А это уже не совпадение. Это рок! Потому, что он тока что с вечерины. В смысле я. Хуже того, как известно, кривые Безье на самом деле не кривые Безье, а полиномы Бернштейна, ну, или на худой конец кривые Де Кастело (ударение почему-то на последний слог), но, к счастью, к нашему вопросу это отношения не имеет. Ну, а в оригинале, это парабола, известная с античных времён, предмет пристального изучения Архимеда.
Ну, хрен с ним, с роком и иностранными фамилиями. Хотя Бернштейн - харьковский учёный, но назвать его фамилию русской язык не поворачивается. К вопросу.
Итак, идея проста: есть палка, вертикально закрепленная в основании. Мы можем ухватить ее за любую часть и согнуть. Как и у любой палки, при сгибании ее длина не меняется. ЗАСАДА! Нет. Спокойне, ща порешаем.
Когда мы тянем мышой, ну, она должна сопротивляться типо. Т.е. чем больше отклоняем, тем дальше мыша от точки захвата - эдакие тактильные ошущения в глаз юзверю.
Уффф. что-то я путаюсь в показаниях, товарищ начальник, ща.

Ну, лады. Тянем - сгибается. Тянем - сгибается. Ага, значит будем делать так: мы знаем длину палки. И знгаем, в каком именно месте палки мы за нее ухватили, т.е. на каком расстоянии от основания. У безьёв прикольная геометрия - в точке основания, вот в самой точке, в нашем случае, касательная к этой точке будет всегда вертикальна.
А, да, если мы ухватили не за вершину палки, то остальная ее часть, та, что повыше места хватания, изгибаться не будет и останется ровной, правильно? Ну это так, хозяйке на заметку.
И всё-таки нечеловеческими усилиями подходим к формулировке задачи: нужно построить кривую Безье, зная начальную точку, касательную к ней, и конечную точку.
Ну, как-бе условий недостаточно. Очевидно, что удовлетворяющих этому условию кривых будет множество, а не единственная. В смысле, это зависит от эластичности палки. Ну а нам-то что? Мы не будем заморачиваться в этом смысле и введём какую-нибудь эмпирическую константу, которая нам обеспечит недостающие данные. (Чё сказал?)
На практике, третью контрольную точку мы рассчитаем как тупо середину по вертикали между основанием и точкой захвата. Чтобы жить легче было (чуть что - поменяем, это же эмпирическая константа). Ну, а как мы помним, касательная в основании всегда вертикальна - это рраз. Контрольная точка C лежит на пересечении касательных - это два. Т.е. если мы решили, что по вертикали эмпирически берём половину, то нам придётся тупо делить на два. Хотелось, конечно формул модных, но нам же результат подавай, правильно?

Вот щас покурил, и воткнул, что я правильно решил, что эмпирическая константа у нас равна 1/2. Ну, если исходить из посыла выше, что палка у нас монотонная по всем показателям. А если она как дерево - толще к основанию и тоньше к вершине, то эта самая константа сместится от 1/2 к единице.
Ну вот, порассуждали, поняли, что нам нужно, ща попробую код написать. Не факт, что получится, ибо. Но попробую.

Добавлено через 38 минут
Ну, разумеется, что рассуждения выше на практике ничего не стоят.
Тут еще какая фишка образовалась: мои рассуждения имели смысл только для случая, когда мы тянем палку строго перпендикулярно точке захвата. тогда наша эмпирическая константа имеет смысл. А если тянем палку не перпендикулярно точке захвата, то получается, что эмпирическая константа сосёт. Ну это, она становится не константой. И это придётся учесть.
Пишу.

Добавлено через 47 минут
Не пишу. Пытаюсь осознать.

Добавлено через 1 час 19 минут
Есть подозрение, что я перемудрил в рассуждениях.
Возможно, что вполне сгодится вот такое:

Код AS3:

package {
        import flash.display.MovieClip;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
 
        public class ElaStickMain extends MovieClip {
 
                private var stick:ElaStick;
 
                public function ElaStickMain() {
                        initInstance();
                }
 
                private function initInstance():void {
                        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
                }
 
                private function onAddedToStage(event:Event):void {
                        initStage();
                        initElaStick();
                }
 
                private function initElaStick():void {
                        const stickLength:uint = 300;
                        const stickBend:Number = 1/2;
                        stick = new ElaStick(stickLength, stickBend);
                        stick.x = stage.stageWidth/2;
                        stick.y = stage.stageHeight;
                        addChild(stick);
                }
 
                private function initStage():void {
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        stage.align = StageAlign.TOP_LEFT;
                }
        }
}

и сам класс:

Код AS3:

package {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;               
 
        public class ElaStick extends Sprite {
 
                private var stickLength:uint = 0;
                private var bend:Number = 1/2;
 
                private var captureDistance:Number;
 
                private const start:Point = new Point(0, 0);
                private const end:Point = new Point(0, 0);
                private const control:Point = new Point(0, 0);
                private const targetPoint:Point = new Point(0, 0);
 
                private var speedX:Number = 0;
                private var speedY:Number = 0;
 
                public function ElaStick(len:uint = 300, stickBend:Number = 1/2) {
                        initInstance(len, stickBend);
                }
 
                private function initInstance(len:uint, stickBend:Number):void {
                        stickLength = len;
                        bend = stickBend;
                        initControlPoints();
                        redraw();
 
                        addEventListener(MouseEvent.MOUSE_DOWN, onStartBend);
                }
 
                private function onStartBend(event:MouseEvent):void {
                        removeEventListener(Event.ENTER_FRAME, onMoveToInitialPosition);
 
                        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                        addEventListener(Event.ENTER_FRAME, onDragEnterFrame);
 
                        captureDistance = -mouseY;
 
                        onMouseMove();
                }
 
                private function onMouseMove(event:MouseEvent = null):void {
                        targetPoint.x = mouseX;
                        targetPoint.y = mouseY;
                }
 
                private function onMouseUp(event:MouseEvent):void {
                        stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                        stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                        removeEventListener(Event.ENTER_FRAME, onDragEnterFrame);
                        addEventListener(Event.ENTER_FRAME, onMoveToInitialPosition);
                        speedX = 0;
                        speedY = 0;
                }
 
                private function onDragEnterFrame(event:Event):void {
                        end.x += (targetPoint.x - end.x)*.1;
                        end.y += (targetPoint.y - end.y)*.1;
                        control.y = end.y/2;
                        redraw();
                }
 
                private function onMoveToInitialPosition(event:Event):void {
                        speedX += (0 - targetPoint.x)*.01;
                        speedY += (-stickLength - targetPoint.y)*.01;
                        speedX *= .96;
                        speedY *= .96;
                        targetPoint.x += speedX;
                        targetPoint.y += speedY;
 
                        end.x += (targetPoint.x - end.x)*.1;
                        end.y += (targetPoint.y - end.y)*.1;
                        control.y = end.y/2;
                        redraw();
                }
 
                private function initControlPoints():void {
                        end.y = -stickLength;
                        control.y = -stickLength/2;
                }
 
                private function redraw():void {
                        graphics.clear();
                        graphics.lineStyle(4, 0x0000FF, 1);
                        graphics.moveTo(start.x, start.y);
                        graphics.curveTo(control.x, control.y, end.x, end.y);
                }
        }
}


N_Daemon 28.02.2009 16:59

Iv =) Это конечно все круто буков много и все такое Ток толку от этого нет я ж не прошу помощи в расчетах или в рассуждениях я просил помощи в AS3 точнее в методах реализации =) вместо огромного предисловия Закаментил бы лучше код у меня вся проблема то в том что опыта в AS именно нет А так спасибо конечно за помощь

Iv 28.02.2009 17:08

1. Код полностью рабочий.
2. Постановка задачи никакая - из-за этого приходится предполагать что тебе нужно. Писать тонны кода на предположениях того, что тебе нужно - терять попусту время.
3. Ты так и не удосужился ответить на мой первый комментарий, но продолжаешь просить чего-то.
4. Если тебе требуется подсказка, совет, направление для мысли или помощь в решении конкретной проблемы, то ты попал по адресу.
Но здесь не благотворительное общество. Если тебе нужно готовое решение, то пиши техническое задание, обозначь бюджет и найди исполнителя.

iNils 28.02.2009 17:53

N_Daemon, не надо игнорировать знаки препинания, у нас за это плюсуют.

N_Daemon 28.02.2009 21:22

iNils, я извиняюсь конечно. Аська в телефоне убивает остатки грамотность блин =(

Добавлено через 26 минут
Iv, как бы те объяснить, мне не нужно готовое решение, я сам вообще админ и допустим если у меня попросят скажем спроектировать скс, я возможно тоже попрошу тех задание и компенсацию за это. Хотя с другой стороны, если мне допустим менее опытный человек задаст какие либо вопросы, я ему на эти вопросы отвечу в меру возможности и не буду лесть в бутылку. Я благодарен за помощь и за рабочий код =), отвечая на ваш первый комментарий, на данном этапе не важно что это будет за упругая палка, не важно какая она будет вертикальная, горизонтальная или по диагонали, для меня важны методы А толку мне в коде который я не понимаю, со справочниками я часть разобрал но есть вещи которые объясняются не четко. Просьба, если вам не составило труда написать этот код и кучу постов в тему за комментируйте код пожалуйста, на каком этапе что происходит. Для меня важно не копирнуть отсюда ваш код и использовать его как готовый где мне заблагорассудится, а понят как оно сделано =)

Iv 28.02.2009 22:04

Код AS3:

package {
        import flash.display.MovieClip;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
 
        public class ElaStickMain extends MovieClip {
 
                private var stick:ElaStick;
 
                public function ElaStickMain() {
                        initInstance();
                }
 
                private function initInstance():void {
                        // слушаем событие добавления на сцену
                        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
                }
 
                private function onAddedToStage(event:Event):void {
                        // когда добавился объект на сцену
                        // инициализируем поведение сцены
                        initStage();
                        // инициализируем палку
                        initElaStick();
                }
 
                private function initElaStick():void {
                        // длину палки
                        const stickLength:uint = 300;
                        // равномерность палки (1/2 - однородная, больше 1/2 - как дерево - толще к корню, меньше 1/2 - утолщается к вершине)
                        const stickBend:Number = 1/2;
                        // создаем экземпляр палки
                        stick = new ElaStick(stickLength, stickBend);
                        // задаем позицию
                        stick.x = stage.stageWidth/2;
                        stick.y = stage.stageHeight;
                        // добавляем палку на сцену
                        addChild(stick);
                }
 
                private function initStage():void {
                        // режим масштабирования сцены - масштабирование запрещено
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        // расположение точки начала отсчета в верхнем левом углу
                        stage.align = StageAlign.TOP_LEFT;
                }
        }
}

ща второй класс наваяю.

Добавлено через 35 минут
Код AS3:

package {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;               
 
        public class ElaStick extends Sprite {
 
                private var stickLength:uint = 0;
                private var bend:Number = 1/2;
 
                private var captureDistance:Number;
                // кривая Безье второго порядка задается тремя точками
                // см. подробности здесь: http://bezier.ru/
                private const start:Point = new Point(0, 0);
                private const end:Point = new Point(0, 0);
                private const control:Point = new Point(0, 0);
                // целевая точка
                private const targetPoint:Point = new Point(0, 0);
                // ортогональные составляющие шага скорости
                private var speedX:Number = 0;
                private var speedY:Number = 0;
                // конструктор класса. принимает в качестве параметров длину и коэффициент равномерности палки
                public function ElaStick(len:uint = 300, stickBend:Number = 1/2) {
                        // вызываем инициализацию объекта
                        initInstance(len, stickBend);
                }
 
                private function initInstance(len:uint, stickBend:Number):void {
                        // сохраняем данные о палке
                        stickLength = len;
                        bend = stickBend;
                        // инициализируем контрольные точки
                        initControlPoints();
                        // рисуем результат
                        redraw();
                        // слушаем событие мыши на нажатие
                        addEventListener(MouseEvent.MOUSE_DOWN, onStartBend);
                }
 
                // обработчик события mouse down
                private function onStartBend(event:MouseEvent):void {
                        // удаляем прослушивание события ENTER_FRAME (если был ранее задан и еще не окончился режим возврата в начальное положение)
                        removeEventListener(Event.ENTER_FRAME, onMoveToInitialPosition);
                        // начинаем слушать событие движения мыши
                        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                        // а также отпускания мыши
                        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                        // назначаем  на ENTER_FRAME обработчик при таскании объекта
                        addEventListener(Event.ENTER_FRAME, onDragEnterFrame);
                        // запоминаем расстояние от начала, на котором ухватили палку
                        captureDistance = -mouseY;
                        // принудительно вызываем обработчик движения мыши
                        onMouseMove();
                }
 
                private function onMouseMove(event:MouseEvent = null):void {
                        // при движении мыши обновляем координаты целевой точки
                        targetPoint.x = mouseX;
                        targetPoint.y = mouseY;
                }
 
                private function onMouseUp(event:MouseEvent):void {
                        // при отпускании мыши отписываемся от событий, которые обрабатывали таскание.
                        stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                        stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                        removeEventListener(Event.ENTER_FRAME, onDragEnterFrame);
                        // и назначаем обработчик события, отвечающий за возврат в исходное положение.
                        addEventListener(Event.ENTER_FRAME, onMoveToInitialPosition);
                        // обнуляем начальную скорость
                        speedX = 0;
                        speedY = 0;
                }
 
                private function onDragEnterFrame(event:Event):void {
                        // каждый кадр в режиме таскания конечная точка стремится
                        // приблизиться к целевой точке на 1/10 расстояния между ними.
                        // собственно можно поиграться с параметром .1, поизменять его, чтобы добиться нужного поведения движения.
                        end.x += (targetPoint.x - end.x)*.1;
                        end.y += (targetPoint.y - end.y)*.1;
                        // координата контрольной точки по X никогда меняться не будет
                        // а по Y будет всегда между начальной точкой (ноль) и координатой конечной точки.
                        // здесь ошибка, нужно было использовать bend
                        // control.y = end.y/2;
                        control.y = end.y*bend;
                        // перерисовываем
                        redraw();
                }
 
                private function onMoveToInitialPosition(event:Event):void {
                        // каждый кадр в режиме возврата в исходное положение
                        // шаг скорости движения в исходную позицию увеличивается на 1/100
                        // здесь тоже можно поиграться с параметром .1
                        speedX += (0 - targetPoint.x)*.01;
                        speedY += (-stickLength - targetPoint.y)*.01;
                        // и слегка гасится, чтобы колебания были затухающими
                        // колебания будут из-за того, что при движении к цели скорость будет увеличиваться, посте прохода цели начнет уменьшаться, пока шаг не сменится на противоположный по знаку.
                        // здесь тоже можно поиграться с параметром .96 (но несильно больше, max - 1, иначе пойдёт вразнос)
                        speedX *= .96;
                        speedY *= .96;
                        // смещаем целевую точку на шаг скорости
                        targetPoint.x += speedX;
                        targetPoint.y += speedY;
                        // двигаем конечную точку Безье на 1/10 расстояния к целевой точке
                        // здесь тоже можно поиграться с параметром .1
                        end.x += (targetPoint.x - end.x)*.1;
                        end.y += (targetPoint.y - end.y)*.1;
                        // контрольная точка будет посередине
                        // здесь ошибка, нужно было использовать bend
                        // control.y = end.y/2;
                        control.y = end.y*bend;
                        // перерисовываем
                        redraw();
                }
 
                private function initControlPoints():void {
                        // расставляем контрольные точки кривой
                        // по X все будут в нуле
                        end.y = -stickLength;
                        // здесь ошибка, нужно было использовать bend
                        // control.y = -stickLength/2;
                        control.y = end.y*bend;
                }
 
                private function redraw():void {
                        // перерисовка
                        graphics.clear();
                        // задаем стиль линии
                        graphics.lineStyle(4, 0x0000FF, 1);
                        // ставим карандаш на старт
                        graphics.moveTo(start.x, start.y);
                        // рисуем кривую безье.
                        graphics.curveTo(control.x, control.y, end.x, end.y);
                }
        }
}


N_Daemon 28.02.2009 22:45

Iv, а из каких соображений вот это все в двух классах. Это обязательное какое то условие? Я просто все что во флеше писал делал это во фла файле прям =).

Добавлено через 5 минут
Iv, благодарю для меня многое прояснилось =)


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

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