Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 12.07.2010, 10:23
drnet_ua вне форума Посмотреть профиль Отправить личное сообщение для drnet_ua Найти все сообщения от drnet_ua
  № 1  
Ответить с цитированием
drnet_ua
 
Аватар для drnet_ua

Регистрация: Jul 2010
Адрес: 50° 27′ 0″ N, 30° 30′ 0″ E
Сообщений: 256
Записей в блоге: 2
По умолчанию Волшебное превращение float в NaN, и как это ловить? (haxe)

Решил поигратся с АС3, до этого был только АС1-2 на таймлайне в FlashIDE в виде АктивХ оболочки на Делфи(опыта лет 8, всякие презентации, слайдшоу, автораны и тд в ассортименте)

Изучив с чем сейчас можно работать остановился на Haxe+FlashDevelop

Для первой задачи выбрал тему про сталкивающиеся 2д шары.

вроде все красиво... но есть 2 проблеммы и 1 вопрос:

1) мне кажется что шары "дергаются", перепрыгивают из 1 места поля в другое и тд, ведут себя странно вобщем. Пока их мало все красиво
это происходит именно в куске кода расчета столкновений

2) через некоторое время, иногда почти сразу, иногда секунд 15-30+ происходит ситуация, после которой VoloX, VeloY получает значение NaN, после чего все вычисляемые от них параметры также уходят в НаН и шар залипает в 0,0 превращаяесь в "черную дыру" ((

Собственно вопрос, как в Нахе такие ситуации ловить?
т.е. я догадываюсь в чем проблемма в общем виде, но как-то привык что у меня рантайм-еррор выскакивает при неадекватных опперациях типа корня из отрицательного числа.

для удобства весь проект архивом

собственно Код:

BallObject:
Код AS3:
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:

Код AS3:
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);
 
}
}
и Main
Код AS3:
package ;
 
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.Lib;
 
class Main 
{
 
	private var Manager: BallManager;
 
	public function new() {
 
 
 
	Manager = new BallManager(Lib.current);
 
	}
	static function main() 
	{
	new Main();
	}
 
}


Последний раз редактировалось drnet_ua; 12.07.2010 в 10:36.
Старый 12.07.2010, 11:07
i.o. вне форума Посмотреть профиль Отправить личное сообщение для i.o. Найти все сообщения от i.o.
  № 2  
Ответить с цитированием
i.o.
 
Аватар для i.o.

Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
Цитата:
как это ловить?
ну наверное проверять с помощью isNaN() в "интимных" местах.


Откуда они вообще берутся? Вот возьмем скажем:
Код AS3:
		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);
Если d окажется ноликом, то NaN'ом станет:
aX и aY - деление на ноль
vA1, vA2, vB1, vB2 - потому что используют aX или aY, т.е NaN. А при операциях с NaN'ом получается в итоге NaN.

И в коде у вас много лишних объявлений локальных переменных. и еще попадаются переобъявления одних и тех же.


Последний раз редактировалось i.o.; 12.07.2010 в 11:20.
Создать новую тему Ответ Часовой пояс GMT +4, время: 16:32.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 16:32.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.