|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Волшебное превращение float в NaN, и как это ловить? (haxe)
Решил поигратся с АС3, до этого был только АС1-2 на таймлайне в FlashIDE в виде АктивХ оболочки на Делфи(опыта лет 8, всякие презентации, слайдшоу, автораны и тд в ассортименте)
Изучив с чем сейчас можно работать остановился на Haxe+FlashDevelop Для первой задачи выбрал тему про сталкивающиеся 2д шары. вроде все красиво... но есть 2 проблеммы и 1 вопрос: 1) мне кажется что шары "дергаются", перепрыгивают из 1 места поля в другое и тд, ведут себя странно вобщем. Пока их мало все красиво это происходит именно в куске кода расчета столкновений 2) через некоторое время, иногда почти сразу, иногда секунд 15-30+ происходит ситуация, после которой VoloX, VeloY получает значение NaN, после чего все вычисляемые от них параметры также уходят в НаН и шар залипает в 0,0 превращаяесь в "черную дыру" (( Собственно вопрос, как в Нахе такие ситуации ловить? т.е. я догадываюсь в чем проблемма в общем виде, но как-то привык что у меня рантайм-еррор выскакивает при неадекватных опперациях типа корня из отрицательного числа. для удобства весь проект архивом собственно Код: BallObject: package ; import flash.display.GradientType; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.Lib; class BallObject extends Sprite { public var Radius:Float; public var Color:UInt; public var VeloX:Float; public var VeloY:Float; public var minTop:UInt; public var maxBottom:UInt; public var minLeft:UInt; public var maxRight:UInt; public function MoveBall() { this.x += VeloX; this.y += VeloY; //wall collisions //left if (this.x < minLeft) { VeloX = -VeloX; this.x = minLeft; } else //right if (this.x > maxRight) { VeloX = -VeloX; this.x = maxRight; } //top if (this.y < minTop) { VeloY = -VeloY; this.y = minTop; } else //bottom if (this.y > maxBottom) { VeloY = -VeloY; this.y = maxBottom; } } private function Render() { var m = new Matrix(); m.createGradientBox(Radius, Radius, 0, -Radius, -Radius); graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, Color], [1,1], [0, 0xFF], m); graphics.drawCircle(0, 0, Radius); graphics.endFill(); } public function new(StartX,StartY,newRadius,VelX,VelY,newColor,stageHeight,stageWidth) { super(); this.x = StartX; this.y = StartY; Radius = newRadius; minLeft = Math.round(Radius)+5; maxRight = Math.round(stageWidth - Radius)-5; minTop = Math.round(Radius)+5; maxBottom = Math.round(stageHeight - Radius)-5; Color = newColor; VeloX = VelX; VeloY = VelY; Render(); } } BallManager: package ; import flash.display.DisplayObject; import flash.display.MovieClip; import flash.events.Event; import flash.geom.Point; import flash.Lib; import flash.text.TextField; import flash.text.TextFieldAutoSize; class BallManager extends MovieClip { var myStage:MovieClip; var balls:Array<BallObject>; var wrongCollisions:UInt; var rightCollisions:UInt; var totalCollisions:UInt; //var gui:MyGui; public function BallCollideEx(ball1:BallObject,ball2:BallObject) { totalCollisions++; //localize var ed:Float = 1; var x1:Float = ball1.x; var y1:Float = ball1.y; var x2:Float = ball2.x; var y2:Float = ball2.y; var vX1:Float = ball1.VeloX; var vY1:Float = ball1.VeloY; var vX2:Float = ball2.VeloX; var vY2:Float = ball2.VeloY; var r1:Float = ball1.Radius; var r2:Float = ball2.Radius; var mass1:Float = 1; var mass2:Float = 1; // flashback to collision time var dx:Float = x2 - x1; var dy:Float = y2 - y1; var d:Float = Math.sqrt(dx * dx + dy * dy); if (d < (r1 + r2)) { // right collision rightCollisions++; var vp1:Float = vX1 * dx / d + vY1 * dy / d; var vp2:Float = vX2 * dx / d + vY2 * dy / d; var dt:Float = (r1 + r2 - d) / (vp1 - vp2); // balls collision coordinates; x1 -= vX1 * dt; y1 -= vY1 * dt; x2 -= vX2 * dt; y2 -= vY2 * dt; // collision var dx:Float = x2 - x1; var dy:Float = y2 - y1; var d:Float = Math.sqrt(dx * dx + dy * dy); // Unit vector in the direction of the collision var aX:Float = dx / d; var aY:Float = dy / d; // Projection of the velocities in these axes var vA1:Float = (vX1 * aX + vY1 * aY); var vB1:Float = ( -vX1 * aY + vY1 * aX); var vA2:Float = (vX2 * aX + vY2 * aY); var vB2:Float = ( -vX2 * aY + vY2 * aX); // New velocities in these axes (after collision): ed<=1, for elastic collision ed=1 var vAP1:Float = vA1 + (1 + ed) * (vA2 - vA1) / (1 + mass1 / mass2); var vAP2:Float = vA2 + (1 + ed) * (vA1 - vA2) / (1 + mass2 / mass1); // Undo the projections vX1 = vAP1 * aX - vB1 * aY; vY1 = vAP1 * aY + vB1 * aX; vX2 = vAP2 * aX - vB2 * aY; vY2 = vAP2 * aY + vB2 * aX; // move time forward x1 += vX1 * dt; y1 += vY1 * dt; x2 += vX2 * dt; y2 += vY2 * dt; // restore variables ball1.x = x1; ball1.y = y1; ball1.VeloX = vX1; ball1.VeloY = vY1; ball2.x = x2; ball2.y = y2; ball2.VeloX = vX2; ball2.VeloY = vY2; } else { //no collision detected wrongCollisions++; } } public function AddRandomBall(maxHeight,maxWidth):BallObject { var ColorArray:Array<Int> = [Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255)]; //ColorArray[Math.round(Math.random() * 3)] = 255; var Color = ColorArray[2] + ColorArray[1] * 0xff + ColorArray[2] * 0xffff; var Radius = Math.random() * 5 + 5; var Angle = Math.random() * 360; var Speed = Math.random() * 5 + 1; var VeloX = Math.sin(Angle) * Speed; var VeloY = Math.cos(Angle) * Speed; var BallX = Radius+ Math.random() * (maxWidth-Radius*2); var BallY = Radius + Math.random() * (maxHeight-Radius*2); return new BallObject(BallX,BallY,Radius,VeloX,VeloY,Color,maxHeight,maxWidth); } public function bruteCollide() { for (i in 0...balls.length-1) { for (j in 0...balls.length-1) { if (i != j) { BallCollideEx(balls[i], balls[j]); } } } } public function xSortCollide() { balls.sort(function (ball1:BallObject, ball2:BallObject):Int return Math.round(ball1.x - ball2.x) ); var rad:Float; var xDist:Float; for (i in 0...balls.length - 2) { for (j in i + 1...balls.length - 1) { rad = balls[j].Radius + balls[i].Radius; xDist = Math.abs(balls[j].x - balls[i].x); if (xDist < rad) { BallCollideEx(balls[i], balls[j]); } else { break; } } } } public function moveBalls(e:Event) { var mode:UInt; //mode = gui.modeSwitch.mode; mode = 1; rightCollisions = 0; wrongCollisions = 0; totalCollisions = 0; var cur:Float = Lib.getTimer(); for (i in 0...balls.length - 1) { balls[i].MoveBall(); } switch (mode) { case 0: bruteCollide(); case 1: xSortCollide(); } var Elapsed = Lib.getTimer() - cur; /*gui.fpsField.text = 'Elapsed: ' + Elapsed + 'ms'; gui.totalCollisionsField.text = 'Всего проверок: ' + totalCollisions; gui.rightCollisionsField.text = 'Правильных столкновений: ' + rightCollisions; gui.wrongCollisionsField.text = 'Ложных проверок: ' + wrongCollisions; gui.wasteField.text = 'Эффективность: ' + Math.floor(10000*rightCollisions / wrongCollisions)/100 + '%';*/ } public function new(dst:MovieClip) { super(); myStage = dst; myStage.addChild(this); myStage.stage.frameRate = 60; //maxballs var MaxBalls = 350; balls = new Array<BallObject>(); for (i in 0...MaxBalls) { balls.push(AddRandomBall(dst.stage.stageHeight, dst.stage.stageWidth)); myStage.addChild(balls[i]); } //gui = new MyGui(); //myStage.addChild(gui); //gui.x = dst.stage.stageWidth - gui.width; //gui.y = 0; this.addEventListener(Event.ENTER_FRAME, moveBalls); } } Последний раз редактировалось drnet_ua; 12.07.2010 в 10:36. |
|
|||||
Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
|
Цитата:
Откуда они вообще берутся? Вот возьмем скажем: var d:Float = Math.sqrt(dx * dx + dy * dy); // Unit vector in the direction of the collision var aX:Float = dx / d; var aY:Float = dy / d; // Projection of the velocities in these axes var vA1:Float = (vX1 * aX + vY1 * aY); var vB1:Float = ( -vX1 * aY + vY1 * aX); var vA2:Float = (vX2 * aX + vY2 * aY); var vB2:Float = ( -vX2 * aY + vY2 * aX); aX и aY - деление на ноль vA1, vA2, vB1, vB2 - потому что используют aX или aY, т.е NaN. А при операциях с NaN'ом получается в итоге NaN. И в коде у вас много лишних объявлений локальных переменных. и еще попадаются переобъявления одних и тех же. Последний раз редактировалось i.o.; 12.07.2010 в 11:20. |
Часовой пояс GMT +4, время: 10:55. |
|
« Предыдущая тема | Следующая тема » |
Опции темы | |
Опции просмотра | |
|
|