Flex Actionscript 3 小球碰撞 多球碰撞

没怎么玩过图形学,最近都需要做,又要复习物理和数学了~~~

以下是初成的作品,其实最终目的也不是这个球碰撞了,只是试试,有bug~~(就是球会偶尔粘在一起,是因为速度太快)

需要解决粘连问题,就需要加入“下一点位置”来做提前的碰撞预判。

可以简单加入下一点标记一下,在Ball类中,加EnterFrame监听,每一帧计算下一帧的位置,然后碰撞的测试函数改为使用nextX和nextY计算,而不是x和y。

效果如下:

直接上代码(没有更新“下一点标记”):

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.engine.Kerning;
	
	import flashx.textLayout.formats.BackgroundColor;
	
	[SWF(width = "600", height = "500", backgroundColor = "#000000", frameRate = "30")] 
	public class Main extends Sprite
	{
		private var ballList:Vector.<Ball> = new Vector.<Ball>;
		public function Main()
		{
			this.graphics.beginFill(0xFFFFFF);
			this.graphics.drawRect(0, 0, 600, 500);
			this.graphics.endFill();
			
			var colorArray:Array = [0x222222, 0x123456, 0xff2200, 0x11ff44, 0x4411ff, 0x132e00, 0x1df144, 0x40110f];
			
			//随机初始化每个MC的运动速度和方向
			for (var i:int = 0; i<8; i++) 
			{
				var radius:int = 30;
				var ball:Ball = new Ball(colorArray[i], radius);
				ball.speed.x = -5 + 10*Math.random();
				ball.speed.y = -5 + 10*Math.random();
				ball.x = i*60 + 5;
				ball.y = i*60 + 5;
				ballList.push(ball);
				
				this.addChild(ball);
			}
			
			var sw:Number = this.width;
			var sh:Number = this.height;
			
			this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(event:Event):void
		{
			for (var i:int = 0; i<ballList.length; i++) 
			{
				var ball:Ball = ballList[i];
				//如果到了边界,就反射
				if ((ball.x < 0) || (ball.x + 2*ball.radius > 600))
				{
					ball.speed.x *= -1;
				}
				if ((ball.y < 0) || (ball.y + 2*ball.radius > 500)) 
				{
					ball.speed.y *= -1;
				}
				//检测所有MC之间是否有碰撞,有就根据情况改变“增量”方向
				for (var j:int = i+1; j<ballList.length; j++) 
				{
					if (collisionTest(ball, ballList[j])) 
					{
						collide(ball, ballList[j]);
					}
				}
				//移动一个“增量”         
				ball.x += ball.speed.x;
				ball.y += ball.speed.y;
			}
		}

		//碰撞函数,根据两球碰撞方向和自身运动方向合成新的增量值
		private function collide(ball1:Ball, ball2:Ball):void 
		{
			//http://tina0152.blog.163.com/blog/static/119447958200910229109326/
			var x1:int = ball1.x + ball1.radius;
			var y1:int = ball1.y + ball1.radius;
			var x2:int = ball2.x + ball2.radius;
			var y2:int = ball2.y + ball2.radius;
			
			//s向量是球心连线上的
			var s:KVector = new KVector(x2-x1, y2-y1);
			s = s.unitfy();
			//t向量是s的垂直线上的
			var t:KVector = s.rotateClockwise(Math.PI/2);
			t = t.unitfy();
			var v1:KVector = ball1.speed;
			var v2:KVector = ball2.speed;
			
			//先算v1(v1x, v1y)在s和t轴的投影值,分别设为v1s和v1t
			//再算v2(v2x, v2y)在s和t轴的投影值,分别设为v2s和v2t:
			var v1s:Number = v1.dotMultiply(s);
			var v1t:Number = v1.dotMultiply(t);
			var v2s:Number = v2.dotMultiply(s);
			var v2t:Number = v2.dotMultiply(t);
			
			//简单做法,当质量一样,直接交换速度
			var temp:Number = v1s;
			v1s = v2s;
			v2s = temp;
			
			//首先求出v1t和v2t在t轴的向量v1t'和v2t'(将数值变为向量)
			//再求出v1s'和v2s'在s轴的向量v1s'和v2s'(将数值变为向量)
			var v1tVector:KVector = t.multiply(v1t);
			var v1sVector:KVector = s.multiply(v1s);
			var v2tVector:KVector = t.multiply(v2t);
			var v2sVector:KVector = s.multiply(v2s);
			
			ball1.speed = v1tVector.add(v1sVector);
			ball2.speed = v2tVector.add(v2sVector);
		}
		
		//碰撞侦测
		private function collisionTest(ball1:Ball, ball2:Ball):Boolean
		{
			var deltaX:Number = ball1.x + ball1.radius - (ball2.x + ball2.radius);
			var deltaY:Number = ball1.y + ball1.radius - (ball2.y + ball2.radius);
			var a:Number=Math.sqrt(deltaX*deltaX + deltaY*deltaY);
			if(a <= ball1.radius+ball2.radius)
			{	
				return true;
			}
			else
			{
				return false;
			}
		}
		
	}
}
package
{
	import flash.display.Sprite;
	
	public class Ball extends Sprite
	{
		private var _radius:int = 0;
		private var _speed:KVector = null;
		
		public function Ball(color:uint, radius:int)
		{
			super();
			this.radius = radius;
			this.graphics.beginFill(color, 0.6);
			this.graphics.drawCircle(radius,radius,radius);
			this.graphics.endFill();
			speed = new KVector();
		}

		public function get radius():int
		{
			return _radius;
		}

		public function set radius(value:int):void
		{
			_radius = value;
		}

		public function get speed():KVector
		{
			return _speed;
		}

		public function set speed(value:KVector):void
		{
			_speed = value;
		}



	}
}
package
{
	public class KVector
	{
		private var _x:Number = 0;
		private var _y:Number = 0;
		public function KVector(x:Number = 0,y:Number = 0)
		{
			this.x = x;
			this.y = y;
		}
		public function add(value:KVector):KVector
		{
			var vector:KVector = new KVector();
			vector.x = x + value.x;
			vector.y = y + value.y;
			return vector;
		}
		
		public function dotMultiply(vector:KVector):Number
		{
			return x * vector.x + y * vector.y;
		}
		public function multiply(value:Number):KVector
		{
			var vector:KVector = new KVector();
			vector.x = x*value;
			vector.y = y*value;
			return vector;
		}
		public function unitfy():KVector
		{
			var vector:KVector = new KVector();
			vector.x = x/Math.sqrt(x*x + y*y);
			vector.y = y/Math.sqrt(x*x + y*y);
			return vector;
		}
		public function divide(value:Number):KVector
		{
			var vector:KVector = new KVector();
			vector.x = x/value;
			vector.y = y/value;
			return vector;
		}
		
		/**
		 * angle是数学的弧度,以Math.PI为180度
		 */ 
		public function rotateClockwise(angle:Number):KVector
		{
			var vector:KVector = new KVector();
			vector.x = x*Math.cos(angle) + y*Math.sin(angle);
			vector.y = -x*Math.sin(angle) + y*Math.cos(angle);
			return vector;
		}

		public function get x():Number
		{
			return _x;
		}

		public function set x(value:Number):void
		{
			_x = value;
		}

		public function get y():Number
		{
			return _y;
		}

		public function set y(value:Number):void
		{
			_y = value;
		}


	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏架构之路

并查集Union-find及其在最小生成树中的应用

并查集是一种用途广泛的数据结构,能够快速地处理集合的合并和查询问题,并且实现起来非常方便,在很多场合中都有着非常巧妙的应用,。 本文首先介绍并查集的定义、原理及...

3044
来自专栏数据结构与算法

洛谷P3966 [TJOI2013]单词(AC自动机)

992
来自专栏chenjx85的技术专栏

leetcode-507-Perfect Number

1404
来自专栏繁花云

[C语言]7-3笔记

对数的定义:一般地,如果ax=N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN,读作以a为底N的对数,其中a叫做对数的底数,N叫做真数。

840
来自专栏王肖的UT

GLSL-内置函数

2073
来自专栏iOSDevLog

day1-numpy练习

这是在numpy邮件列表,stackoverflow和numpy文档中收集的练习集合。 该系列的目标是为新老用户提供快速参考,同时为教学人员提供一系列练习。

2151
来自专栏数据结构与算法

P2216 [HAOI2007]理想的正方形(二维RMQ)

题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。 输入输出格式 输入格式: 第一行为3...

2756
来自专栏机器学习和数学

[ Tensorflow]Tensorflow Reduction operations

reduce系列在平时工程中是经常使用的,其中reduce_sum是使用最频繁的一个。主要用在计算loss的时候,当我们定义好loss之后,我们一般要求loss...

3564
来自专栏鸡蛋君

计算机等级考试二级MsOffice之Excel函数学习

973
来自专栏進无尽的文章

基础篇- iOS开发中常用的数学函数

1382

扫码关注云+社区