flash on 2011-4-27
/**
* Copyright yama3 ( http://wonderfl.net/user/yama3 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vobN
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Graphics;
[SWF(frameRate=60)]
public class FlashTest extends Sprite {
public function FlashTest() {
var sw:int = stage.stageWidth;
var sh:int = stage.stageHeight;
var balls:Vector.<Ball> = new <Ball>[]
var curves:Vector.<Curve> = new <Curve>[new Curve, new Curve, new Curve, new Curve]
var gravity:Number = 0.7;
stage.addEventListener("mouseDown", function():void{for each(var c:Curve in curves)c.reset()})
addEventListener(Event.ENTER_FRAME, ENTER_FRAME)
function ENTER_FRAME(e:Event):void {
balls.push(new Ball)
var ball:Ball, curve:Curve
graphics.clear();
for each(curve in curves) {drawCurve(graphics, curve)}
for(var i:int = 0; i < balls.length; i++)
{
ball = balls[i]
ball.x += ball.vx, ball.y += ball.vy
var t:Number, theT:Number = 2, theCurve:Curve
for each(curve in curves) {
t = curve.getT(ball.prevx, ball.prevy, ball.x, ball.y)
if(t < theT) {theT = t, theCurve = curve}
}
if(0 <= theT && theT <= 1) {
ball.resolve(theCurve, theT)
}
if(ball.y > sh || ball.x < 0 || ball.x > sw) {
balls.splice(i, 1)
}
drawBall(graphics, ball)
ball.prevx = ball.x
ball.prevy = ball.y
ball.vy += gravity
}
}
function drawBall(g:Graphics, b:Ball):void {
g.lineStyle(3, 0xff0000)
g.moveTo(b.prevx, b.prevy)
g.lineTo(b.x, b.y)
}
function drawCurve(g:Graphics, c:Curve):void {
g.lineStyle(3, 0x000000)
g.moveTo(c.p0x, c.p0y)
g.curveTo(c.p1x, c.p1y, c.p2x, c.p2y)
}
}
}
}
function linear(start:Number, end:Number, t:Number):Number
{
return start + (end - start)*t;
}
function bezier(values:Array, t:Number):Number
{
if(values.length < 2) return NaN;
if(values.length == 2) return linear(values[0], values[1], t);
var postValues:Array = values.concat();
var i:int;
while(postValues.length > 1)
{
var resultValues:Array = new Array;
var count:int = postValues.length - 1;
for(i = 0; i < count; ++i)
{
resultValues.push(linear(postValues[i], postValues[i+1],t));
}
postValues = resultValues;
}
return postValues[0];
}
class Curve {
public var p0x:Number, p0y:Number
public var p1x:Number, p1y:Number
public var p2x:Number, p2y:Number
public function Curve() {
reset()
}
public function reset():void {
p0x = Math.random()*200, p0y = Math.random()*100+150
p1x = Math.random()*550, p1y = Math.random()*400
p2x = Math.random()*200+350, p2y = Math.random()*100+150
}
public function getT(slx:Number, sly:Number, elx:Number, ely:Number):Number {
if(slx == elx) slx += 0.01
var px:Number = p0x - 2 * p1x + p2x, py:Number = p0y - 2*p1y + p2y
var qx:Number = -2*p0x + 2*p1x, qy:Number = -2*p0y + 2*p1y
var rx:Number = p0x, ry:Number = p0y
var ax:Number = elx - slx, ay:Number = ely - sly
var bx:Number = slx, by:Number = sly
var X:Number = ay * px - ax * py
var Y:Number = ay * qx - ax * qy
var Z:Number = ay * rx - ay * bx - ax * ry + ax * by
var d:Number = Y * Y - 4 * X * Z
if(d < 0) return NaN
var t1:Number, s1:Number
if(d == 0) {
t1 = -Y/(2 * X)
if(0>t1 || 1 < t1) {
return NaN;
} else {
s1 = (px * t1 * t1 + qx * t1 + rx - bx) / ax
if(0 <= s1)if(s1 <= 1) return t1
return NaN
}
}
var t2:Number, s2:Number
var d2:Number = Math.sqrt(d)
t1 = (-Y + d2) / (2 * X)
t2 = (-Y - d2) / (2 * X)
s1 = (0 > t1 || 1 < t1) ? 2 : (px * t1 * t1 + qx * t1 + rx - bx)/ax
s2 = (0 > t2 || 1 < t2) ? 2 : (px * t2 * t2 + qx * t2 + rx - bx)/ax
if(s1 < s2) if(0<=s1)if(s1<=1) return t1
if(s2 < s1) if(0<=s2)if(s2<=1) return t2
if(s1 < 0)if(0<=s2)if(s2<=1)return t2
if(s2 < 0)if(0<=s1)if(s1<=1)return t1
return NaN
}
}
class Ball {
public var prevx:Number, prevy:Number
public var x:Number, y:Number
public var vx:Number, vy:Number
public function Ball() {
reset()
}
public function resolve(curve:Curve, t:Number):void {
with(curve) {
var dx:Number = (2 * p0x - 4 * p1x + 2 * p2x)*t + (-2 * p0x + 2 * p1x)
var dy:Number = (2 * p0y - 4 * p1y + 2 * p2y)*t + (-2 * p0y + 2 * p1y)
var d:Number = Math.sqrt(dx * dx + dy * dy)
dx /= d, dy /= d
var K:Number = 2 * (vx * dx + vy * dy)
x = bezier([p0x, p1x, p2x], t)
y = bezier([p0y, p1y, p2y], t)
vx = (K * dx - vx) * 0.7
vy = (K * dy - vy) * 0.7
if(vy < 0) {x -= -dy; y -= dx} else x += dy, y += -dx
}
}
public function reset():void {
vx = Math.random()*10-5, vy = Math.random()*10 - 5
prevx = x = Math.random()*550
prevy = y = 0
}
}