Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   плавный Drag rotation (http://www.flasher.ru/forum/showthread.php?t=172968)

reQuiem 21.12.2011 04:00

плавный Drag rotation
 
Вложений: 1
Привет, пробую реализовать вращение объекта драгом.
Легко сделать, чтобы объект всегда следил за курсором, но мне нужно порционное движение при нажатой мышке.

Как когда пальцем крутишь пластинку на граммофоне.

Для этого напиал следующий код, но запутался, когда и что надо обновлять, подскажите, пожалуйста.

В интернете нашел только либо простые следящие драги, либо handle, которая по сути тоже просто прыгает на курсор при клике.

Попытался изобразить на схеме, что я делаю в коде.

В аттаче файл сцены.


[IMG]http://img440.**************/img440/9692/schemeh.jpg[/IMG]

Код AS3:

var CurX:Number=0;
var CurY:Number=0;
var GunX:Number=0;
var GunY:Number=0;
 
var lengthT:Number=0;
var heightT:Number=0;
 
var angleActual:Number=0;
var anglePast:Number=0;
var angle2rotate:Number=0;
 
 
 
 
GunX=round.x;
GunY=round.y;
 
 
var clicked:Boolean=false;
stage.addEventListener (MouseEvent.MOUSE_DOWN , mouseDownFunc);
 
function mouseDownFunc(e:MouseEvent):Boolean
{
        clicked=true;
 
        return clicked;
 
 
 
}
 
stage.addEventListener (MouseEvent.MOUSE_UP , mouseUpFunc);
 
function mouseUpFunc(e:MouseEvent):Boolean
{
        clicked=false;
 
        return clicked;
}
 
 
addEventListener(Event.ENTER_FRAME, frameUpdate);
function frameUpdate(e:Event):void 
{
        if(clicked)
        {
                lengthT=Math.floor(stage.mouseX-GunX);
                heightT=-(Math.floor(stage.mouseY-GunY));
 
                trace("lengthT",lengthT);
                trace("heightT",heightT);
 
                anglePast=angleActual;
                trace("anglePast",anglePast);
                angleActual=(Math.atan2(lengthT,heightT))*180/Math.PI;
                trace("аngleActual",angleActual);
                angle2rotate=angleActual-anglePast;
                trace("angle2rotate",angle2rotate);
                round.rotation+=angle2rotate;
 
        }
 
 
 
 
 
 
}


Спасибо!

t4arty 21.12.2011 04:22

http://xitri.com посмотрите тут, либо используйте уже написанные движки для физики.

ProxyGreen 21.12.2011 06:14

Хм как-то всё скомкано... Но всё-же стоит вычислять anglePast при нажатии кнопки, имхо подписываться лучше на MOUSE_MOVE, angleActual нужна как локальная переменная, не надо её хранить. Почему вы не берёте координаты на прямую у объекта? Что если он будет смещаться во время выполнения?

Обработчик будет выглядеть как-то так:
Код AS3:

function mouseMove(e:MouseEvent):void {
        var currentAng:Number = Math.atan2(mouseY - obj.y, mouseX - obj.x) * 180 / Math.PI;
        obj.rotation += currentAng - oldAng;
        oldAng = currentAng;
}

Обратите внимание, что вы не верно назначили параметры функции Math.atan2(y,x).
Если уж пишите в кадрах, не перемешивайте объявления функций с остальным кодом, вымораживает такое наблюдать, да и лучше не пишите код в кадрах вообще.

Alex Lexcuk 21.12.2011 13:55

Тут основная проблема определить в какую сторону надо вращать на данный момент, по часовой или против часовой, для себя я сделал класс, которым пользуюсь по мере необходимости.
Код AS3:

package  
{
        /**
        * ...
        * @author Lexcuk
        */

        public class Rad
        {
                public static var rx:Number = 0;
                public static var ry:Number = 0;
 
                public static const PI:Number = Math.PI;
                public static const PI2:Number = Math.PI + Math.PI;
                public static const PI_DIV_2:Number = Math.PI / 2;
 
 
                public static function rotPoint(ax:Number, ay:Number, rad:Number):void {
                        var cosrad:Number = Math.cos(-rad);
                        var sinrad:Number = Math.sin(-rad);
                        rx = ax * cosrad + ay * sinrad;
                        ry = ay * cosrad - ax * sinrad;
                }
 
                public static function getAngl(tx:Number, ty:Number):Number {
                        var res:Number = Math.atan2(tx, ty)+PI;
                        return -res;
                }
 
                public static function angCorrectRad(_ang:Number):Number {//корректор углов
                        if (_ang > -PI && _ang < 0) return _ang;
                        if (_ang < PI && _ang > 0) return _ang;
                        _ang = _ang % (PI2);
                        if (_ang > 0) {
                                if (_ang >= PI) _ang =  _ang - PI2;
                        }else {
                                if (_ang <= - PI) _ang = _ang + PI2;
                        }
                        return _ang;
                }
        }
 
}

Можно привязываться к этому классу, что бы всегда попадать в принятые рамки, как-то где минус угла -180, где плюс + 180 градусов, и как воспринимать угол 1340 градусов, или радианов. Как пользоваться.
Код AS3:

package  
{
        import flash.display.*;
        import flash.events.*;
        import flash.geom.*;
        import flash.text.*;
 
 
        /**
        * ...
        * @author Lexcuk
        * http://murmadillo.tut.su/m/rad-doc.swf
        */

        public class Doc extends Sprite
        {
                private var turSp:Sprite;
 
                private var turX:Number = 200;
                private var turY:Number = 150;
 
                private var curRad:Number = 0;
                private var targetRad:Number = 0;
                private var radStep:Number = 0.1;
 
                public function Doc()
                {
                        addChild(turSp = new Sprite());
                        turSp.graphics.lineStyle(1, 0x000000);
                        turSp.graphics.drawCircle(0, 0, 2);
                        turSp.graphics.drawCircle(0, 0, 50);
                        turSp.graphics.lineStyle(3, 0xFF0000);
                        turSp.graphics.drawCircle( 0, -60, 5);
                        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
                }
 
                private function enterFrameHandler(e:Event):void {
                        targetRad = Rad.angCorrectRad(Rad.getAngl(stage.mouseX - turX, stage.mouseY - turY));
                        curRad = Rad.angCorrectRad(curRad);
 
                        var minusRad:Number = Rad.angCorrectRad(targetRad - curRad);
 
                        if (Math.abs(minusRad) > Math.PI) {
                                minusRad = - Rad.angCorrectRad(curRad - targetRad);
                        }
 
                        if (Math.abs(minusRad) > radStep) {
                                if (minusRad > 0) curRad += radStep; else curRad -= radStep;
                        } else curRad = targetRad;
 
                        var m:Matrix = turSp.transform.matrix;
                        m.identity();
                        m.rotate(curRad);
                        m.translate(turX, turY);
                        turSp.transform.matrix = m;
                }
 
 
        }
 
}

Демо http://murmadillo.tut.su/m/rad-doc.swf
На буржуйском форуме эта штука понравилась
http://www.kirupa.com/forum/showthre...oblem-of-enemy

А вом надо при нажатии мыши ну так можно на событие нажатия кнопки мыши добавлять enterFrame, а при отпусканиии удалять enterFrame слушатель.

artcraft 21.12.2011 17:01

вот игра в утку http://artcraft.cz/fun/duck.html

там нет поясания, но задача такова:
есть круглое озеро с голодной уткой
и лиса на берегу, которая бегает ровно в 4 раза быстрее чем плавает утка,
утке надо попасть на берег и поесть там травы, урвав момент когда рядом нет лисы,
но лиса не спит и изо всех сил пытается подловить утку на берегу

могу поискать исходник, если надо

reQuiem 22.12.2011 02:19

Вложений: 1
t4arty

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


ProxyGreen

Да, но вы написали просто более аккуратный вариант моего кода, в этом случае при клике все равно объект ориентируется на курсор.

Спасибо я у себя поправил с вашими рекомендациями, но проблема осталась.

Мне нужно вращать объект за любое место на столько градусов сколько составило отклонение от начала драга до текущего момента.

Мб а вас не до конца понял? вот мой текущий код.

Код AS3:

var anglePast:Number=round.rotation;
 
var clicked:Boolean=false;
 
stage.addEventListener (MouseEvent.MOUSE_DOWN , mouseDownFunc);
stage.addEventListener (MouseEvent.MOUSE_UP , mouseUpFunc);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveFunc);
 
