c++ 读取 flash AIR NativeAplication 参数
c++ read flash AIR NativeAplication arguments
Hy 我制作了一个 AIR 应用程序,它使用 flash.desktop.NativeProcess 来启动 c++ a* 路径求解器。原因是 - Flash 需要太多时间来解决 250 * 250 开放网格。
AIR 应用程序很好。它可以启动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 个用于六边形地形)。那时我不需要复杂的东西(我认为你也不需要它们),比如路径权重,只是为了在用户体验可接受的时间范围内找到最短路径。
如果你看一下算法寻路部分,它是如此简单。没有 x 和 y 坐标。没有边境检查。没有节点对象,没有属性,没有额外的函数调用。每个单元只有最简单的数学和一些操作——尽可能少。这就是它如此快速和高效的原因。
提到的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;
}
}
}
Hy 我制作了一个 AIR 应用程序,它使用 flash.desktop.NativeProcess 来启动 c++ a* 路径求解器。原因是 - Flash 需要太多时间来解决 250 * 250 开放网格。
AIR 应用程序很好。它可以启动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 个用于六边形地形)。那时我不需要复杂的东西(我认为你也不需要它们),比如路径权重,只是为了在用户体验可接受的时间范围内找到最短路径。
如果你看一下算法寻路部分,它是如此简单。没有 x 和 y 坐标。没有边境检查。没有节点对象,没有属性,没有额外的函数调用。每个单元只有最简单的数学和一些操作——尽可能少。这就是它如此快速和高效的原因。
提到的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;
}
}
}