Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Линии и MouseEvent. Нужна помощь (http://www.flasher.ru/forum/showthread.php?t=183467)

Snopka 22.08.2012 21:30

Линии и MouseEvent. Нужна помощь
 
Уважаемые флешеры, помогите пожалуйста в реализации вот такой вот вещи.

Есть сетка AxB, координаты пересечений линий выводил с помощью trace, то есть они есть. Нужно что бы можно было кликами создавать линии как показано на скриншоте. Линии должны накладываться только поверх линий сетки, длина - максимум до соседнего пересечения. Возможно ли такое? Если да, то как такое реализовать. Заранее благодарю.
[IMG]http://s2.************/uploads/20120822/R2SgLVUm.png[/IMG]

MINASTIS 22.08.2012 21:46

Кликами? В смысле рисовать мышкой линии от координат x1,y1 до координат x2,y2?

Snopka 22.08.2012 21:51

Да, именно так

MINASTIS 22.08.2012 21:59

Так это же просто. При одном клике взять координаты мыши, при втором взять вторые и нарисовать линию с ними.

Snopka 22.08.2012 22:03

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

MINASTIS 22.08.2012 22:08

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

Snopka 22.08.2012 22:24

Сделаю наверное невидимые кнопки на сетке

olexandr 23.08.2012 02:55

банально делить с округлением
знаем, что ширина ячейки 10, клик сделали в позиции 23 - получим, Math.round(23 / 10) = 2 * 10 = 20;

Isfet 23.08.2012 06:35

можно сделать допустим каждую линию классом, которая будет при нажатии менять свой цвет, и циклом их расставить по картинке

ChuwY 23.08.2012 13:13

Вложений: 2
Можно как-то вот так. [см ниже]
Не спорю с тем, что можно сделать проще (наверное) и оптимальнее (точно) , но для примера вполне пойдет:

P.S. Только что понял, что не очень-то понял задачу.
Тов. Snopka, объясните подробнее, как себя должны вести линии при различных условиях. И как вообще строиться.

Код:

LineSegment.as
Код AS3:

package gridExample.grid
{
        import flash.geom.Point;
 
        /**
        * Класс модели отрезка.
        * Координаты конца и начала -- координаты сетки, а не дисплейные
        * @author chu
        */

        public class LineSegment
        {
                private var _start : Point;
                private var _end : Point;
                private var _color : uint;
                public function LineSegment(start : Point, end : Point, color : uint = 0x0)
                {
                        _start = start;
                        _end = end;
                        _color = color;
                }
 
                //***  public ***//
                public function get start():Point
                {
                        return _start;
                }
 
                public function get end():Point
                {
                        return _end;
                }
 
                public function get color():uint
                {
                        return _color;
                }
 
                public function set color(value : uint):void
                {
                        _color = value;
                }
 
                public function hasCoincidence(start : Point, end : Point):Boolean
                {
                        return hasDirectCoincidence(start, end) || hasDirectCoincidence(end, start);
                }
 
                //*** private ***//
                private function hasDirectCoincidence(start : Point, end : Point):Boolean
                {
                        return this.start.equals(start) && this.end.equals(end)
                }
        }
}


Код:

Grid.as
Код AS3:

package gridExample.grid
{
        import flash.display.Graphics;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.geom.Point;
 
        public class Grid extends Sprite
        {
                private static const CELL_SIZE : uint = 70;
                private static const BG_FILL_COLOR : uint = 0xAAAAAA;
                private static const BG_LINES_COLOR : uint = 0x555555;
                private static const BG_LINES_THICKNESS : Number = 2;
                private static const BG_BORDER_THICKNESS : Number = 6;
                private static const CELL_COLOR : uint = 0xFFFFFF;
                private static const SEGMENTS_LINE_THICKNESS : uint = 4;
                private static const COLLISED_PREVIEW_ALPHA : Number = 0.5;
                private static const DEFAULT_ALPHA : Number = 1;
                // model
                private var _rows : uint;
                private var _cols : uint;
                private var _currentColor : uint;
                private var _allowReplacing : Boolean;
                private var _segments : Vector.<LineSegment> = new Vector.<LineSegment>();
                private var _currentSegment : LineSegment;
                // subview
                private var _bg : Shape;
                private var _linesContainer : Shape;
                public function Grid()
                {
                        getControls();
                }
 
                //*** public ***//
                public function clearLines():void
                {
                        _segments.splice(0, _segments.length);
                        _linesContainer.graphics.clear();
                }
 
                public function setSize(cols : uint, rows : uint):void
                {
                        _rows = rows;
                        _cols = cols;
                        drawBg();
                        drawSegments();
                }
 
                public function setCurrentColor(color : uint):void
                {
                        _currentColor = color;
                }
 
                public function setAllowReplacing(value : Boolean):void
                {
                        _allowReplacing = value;
                }
 
                public function buildLine(x : Number, y : Number, preview : Boolean = false):void
                {
                        var col : int = Math.floor(x/CELL_SIZE);
                        var row : int = Math.floor(y/CELL_SIZE);
                        var segment : LineSegment;
 
                        if(hasOutside(col, row))
                        {
                                return;
                        }
 
                        segment = getNearestSegment(x, y);
                        handleNewSegment(segment, preview);
 
                        drawSegments();
                }
 
                //*** private ***//
                private function hasSlotBused(segment : LineSegment):Boolean
                {
                        var oldSegment : LineSegment = getSegmentByPosition(segment.start, segment.end);
                        return oldSegment != null;
                }
 
                private function handleNewSegment(segment : LineSegment, preview : Boolean):void
                {
                        var isBusy : Boolean = hasSlotBused(segment);
 
                        if(preview || (isBusy && !_allowReplacing))
                        {
                                _currentSegment = segment;
                                return;
                        }
 
                        if(isBusy && _allowReplacing)
                        {
                                getSegmentByPosition(segment.start, segment.end, true);
                        }
                        _segments.push(segment);
                }
 
                private function getSegmentByPosition(start : Point, end : Point, remove : Boolean = false):LineSegment
                {
                        var numSegments : uint = _segments.length;
                        while(numSegments--)
                        {
                                var segment : LineSegment = _segments[numSegments];
                                if(segment.hasCoincidence(start, end))
                                {
                                        if(remove)
                                        {
                                                _segments.splice(numSegments, 1);
                                        }
                                        return segment;
                                }
                        }
                        return null;
                }
 
                /**
                * Возвращает вектор нормали от указанной точки до ближайшего отрезка
                * пикселы
                */

                private function getNormal(x : uint, y : uint):Point
                {
                        var xLen : Number = x - Math.round(x/CELL_SIZE)*CELL_SIZE;
                        var yLen : Number = y - Math.round(y/CELL_SIZE)*CELL_SIZE;
                        var isVert : Boolean = Math.abs(yLen) < Math.abs(xLen);
                        var dirX : Number = isVert ? 0 : xLen;
                        var dirY : Number = isVert ? yLen : 0;
 
                        return new Point(dirX, dirY);
                }
 
                private function getNearestSegment(x : uint, y : uint):LineSegment
                {
                        var normal : Point = getNormal(x, y);
                        var startX : uint;
                        var startY : uint;
                        var endX : uint;
                        var endY : uint;
 
                        if(normal.x)
                        {
                                startX = (x - normal.x)/CELL_SIZE;
                                startY = Math.floor(y/CELL_SIZE);       
                                endX = startX;
                                endY = Math.ceil(y/CELL_SIZE);
                        }
                        else
                        {
                                startX = Math.floor(x/CELL_SIZE);       
                                startY = (y - normal.y)/CELL_SIZE;
                                endX = Math.ceil(x/CELL_SIZE);
                                endY = startY;
                        }
 
                        return new LineSegment(new Point(startX, startY), new Point(endX, endY), _currentColor);
                }
 
                private function getControls():void
                {
                        _bg = new Shape();
                        addChild(_bg);
 
                        _linesContainer = new Shape();
                        addChild(_linesContainer);
                }
 
                private function drawSegments():void
                {
                        var graph : Graphics = _linesContainer.graphics;
 
                        graph.clear();
 
                        for each(var segmentParam : LineSegment in _segments)
                        {
                                drawSegment(segmentParam, graph);
                        }
                        if(_currentSegment)
                        {
                                var isCollision : Boolean = hasSlotBused(_currentSegment);
                                var alpha : Number = isCollision ? COLLISED_PREVIEW_ALPHA : DEFAULT_ALPHA;
                                drawSegment(_currentSegment, graph, alpha);
                        }
                }
 
                private function drawSegment(segment : LineSegment, graph : Graphics, alpha : Number = DEFAULT_ALPHA):void
                {
                        // ячейки
                        var start : Point = segment.start;
                        var end : Point = segment.end;
 
                        //проверка на вхождение отрезка в зону отображения
                        if(hasPointOutside(start) || hasPointOutside(end))
                        {
                                return;
                        }
 
                        // пикселы
                        var startX : uint = start.x * CELL_SIZE;
                        var startY : uint = start.y * CELL_SIZE;
                        var endX : uint = end.x * CELL_SIZE;
                        var endY : uint = end.y * CELL_SIZE;
 
                        graph.lineStyle(SEGMENTS_LINE_THICKNESS, segment.color, alpha);
                        graph.moveTo(startX, startY);
                        graph.lineTo(endX, endY);
                }
 
                private function hasPointOutside(point : Point):Boolean
                {
                        return hasOutside(point.x, point.y);
                }
 
                private function hasOutside(col : Number, row : Number):Boolean
                {
                        return (col < 0) || (col > _cols) || (row < 0) || (row > _rows);
                }
 
                private function drawBg():void
                {
                        var graph : Graphics = _bg.graphics;
                        var width : uint = CELL_SIZE * _cols;
                        var height : uint = CELL_SIZE * _rows;
 
                        graph.clear();
 
                        // бордюр и фон
                        graph.beginFill(BG_FILL_COLOR);
                        graph.lineStyle(BG_BORDER_THICKNESS, BG_LINES_COLOR);
                        graph.drawRect(0, 0, width, height);
 
                        // остальные линии
                        graph.endFill();
                        graph.lineStyle(BG_LINES_THICKNESS, BG_LINES_COLOR);
 
                        for(var col : uint = 1; col < _cols; col++)
                        {
                                var currentX : uint = CELL_SIZE * col;
                                graph.moveTo(currentX, 0);
                                graph.lineTo(currentX, height);
                        }
                        for(var row : uint = 1; row < _rows; row++)
                        {
                                var currentY : uint = CELL_SIZE * row;
                                graph.moveTo(0, currentY);
                                graph.lineTo(width, currentY);
                        }
                }
        }
}

Остальное в приложенных исходниках.
Результат примерно такой:


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

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