function mouseDownFunc(e:MouseEvent):Boolean
{
        clicked=true;
        return clicked;
}
 
function mouseUpFunc(e:MouseEvent):Boolean
{
        clicked=false;
        return clicked;
}
 
function mouseMoveFunc(e:MouseEvent):void
{
        if(clicked)
        {       
                var currentAng:Number = Math.atan2(mouseY - round.y, mouseX - round.x) * 180 / Math.PI;
                round.rotation += currentAng - anglePast;
                anglePast = currentAng;
        }
}

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



Alex Lexcuk
artcraft


Спасибо, но вы не совсем верно меня поняли. У меня сейчас уже объект ловит правильные градусы но глобально - Повернуть от 0 до текущего угла курсора.
А мне надо угол объекта увеличить на разность между углом курсора на начало драга и углом курсора на текущий момент.

ProxyGreen 22.12.2011 03:18

Цитата:

Мб а вас не до конца понял?
Омг. да таки не до конца поняли.
Вот что я имел ввиду:
Код AS3:

        var anglePast:Number;      //подумайте над названиями переменных, да это тоже важно
            var clicked:Boolean=false; // старайтесь использовать по возможности естественные условия
 
            stage.addEventListener (MouseEvent.MOUSE_DOWN , mouseDownFunc);
            stage.addEventListener (MouseEvent.MOUSE_UP , mouseUpFunc);
 
            function mouseDownFunc(e:MouseEvent):Boolean
            {
                //стоит вычислять anglePast при нажатии кнопки, ага
                anglePast = mouseAng(round);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveFunc);
 
            }
            function mouseUpFunc(e:MouseEvent):Boolean
            {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveFunc);
            }
 
            function mouseMoveFunc(e:MouseEvent):void
            {
                var currentAng:Number = mouseAng(round);
                round.rotation += currentAng - anglePast;
                anglePast = currentAng;
            }
 
            function mouseAng(obj:DisplayObject):Number{
                //все типичные и часто повторяющиеся операции выносите
                //в отдельные функции
                return Math.atan2(mouseY - obj.y, mouseX - obj.x) * 180 / Math.PI;
            }

Цитата:

А в кадре ну просто так быстрее набросать было пример. Потом естественно все будет в классе.
Избегать кода в IDE нужно хотя-бы из-за отсутствия там вменяемого автокомплита, использовали-бы нормальный редактор, досадных ошибок с тем-же Math.atan2() просто не было бы.

Wolsh 22.12.2011 08:48

Цитата:

//все типичные и часто повторяющиеся операции выносите
//в отдельные функции
Я бы еще добавил – а все константы типа (180 / Math.PI) вычислять один раз, а не делать одно и то же вычисление с обращением к другому классу 100 раз на одно короткое движение.

reQuiem 22.12.2011 11:10

Большое спасибо!
Все учту.

lovik 22.12.2011 12:20

доброго времени суток
Если вас не затруднит распишите подробно формулу вычисления угла поворота объекта в зависимости от положения мыши и что надо увеличивать по событию ентер фрейм чтоб оно двигалось поскольку чет у меня нечего не получается

заранее спасибо


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

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