Рисование

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

Во-первых, посмотрим, как работать с необязательными параметрами функций и присваивать значения по умолчанию. Жаль, что 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);
        }
}

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

Комментарии

PHP?

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

А еще в классе Border надо добавить "override":

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

Время идет, всё меняется

Все работает, без проблем ...
Жаль, что haXe не поддерживает синтаксис:

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

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

Пример:

class Test {

        static function Hello(str:String = "Hello haXe", i:Int = 100){
                var j;
                for( j in 0...i ) trace( str + " > " +j);
        }
               
        public static function main(){
               
                Hello();
        }        
}

Немного не в

Немного не в тему, но не могу разобраться. Пожалуйста, помогите.
Во FlashDevelop (версия 3.0.3) создаю пакет drawing и Ваши классы. Все замечательно работает и рисуется.

Теперь привожу код класса Main к такому виду:

package;

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

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);
               
                var mc : flash.display.MovieClip = flash.Lib.current;
                var tf : flash.text.TextField;
        mc.beginFill(0xFF0000);
        mc.moveTo(50,50);
        mc.lineTo(100,50);
        mc.lineTo(100,100);
        mc.lineTo(50,100);
        mc.endFill();
               
                        tf = flash.Lib.current.createTextField("tf",0,5,flash.Stage.height - 25,flash.Stage.width-10,20);
                tf.type = "input";
                tf.border = true;
                tf.background = true;
                tf.backgroundColor = 0xEEEEEE;
                               
        }
}

После Project - Build project получаю в results:
E:\web-проекты\Flash проекты\drawing\src/Main.hx:38: characters 51-69 : Class not found : flash.Stage
E:\web-проекты\Flash проекты\drawing\src/Main.hx:39: characters 2-19 : String should be flash.text.TextFieldType

Насчет первой ошибки понятно, что класс flash.Stage не найден. Со второй ошибкой уже сложнее.
В связи с этими ошибками становится не ясно, почему вот этот код (он так и записан в файле - дословно, ничего не пропущено) прекрасно компилируется в swf-файл и работает:

class Test {
    static function main() {
        var mc : flash.MovieClip = flash.Lib.current;
                var tf : flash.TextField;
        mc.beginFill(0xFF0000);
        mc.moveTo(50,50);
        mc.lineTo(100,50);
        mc.lineTo(100,100);
        mc.lineTo(50,100);
        mc.endFill();
               
                        tf = flash.Lib.current.createTextField("tf",0,5,flash.Stage.height - 25,flash.Stage.width-10,20);
                tf.type = "input";
                tf.border = true;
                tf.background = true;
                tf.backgroundColor = 0xEEEEEE;
    }
}

А компилятор ведь у FlashDevelop такой же, что и я вызываю вручную... Так почему один и тот же код в одном случае вызывает ошибки, а в другом - нет? И как надо писать, чтобы компилятор вел себя предсказуемо?

override

class Border extends Fill
{
        . . .
        public override function toString():String  //  компилятор говорит надо override
        {
                return 'Border [' + clr + ',' + alpha + ',' + tn + ']';
        }
}

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <blockcode> <dd>
  • Строки и параграфы переносятся автоматически.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>.

Подробнее о форматировании

CAPTCHA
Этот вопрос помогает предотвратить автоматический спам
Image CAPTCHA
Enter the characters shown in the image without spaces, also respect upper and lower case.
To prevent automated spam submissions leave this field empty.