mieki256's diary



2013/08/31() [n年前の日記]

#1 [haxe] Haxe+OpenFLでハマった

Haxe + OpenFL で、svg 表示ができるかどうかが気になって試していたのだけど、ハマってしまったり。全然すんなり行かない…。

結論から言うと、svgの内容によっては、一応表示できなくもない感じ。ただし、いくつか注意点がありそう。 要するに、HTML5用に出力すると、ハマります。svgをブラウザで直接開くと、まともに表示されるので、svgがおかしいというわけではないのだろうけど…。

ちなみに、Inkscape で svg を作ってたのだけど。その場合、以下の点に注意して作業・保存したほうが良いかもしれず。 とにかく一発で表示できず、何度も修正・保存形式を変えて試してみる羽目に。どう考えても、ビットマップ化して表示したほうが、余計なトラブルに遭遇せずに済みそう…。

Haxe + OpenFL上で、svg表示を可能にするライブラリ?は、gm2d/svg と haxenme/svg の2種類があるようで。前者を試したらエラーが出て解決できなかったので、後者で試した。

haxelib.exe を使って、いくつかライブラリをインストールする必要あり。
haxelib.exe install format
haxelib.exe install svg
haxelib.exe install swf
最後のは要らないかもしれないけど、念のため入れてみたり。

application.xml
<?xml version="1.0" encoding="utf-8"?>
<project>
    <!-- NMML reference: https://gist.github.com/1763850 -->
    
    <!-- metadata, make sure 'package' is at least 3 segments (ie. com.mycompany.myproject) -->
    <meta title="haxe_openfl_svg_disp_test" package="haxeopenflsvgdisptest" version="1.0.0" company="mieki256" />
    
    <!-- output -->
    <app main="Main" file="haxeopenflsvgdisptest" path="bin" />
    
    <window background="#FFFFFF" fps="60" />
    <window width="640" height="360" unless="mobile" />
    <window orientation="landscape" vsync="false" antialiasing="4" if="cpp" />
    
    <!-- classpath, haxe libs -->
    <source path="src" />
    <!--
    <haxelib name="gm2d" />
    -->
    <haxelib name="format" />
    <haxelib name="svg" />
    <haxelib name="openfl" />
    <haxelib name="actuate" />
    
    <!-- assets -->
    <icon path="assets/openfl.svg" />
    <assets path="assets/img" rename="img" />
    
    <!-- optimize output
    <haxeflag name="-dce full" /> -->
    
</project>

Main.hx
package ;

import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.Lib;
import openfl.Assets;

import format.SVG;

//import gm2d.svg.Svg;
//import gm2d.reso.Resources;
//import gm2d.svg.SvgRenderer;

/**
 * SVG display test. use haxenme/svg
 * @author mieki256
 */

class Main extends Sprite 
{
    var inited:Bool;
    var bg:Sprite;
    var count:Int;

    /* ENTRY POINT */
    
    function resize(e) 
    {
        if (!inited) init();
        // else (resize or orientation change)
    }
    
    function init() 
    {
        if (inited) return;
        inited = true;

        // (your code here)
        
        // Stage:
        // stage.stageWidth x stage.stageHeight @ stage.dpiScale
        
        // Assets:
        // nme.Assets.getBitmapData("img/assetname.jpg");

        // svg setting
        var svg = new SVG(Assets.getText("img/bg.svg"));
        var shape = new Shape();
        svg.render(shape.graphics);
        shape.cacheAsBitmap = true;
        
        //var svg = new SvgRenderer(Resources.loadSvg("img/bg.svg"));
        //var shape = svg.createShape();
        //shape.cacheAsBitmap = true;
        
        bg = new Sprite();
        this.addChild(bg);
        bg.addChild(shape);
        shape.x = -320;
        shape.y = -180;
        bg.x = 320;
        bg.y = 180;
        
        this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        count = 0;
    }
    
    private function onEnterFrame(e:Event):Void
    {
        //bg.rotation = 20 * Math.cos((count * 4) * Math.PI / 180.0);
        count++;
    }

    /* SETUP */

    public function new() 
    {
        super();    
        addEventListener(Event.ADDED_TO_STAGE, added);
    }

    function added(e) 
    {
        removeEventListener(Event.ADDED_TO_STAGE, added);
        stage.addEventListener(Event.RESIZE, resize);
        #if ios
        haxe.Timer.delay(init, 100); // iOS 6
        #else
        init();
        #end
    }
    
    public static function main() 
    {
        // static entry point
        Lib.current.stage.align = flash.display.StageAlign.TOP_LEFT;
        Lib.current.stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
        Lib.current.addChild(new Main());
    }
}

