zoukankan      html  css  js  c++  java
  • 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;
    		}
    
    
    	}
    }
    
  • 相关阅读:
    Linux系统下搭建Gitlab服务器
    Sqlserver数据库表转换成C#实体类
    C# 获取今天,昨天,上周,下周,上月,下月等等一些日期格式【转】
    Funthing
    网页生成海报
    NET 5.0 Swagger API 自动生成MarkDown文档
    说说C# 8.0 新增功能Index和Range的^0是什么?
    tblive-studio vs2019 编译过程记录
    确定已安装的 .NET Framework 版本
    修改CMD默认编码
  • 原文地址:https://www.cnblogs.com/kenkofox/p/2168944.html
Copyright © 2011-2022 走看看