c++ 读取 flash AIR NativeAplication 参数

c++ read flash AIR NativeAplication arguments

Hy 我制作了一个 AIR 应用程序,它使用 flash.desktop.NativeProcess 来启动 c++ a* 路径求解器。原因是 - Flash 需要太多时间来解决 250 * 250 开放网格。

A​​IR 应用程序很好。它可以启动c++ exe文件 exe 可以独立运行

问题是。它们不能成对工作 :(

当 flash 发送参数时,c++ 部分静静地死去

char buf[ 256 ]; std::cin.getline( buf, 256 );

我只是没有设法找到正在发生的事情。如果我使用参数而不是标准输入,我会得到一些奇怪的字符。任何的想法 ?

丑陋的 hack,但确实有用 :D

var f = File.documentsDirectory.resolvePath("command.txt"); 
var stream = new FileStream();
stream.open(f, FileMode.WRITE);  
stream.writeUTFBytes(nextQuery.command + "/" + nextQuery.data);
stream.close();

你可以猜到c++端

std::stringstream strmap;
strmap << my_documents << "/command.txt" ;
std::ifstream myfile (strmap.str().c_str());

我称之为

black market algorytm

那好吧。您将在下面找到有效的(此外,工作速度很快)波浪寻路演示。有两个测试用例:

  • 32x32 预先设计的地牢,循环 256 次,运行 0.12 秒 - 0.13 秒
  • 320x320大,空,入口和出口在对角,运行0.03s - 0.04s

所以,教程和算法的问题是它们非常适合干净的小教程案例。当有很多数据时,好吧,不是那么多。如果您按照该教程进行操作,它会给您留下 Node class of getters 和 setters。每次引用 getter 或 setter 时,都会调用一个函数调用,这是一个比较繁重的操作。一次、十次、一百次——没问题,但是你有 64K 个这样的节点,这建立了性能动力。即使你没有去 getter/setter 图片,仍然有很多节点实例,你拉他们的属性......你得到图片,对吧?

当我在 2009 年第一次进行波浪寻路时,我也犯了错误,陷入了节点实例及其属性的混乱之中。然后是二维整数数组,不行。然后我想到了 BitmapData class,它可以完全代表地图并为每个 cell/pixel 保存 32 位数据。每一个想法都证明还是太慢了。

我可能会更快地想到一维表示,但事实是,我使用六边形贴图,所以每个单元格都有 6 条出路,而不仅仅是 4 条,有点令人困惑。

然而,最后,我想出了将区域映射到一维数组并使用 +1- 导航的整个想法1+width-width 位移(好吧,还有 2 个用于六边形地形)。那时我不需要复杂的东西(我认为你也不需要它们),比如路径权重,只是为了在用户体验可接受的时间范围内找到最短路径。

如果你看一下算法寻路部分,它是如此简单。没有 xy 坐标。没有边境检查。没有节点对象,没有属性,没有额外的函数调用。每个单元只有最简单的数学和一些操作——尽可能少。这就是它如此快速和高效的原因。

提到的Logclass,大家可以到my repo.

获取
package
{
    import flash.utils.getTimer;
    import flash.display.Sprite;
    import ru.delimiter.utils.Log;

    /**
     * ...
     * @author Dmitry Yamaykin
     */

    public class PathFinding extends Sprite
    {
        public function PathFinding() 
        {
            super();

            // Log is a debug output panel which allows you
            // to see things if traces are unavailable
            // or/and suppressed by the release build.
            Log.create(this, true);
            Log.log("[PathFinding] starts!");

            testBig();
            testSmall();
        }

        // The main data array that keeps obstacles,
        // empty cells and those already passed by the wave.
        private var map:Vector.<int> = new Vector.<int>;

        // The front of the wave and the next front.
        private var wave:Vector.<int> = new Vector.<int>;
        private var froth:Vector.<int> = new Vector.<int>;

        // Mapping the map back to the original data. Just for
        // this demo, you probably won't need it with the real thing.
        private var route:Vector.<int> = new Vector.<int>;

        // Be extra careful with the 'w' argument, if you fumble with
        // the width of the row, the whole thing will totally go astray.
        private function findPath(source:Array, w:int, h:int):Array
        {
            var length:int = source.length;
            var begin:int;
            var end:int;
            var i:int;

            var steps:int;
            var windex:int;
            var findex:int;
            var mindex:int;

            map.fixed = false;
            wave.fixed = false;
            froth.fixed = false;
            route.fixed = false;

            // The brilliance of it: working with just a few instances
            // that are set up in the very beginning and fixed to a
            // certain amount of memory. No memory management while
            // finding paths, no creating and disposing of instances,
            // no Garbage Collector to kick in and do its thing.

            map.length = length;
            wave.length = w + h;
            froth.length = w + h;
            route.length = length;

            map.fixed = true;
            wave.fixed = true;
            froth.fixed = true;
            route.fixed = true;

            // The main idea behind fast wave is mapping the source
            // 2-dimensional data into 1-dimensional array of int
            // values. Your position is indicated by a single
            // index, +1 is 'go right', -1 is 'go left',
            // +width and -width are 'go down' and 'go up' respectively.
            // Just don't forget to add a solid impassable top and bottom
            // lines (to avoid 'out of range' array errors) and a solid
            // wall at the right (at least) so you don't flip over the
            // data while going right from the rightmost position
            // and left from the leftmost. It's far more efficient this
            // way than additional code checks for borders.

            for (i = 0; i < length; i++)
            {
                switch (source[i])
                {
                    case '.':
                        map[mindex] = 0;
                        route[mindex] = i;

                        mindex++;
                        break;

                    case '#':
                        map[mindex] = -1;
                        route[mindex] = i;

                        mindex++;
                        break;

                    case 'X':
                        map[mindex] = -1;
                        route[mindex] = i;
                        end = mindex;

                        mindex++;
                        break;

                    case 'Y':
                        // We need it to be passable
                        // for wave to wash in there.
                        map[mindex] = 0;
                        route[mindex] = i;
                        begin = mindex;

                        mindex++;
                        break;
                }
            }

            // Be careful with logging. It duplicates the output to the
            // standard trace, which includes writing to a file
            // (Flash thing, not my fault) which is really,
            // like REALLY slow operation to do.

            // Log.log(begin, '>', end);

            // With just fixed [1, -1, w, -w] it will work a bit faster,
            // bit the algorithm will prefer going in the straight lines,
            // rather than wandering in diagonals and cutting the corners.

            var AWX:int = 0;
            var AWAY:Array;
            var WAYS:Array =
            [
                [1, -1, w, -w],
                [w, -w, 1, -1],
                [-1, w, 1, -w],
                [-w, 1, w, -1],

                [1, -1, -w, w],
                [w, -w, -1, 1],
                [-1, 1, -w, w],
                [w, -w, -1, 1],

                [1, w, -1, -w],
                [w, -1, -w, 1],
                [-1, 1, w, -w],
                [-w, w, 1, -1],

                [1, -w, -1, w],
                [w, 1, -w, -1],
                [-1, -w, 1, w],
                [w, -1, -w, 1],
            ];

            // Lets the party begin.
            wave[0] = end;
            windex = 1;

            // Repeat while wave front is not empty.
            while (windex)
            {
                // Pick the next pattern of motion preferences.
                if (--AWX < 0) AWX = WAYS.length - 1;

                AWAY = WAYS[AWX];

                // Go through all the points on the current wave front.
                while (windex--)
                {
                    var anindex:int = wave[windex];

                    // Try to move into the all
                    // possible directions from it.
                    for each (var ashift:int in AWAY)
                    {
                        // This value will be used a few times
                        // so it's better to calculate it once and store.
                        var awindex:int = anindex + ashift;

                        // Either -1 (impassable) or 1+
                        // (wave's been here already) means
                        // this spot is of no interest to us.
                        if (map[awindex]) continue;

                        // The 'path is found' routine.
                        if (awindex == begin)
                        {
                            // Log.log("THE WAY");

                            // The following code is just a dummy demo.
                            var result:Array = source.slice();

                            while (anindex != end)
                            {
                                result[route[anindex]] = '*';
                                anindex = map[anindex];
                            }

                            return result;

                            /**
                             * The main idea behind the result code
                             * is to unwind the calculated path,
                             * which is pretty easy because each
                             * affected map cell contains
                             * the index of the previous
                             * cell all the way back
                             * to the center of
                             * the wave.
                             * 

                            result = [begin];

                            while (anindex != end)
                            {
                                result.push(anindex);
                                anindex = map[anindex];
                            }

                            result.push(end);

                             *
                            **/
                        }

                        // Add the empty cell to the
                        // next front line of the wave.
                        map[awindex] = anindex;
                        froth[findex++] = awindex;
                    }
                }

                // The next front line is formed,
                // time to move on to the next iteration.

                var xchange:Vector.<int> = froth;
                var xindex:int = findex;

                froth = wave;
                findex = 0;

                wave = xchange;
                windex = xindex;

                //Log.log(windex, wave);
            }

            // If we're here, that means the wave started
            // at the 'end' point never hit the 'begin'.

            trace("NO WAY");

            return null;
        }

        // Tests pathfinding in a smaller dungeon: a multiple times.
        private function testSmall():void
        {
            var X:XML = <root><![CDATA[
                ##################################
                #.............#................#Y#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#.......#.......#........#.#
                #.....#...............#..........#
                #.....############################
                #................................#
                #................................#
                #................................#
                #................................#
                #######..........................#
                #................................#
                #...####.........................#
                #................................#
                #................................#
                #................................#
                #................................#
                #................................#
                #................................#
                #................................#
                ##################...............#
                #................#...............#
                #................#...............#
                #...######.......#...............#
                #........#.......#...............#
                #........#.......#...............#
                #........#.......#...............#
                #X.......#.......................#
                ##################################
            ]]></root>;

            var D:String = X.children()[0].toString().split("\r").join("");
            var A:Array = D.split("");

            var aTime:int = getTimer();

            var R:Array;

            for (var i:int = 255; i >= 0; i--)
            {
                R = findPath(A, 34, 34);
            }

            Log.log("");
            Log.log("32 x 32, pre-designed, not empty, 256 times.");
            Log.log("Elapsed", getTimer() - aTime, "ms.");

            if (R) Log.log(R.join(""));
        }

        // Tests pathfinding in a big empty dungeon.
        private function testBig():void
        {
            var D:String = "";

            // Lets form a biiig empty field with
            // entrance and exit at the opposite corners.
            var TB:String = G("#", 322);
            var TX:String = "#" + G(".", 319) + "X#";
            var TY:String = "#Y" + G(".", 319) + "#";
            var TE:String = "#" + G(".", 320) + "#";

            D += TB;
            D += TX;

            for (var i:int = 0; i < 318; i++)
            {
                D += TE;
            }

            D += TY;
            D += TB;

            var A:Array = D.split("");
            var aTime:int = getTimer();

            var R:Array = findPath(A, 320, 320);

            Log.log("");
            Log.log("320 x 320, empty.");
            Log.log("Elapsed", getTimer() - aTime, "ms.");
        }

        private function G(char:String, repeat:int):String
        {
            var result:String = char;

            while (result.length < repeat)
            {
                result += result;
            }

            result = result.substr(0, repeat);

            return result;
        }
    }
}