以下の3行が肝心の部分、なのかな。
        var svg = new SVG(Assets.getText("img/bg.svg"));
        var shape = new Shape();
        svg.render(shape.graphics);

SVG表示の不具合について。 :

以下の画像のような感じになる。

グラデーションの色がおかしくなる件。

Flash ... OK。
Haxe + OpenFL + Flash

Neko ... OK。
Haxe + OpenFL + Neko

HTML5 ... NG。色がおかしい。
Haxe + OpenFL + HTML5


ストロークが入っていると表示がおかしくなる件。

Flash ... OK。
Haxe + OpenFL + Flash

Neko ... OK。
Haxe + OpenFL + Neko

HTML5 ... NG。ストロークが無いはずの部分にまでストロークがついている。
Haxe + OpenFL + HTML5

マウス座標の取得でハマったり。 :

画像を表示してマウスカーソルを追いかける、という処理を試しに書いていたのだけど。 Flash や Neko上ではすんなりと正常動作したものの、HTML5上ではうんともすんとも反応しなくてハマったり。

Spriteのプロパティ値を疑って、半日ほどアレコレ試していたけど。そこではなくて、マウス座標がそもそも取得できてない場面があったのが原因だった。undefined だか NaN だかの値をマウス座標として得てしまった際に、Sprite の x座標にもその値が入ってしまって、その後も、その計算不能な値を使って計算しようとするから、ずっと計算できずにピクリとも動かなくなっていた。

Main.hx
package ;

import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.Lib;
import flash.text.TextField;
import openfl.Assets;

/**
 * OpenFLテスト。マウスカーソルを画像が追いかける。
 * @author mieki256
 */

class Main extends Sprite 
{
    var inited:Bool;
    var spr:Sprite;
    var bmp:Bitmap;
    var tf:TextField;
    var mousex:Float;
    var mousey:Float;

    /* ENTRY POINT */
    
    function resize(e) 
    {
        if (!inited) init();
        // else (resize or orientation change)
    }

    /**
     * 初期化処理
     */
    function init() 
    {
        if (inited) return;
        inited = true;

        mousex = 320;
        mousey = 180;
        
        // 画像を描画
        spr = new Sprite();
        bmp = new Bitmap(Assets.getBitmapData("img/chara.png"));
        bmp.x = - bmp.width / 2;
        bmp.y = - bmp.height / 2;
        spr.addChild(bmp);
        Lib.current.addChild(spr);
        
        // 文字列を描画
        tf = new TextField();
        tf.selectable = false;
        tf.width = 640;
        tf.height = 48;
        tf.textColor = 0x333333;
        tf.text = "start";
        Lib.current.addChild(tf);

        // ステージ上でマウスが動いた際のイベントを登録
        Lib.current.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        
        // 毎フレームの処理を登録
        this.addEventListener(Event.ENTER_FRAME, mainUpdate);
    }
    
    /**
     * マウスカーソルが動いた時の処理
     * @param   event
     */
    function onMouseMove(event:MouseEvent):Void
    {
        mousex = event.stageX;
        mousey = event.stageY;
    }
    
    /**
     * メインループ部分相当
     * @param   e
     */
    private function mainUpdate(e:Event):Void
    {
        var mx:Float;
        var my:Float;

        // マウス座標を取得
        switch (1) {
            case 0:
                // html5上でも動く。
                mx = mouseX;
                my = mouseY;
            case 1:
                // html5上でも動く。
                mx = mousex;
                my = mousey;
            default:
                // html5上では動かない。Flash や Neko では動く。
                mx = Lib.current.stage.mouseX;
                my = Lib.current.stage.mouseY;
        }

        // キャラクタ画像が、マウスカーソルを追いかける処理
        var spd:Float = 0.04;
        var dx:Float = (mx - spr.x) * spd;
        var dy:Float = (my - spr.y) * spd;
        spr.x = spr.x + dx;
        spr.y = spr.y + dy;
        
        tf.text = 'mouse x,y = $mx, $my';
        //tf.text = 'spr x,y = ${spr.x}, ${spr.y}';
    }
    
    /* SETUP */

    public function new() 
    {
        super();    
        addEventListener(Event.ADDED_TO_STAGE, added);
    }

    function added(e) 
    {
        removeEventListener(Event.ADDED_TO_STAGE, added);
        stage.addEventListener(Event.RESIZE, resize);
        #if ios
        haxe.Timer.delay(init, 100); // iOS 6
        #else
        init();
        #end
    }

    public static function main() 
    {
        // static entry point
        Lib.current.stage.align = flash.display.StageAlign.TOP_LEFT;
        Lib.current.stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
        Lib.current.addChild(new Main());
    }
}

以上です。

過去ログ表示

Prev - 2013/08 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project