PDA

Просмотр полной версии : Странные глюки.


AlexCooper
02.03.2011, 16:05
Здравствуйте.
Сегодня ночью наткнулся на целый ряд не понятных мне багов. Когда трасировка к примеру
course.controlpoint[0][0]==Math.floor(course._x) показывала false при course.controlpoint[0][0]=163 && Math.floor(course._x)=163. Но это еще не всё. Попрошу лучше взглянуть на код. Так как при выполнении одного условия в строчке 56 просчитываются довольно большое количество итераций в пустую. Это можно увидеть при снятии закоментированных трейсеров.
Дальше идёт код, правда немного не красивый но я не успел еще привести его до толку. Но больше всего интересует такой вопрос с свойствами _х и _у с аналогичными course.controlpoint[0][0] и course.controlpoint[0][1] данными, когда там одинаковые числа а выводит false, причём если не использовать Math.floor то вообщепроисходить всеголишь 1 итерация.
//import flash.display.Graphics;

class Vector2D
{

private var _x:Number;
private var _y:Number;

public function Vector2D(x:Number,y:Number)
{
_x = x;
_y = y;
}

public function draw(graphics:MovieClip, color):Void
{
graphics.lineStyle(0, color);
graphics.moveTo(0, 0);
graphics.lineTo(_x, _y);
}

public function clone():Vector2D
{
return new Vector2D(x, y);
}

public function zero():Vector2D
{
_x = 0;
_y = 0;
return this;
}

public function isZero():Boolean
{
return _x == 0 && _y == 0;
}

public function set length(value:Number):Void
{
var a:Number = angle;
_x = Math.cos(a) * value;
_y = Math.sin(a) * value;
}
public function get length():Number
{
return Math.sqrt(lengthSQ);
}

public function get lengthSQ():Number
{
return _x * _x + _y * _y;
}

public function set angle(value:Number):Void
{
var len:Number = length;
_x = Math.cos(value) * len;
_y = Math.sin(value) * len;
}
public function get angle():Number
{
return Math.atan2(_y, _x);
}

public function set corner(value:Number):Void
{
var len:Number = length;
_x = Math.cos(value*Math.PI/180) * len;
_y = Math.sin(value*Math.PI/180) * len;
}

public function get corner():Number
{
return angle * 180 / Math.PI;
}

public function normalize():Vector2D
{
if(length == 0)
{
_x = 1;
return this;
}
var len:Number = length;
_x /= len;
_y /= len;
return this;
}

public function truncate(max:Number):Vector2D
{
length = Math.min(max, length);
return this;
}

public function reverse():Vector2D
{
_x = -_x;
_y = -_y;
return this;
}

public function isNormalized():Boolean
{
return length == 1.0;
}

public function dotProd(v2:Vector2D):Number
{
return _x * v2.x + _y * v2.y;
}

public function crossProd(v2:Vector2D):Number
{
return _x * v2.y - _y * v2.x;
}


public static function angleBetween(v1:Vector2D, v2:Vector2D):Number
{
if(!v1.isNormalized()) v1 = v1.clone().normalize();
if(!v2.isNormalized()) v2 = v2.clone().normalize();
return Math.acos(v1.dotProd(v2));
}

public static function cornerBetween(v1:Vector2D, v2:Vector2D):Number
{
return angleBetween(v1,v2) * 180 / Math.PI;
}

public function sign(v2:Vector2D)
{
return perp.dotProd(v2) < 0 ? -1 : 1;
}

public function get perp():Vector2D
{
return new Vector2D(-y, x);
}

public function dist(v2:Vector2D):Number
{
return Math.sqrt(distSQ(v2));
}

public function distSQ(v2:Vector2D):Number
{
var dx:Number = v2.x - x;
var dy:Number = v2.y - y;
return dx * dx + dy * dy;
}

public function add(v2:Vector2D):Vector2D
{
return new Vector2D(_x + v2.x, _y + v2.y);
}

public function subtract(v2:Vector2D):Vector2D
{
return new Vector2D(_x - v2.x, _y - v2.y);
}

public function multiply(value:Number):Vector2D
{
return new Vector2D(_x * value, _y * value);
}

public function divide(value:Number):Vector2D
{
return new Vector2D(_x / value, _y / value);
}

public function equals(v2:Vector2D):Boolean
{
return _x == v2.x && _y == v2.y;
}

public function set x(value:Number):Void
{
_x = value;
}
public function get x():Number
{
return _x;
}

public function set y(value:Number):Void
{
_y = value;
}
public function get y():Number
{
return _y;
}

public function toString():String
{
return "[Vector2D (x:" + _x + ", y:" + _y + ")]";
}
}

