没怎么玩过图形学,最近都需要做,又要复习物理和数学了~~~
以下是初成的作品,其实最终目的也不是这个球碰撞了,只是试试,有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;
}
}
}