Рисование

Набросаем несколько классов для рисования прямоугольников. Тут интересно пару моментов.

Во-первых, посмотрим, как работать с необязательными параметрами функций и присваивать значения по умолчанию. Жаль, что haXe не поддерживает синтаксис:

function Some(param1:Int = 10, param2:String = 'Hello'):Void

Это общепринятый, простой и лакончный вариант. Но чего нет, того нет. (Полагаю, это из-за необходимости поддерживать совместимось с JavaScript, Neko, PHP и пр.)

Во-вторых, обратим внимание на один нюанс при рисовании границ векторных фигур. Допустим мы хотим создать прямоугольник размерами 100x100 пикселей с границей в10 пикселей. Если для рисования границы мы будем использовать lineStyle, то половина толщины этой границы наложится на прямоугольник, а вторая половина выйдет за его пределы. В результате, прямоугольник окажется толщиной 110x110 пикселей. А если граница имеет прозрачность, то будет заметно, как она накладывается. Полагаю, все это не то, что нам хотелось бы получить.

В данной ситуации нужно рисовать 5 прямоугольников. Один -- заливка, размером 80x80 пикселей. Остальные 4 - это границы. Причем прямоугольники не должны накладываться друг на друга, иначе при наличии прозрачности это будет заметно.

Итак, создаем пакет drawing и в нем три класса:

  • Fill.hx - определяет параметры заливки (цвет и прозрачность)
  • Border.hx - определяет параметры границы (цвет, прозрачность, толщина)
  • Rect.hx - непосредственно рисует прямоугольник

/**
 * @author Yzh
 *
 */

package drawing;

class Fill
{
        public var clr:         Int;
        public var alpha:       Float;

        public function new(?color:Int, ?alpha:Float)
        {
                this.clr = if(color != null) color else 0x0000ff;
                this.alpha = if(alpha != null) alpha else 0.9;
        }

        public function toString():String
        {
                return 'Fill [' + clr + ',' + alpha + ']';
        }
}

/**
 * @author Yzh
 *
 */

package drawing;

class Border extends Fill
{
        public var tn:  Int; //thickness

        public function new(?color:Int, ?alpha:Float, ?thickness:Int)
        {
                super(if(color != null) color else 0xff0000,
                        if(alpha != null) alpha else 1.0);
                this.tn = if(thickness != null) thickness else 1;
        }

        public function toString():String
        {
                return 'Border [' + clr + ',' + alpha + ',' + tn + ']';
        }
}

/**
 * @author Yzh
 *
 */

package drawing;

import flash.display.Graphics;

class Rect
{
        public var x:   Int;
        public var y:   Int;
        public var w:   Int;
        public var h:   Int;
        public var f:   Fill;
        public var b:   Border;

        public function new(?x:Int, ?y:Int, ?w:Int, ?h:Int)
        {
                this.x = if(x != null) x else 0;
                this.y = if(y != null) y else 0;
                this.w = if(w != null) w else 10;
                this.h = if(h != null) h else 10;
                this.f = new Fill();
                this.b = new Border();
        }

        public function Draw(context:Graphics):Void
        {
                var db:Int = b.tn * 2;

                context.beginFill(f.clr, f.alpha);
                context.drawRect(x + b.tn, y + b.tn, w - db, h - db);

                context.beginFill(b.clr, b.alpha);
                context.drawRect(x, y, w, b.tn);
                context.drawRect(x, y + h - b.tn, w, b.tn);
                context.drawRect(x, y + b.tn, b.tn, h - db);
                context.drawRect(x + w - b.tn, y + b.tn, b.tn, h - db);
                context.endFill();
        }

        public function toString():String
        {
                return 'Rect [' + x + ',' + y + ',' + w + ',' + h + ']';
        }
}

И чтобы протестировать эти классы, создадим основной класс приложения, их использующий.

/**
 * @author Yzh
 *
 */

package;

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.Graphics;

import drawing.Rect;
import drawing.Fill;
import drawing.Border;

class Main
{
        static public function main()
        {
                var root:Sprite = flash.Lib.current;
                root.stage.align = StageAlign.TOP_LEFT;
                root.stage.scaleMode = StageScaleMode.NO_SCALE;

                var g:Graphics = flash.Lib.current.graphics;

                var r:Rect = new Rect(20, 20, 280, 180);
                r.f = new Fill(0x336699, 0.5);
                r.b = new Border(0x833300, 0.5, 10);
                r.Draw(g);
        }
}

Играемся с параметрами, компилируем, любуемся.