и в самом флеше поместите небольшой мувик с назначенным ему "ship" идентификатором.
import Vector2D;

var t:MovieClip = _root.createEmptyMovieClip("triang_mc", 1);
thickness = 1;
lineColor = 0xff0000;
alpha = 100;

triang_mc.lineStyle(thickness, lineColor, alpha);

ship.m=20;
ship.speed=20;
ship.stopl=30;
ship.radius=180/ship.m;

triang_mc.moveTo(ship._x, ship._y);

X=ship._x+Math.cos(Math.PI/180*(ship._rotation+90))*ship.radius;
Y=ship._y+Math.sin(Math.PI/180*(ship._rotation+90))*ship.radius;
triang_mc.lineTo(X, Y);
var course:MovieClip = new MovieClip();

course.axis = new Vector2D(Math.cos(Math.PI/180*ship._rotation),Math.sin(Math.PI/180*ship._rotation));

course.target = new Vector2D(dot._x-ship._x,dot._y-ship._y);

triang_mc.lineStyle(0, 0xFF0000);
triang_mc.moveTo(ship._x, ship._y);

BuildRoute = function()
{
r++;

course.target.x=course.tx-course._x;
course.target.y=course.ty-course._y;

//trace(Vector2D.cornerBetween(course.route,course.target));

if (Vector2D.cornerBetween(course.route,course.target)>course.m)
{

course.route.corner+=course.shift*course.m;
course._rotation=course.route.corner;

} else
{
course.route=course.target;
course._rotation=course.target.corner;
}

course._x+= (course.target.length>course.speed) ? Math.cos(Math.PI/180*course._rotation)*course.speed : course.target.x;
course._y+= (course.target.length>course.speed) ? Math.sin(Math.PI/180*course._rotation)*course.speed : course.target.y;

course._x=Math.floor(course._x);
course._y=Math.floor(course._y);

if ((course.controlpoint[0][0]==Math.floor(course._x) && course.controlpoint[0][1]==Math.floor(course._y)) || (Vector2D.cornerBetween(course.route,course.axis)<course.m && !course.route.equals(course.target)))
{


//triang_mc.lineTo(course._x, course._y);
course.speed-=1;
//trace('Speed:'+course.speed);
course.controlpoint.splice(1);
course.route.x=course.axis.x;
course.route.y=course.axis.y;
course.route = course.axis.clone();
course.route.corner+=course.shift;
course._x=Math.floor(ship._x);
course._y=Math.floor(ship._y);

} else
{
if (course.target.length<course.speed)
{
if (course.target.equals(course.route))
{
course.controlpoint.push([course._x, course._y,course._rotation]);

return false;
}
else
{
course.speed-=1;

course.controlpoint.splice(0);
course.route.x=course.axis.x;
course.route.y=course.axis.y;
course.route = course.axis.clone();
course.route.corner+=course.shift;
course._x=Math.floor(ship._x);
course._y=Math.floor(ship._y);

/*/triang_mc.clear();
triang_mc.lineStyle(0, 0xFF0000);
triang_mc.moveTo(course.controlpoint[0][0],course.controlpoint[0][1]);*/
}

} else
{
course.controlpoint.push([course._x, course._y,course._rotation]);
//triang_mc.lineTo(course._x, course._y);
}

}
return true;
}

function traceRoute()
{
triang_mc.lineStyle(0, 0xFF0000);
triang_mc.moveTo(course.controlpoint[0][0],course.controlpoint[0][1]);

for (step=1; step< course.controlpoint.length; step++)
{
triang_mc.lineTo(course.controlpoint[step][0],course.controlpoint[step][1]);
}
}

_root.bufferT = getTimer();
_root.onMouseDown = function()
{
delete ship.onEnterFrame;

if (getTimer()-_root.bufferT>500)
{
ship._x= Math.floor(ship._x);
ship._y= Math.floor(ship._y);
course.tx = Math.floor(_xmouse);
course.ty = Math.floor(_ymouse);
course._x = ship._x;
course._y = ship._y;
course._rotation = ship._rotation;
course.controlpoint = new Array();

for (prop in ship)
{
course[prop]=ship[prop];
}

course.axis.x=Math.cos(Math.PI/180*course._rotation);
course.axis.y=Math.sin(Math.PI/180*course._rotation);

course.target.x=course.tx-course._x;
course.target.y=course.ty-course._y;

course.axis.length=1;

course.route = course.axis.clone();

if (Vector2D.cornerBetween(course.axis,course.target)>=course.m)
{
course.shift = 1;

course.route.corner+=course.shift;

if (Vector2D.cornerBetween(course.route,course.target)>Vector2D.cornerBetween(course.axis,course.target))
{
course.shift*=-1;
}
} else course.shift = 0;

course.route.x=course.axis.x;
course.route.y=course.axis.y;

course.controlpoint.push([course._x, course._y,course._rotation]);

r = 0;
while (BuildRoute());

trace('Search iteration :: '+r);
} else
{
traceRoute();
delete ship.onEnterFrame;
//trace(course.controlpoint);
ship.dx=(course.controlpoint[1][0]-ship._x)/10;
ship.dy=(course.controlpoint[1][1]-ship._y)/10;
ship.dr=(course.controlpoint[1][2]-ship._rotation)/10;
ship.s=0;
ship.st=1;
ship.onEnterFrame = function()
{
//trace(course.controlpoint[++ship.st][0]);
this._x+=this.dx;
this._y+=this.dy;
this._rotation+=this.dr;
if (++this.s==10)
{
this.s=0;
this.dx=(_root.course.controlpoint[++this.st][0]-this._x)/10;
this.dy=(_root.course.controlpoint[this.st][1]-this._y)/10;
this.dr=(_root.course.controlpoint[this.st][2]-this._rotation)/10;
}
}
}
_root.bufferT = getTimer();
//traceRoute();
}
предыдущая тема http://www.flasher.ru/forum/showthread.php?t=151244

Hauts
02.03.2011, 16:21
Формализуйте вопросы и выложите исходники, иначе проблематично разобраться.

AlexCooper
03.03.2011, 04:06
Глюки уже не тревожат, вот только при больших значениях speed и flexbility и кликах как можно больше к мувику возможны "зависания" + не правильный просчёт. А вообще вектора рулят))

speed - скорость в пикселях за одну итерацию
flexbility - допустимый угол поворота, то-есть манёвренность

так же я дополнил класс Вектор2Д

трёма функциями преобразующие геометрические углы в понятное для нас свойство _rotation (угол наклона)
геттеры и сетеры
public function set corner(value:Number):Void
{
var len:Number = length;
_x = Math.cos(value*Math.PI/180) * len;
_y = Math.sin(value*Math.PI/180) * len;
}

public function get corner():Number
{
return angle * 180 / Math.PI;
}

функция возвращающая угол наклона между векторами
public static function cornerBetween(v1:Vector2D, v2:Vector2D):Number
{
return angleBetween(v1,v2) * 180 / Math.PI;
}

исходный код класса есть в самом начале

AlexCooper
03.03.2011, 04:19
Так же хочу поблагодарить Hauts который направил меня на немало полезной информации. Еще раз спасибо, как Видете пришлось переписать по АС2, но за то функциональные возможности взросли в несколько раз

Hauts
03.03.2011, 08:44
AlexCooper, спасибо :)

Отличная флэшка получилась! Честно говоря, не думал, что так быстро сделаете.

Кстати в классе вектора я обычно Math.PI/180 выношу в прайват-переменную (кэширую) и использую ее для расчетов, а не делю каждый раз PI на 180.

Котяра
03.03.2011, 12:24
Почему AS2?

AlexCooper
03.03.2011, 14:06
Да я просто никак не начну писать под AS3 и как следствие не знаю разницы в методах объявление функций в классах (public, private, property)