在2016年寒假,《复仇者联盟2》上映后,网上也推出了Flash小游戏。这是我当年根据效果自己模拟的破碎效果,可能稍微逊色。
在舞台上创建实例名称为img的影片剪辑,文件类填写Fragment。
package
{
//2016.02.11
//正弦前锋
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.geom.Point;
import flash.display.Shape;
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import fl.transitions.Tween;
import flash.geom.ColorTransform;
import flash.filters.GlowFilter;
public class Fragment extends Sprite
{
public var img:MovieClip;
private var pstartr:Number = Math.random() * 2;
private var pcenter:Point = new Point(400,300);
private var rounds:Array = [];
private var breakpoints:Number = 18;
private var pieces:Array = [];
private var pieces2:Array = [];
private var sps:Number;
private var stateW:Number = 800;
private var stateH:Number = 600;
private var lastR:Number;
private var lengths:Array;
private var played:Boolean = false;
private var compNum:Number = 0;
private var timer:Timer = new Timer(5);
public function Fragment()
{
img.gotoAndStop(1);
stage.addEventListener(MouseEvent.CLICK,onClick);
timer.addEventListener(TimerEvent.TIMER,onTimer);
}
private function getRound(r:Number,p:Number):Array
{
var angle:Number = 2 * Math.PI / p;
var pstart:Number = pstartr * Math.PI;
var pp:Array = [];
var i:Number;
for (i=1; i<=p; i++)
{
var vp:Number = pstart + angle * (i - 1);
var vx:Number = Math.cos(vp) * r + Math.random() / 5 * r;
var vy:Number = Math.sin(vp) * r + Math.random() / 5 * r;
pp[i] = new Point(Math.round(vx),Math.round(vy));
}
return pp;
}
private function getMost(p:Array):Object //找出坐标取最值的碎片
{
var t:Point = new Point ;
var i:Number;
var u:Array = new Array ;
var o:Object = new Object ;
var xmin:Number = 0;
var ymin:Number = 0;
t.x = p[1].x;
t.y = p[1].y;
for (i=1; i<p.length; ++i)
{
u[i] = new Point ;
u[i].x = p[i].x;
u[i].y = p[i].y;
}
for (i=2; i<p.length; ++i)
{
if (t.x > p[i].x)
{
t.x = p[i].x;
}
if (t.y > p[i].y)
{
t.y = p[i].y;
}
}
xmin = t.x;
ymin = t.y;
for (i=1; i<u.length; ++i)
{
u[i].x -= xmin;
u[i].y -= ymin;
}
o.arr = u;
o.x = xmin;
o.y = ymin;
return o;
}
private function getPieces(r:Array):MovieClip //绘制碎片多边形轮廓
{
var k:MovieClip = new MovieClip ;
k.graphics.beginFill(0x000000,1);
k.graphics.lineStyle(0,0x000000);
k.graphics.moveTo(r[1].x,r[1].y);
for (var i=2; i<r.length; ++i)
{
k.graphics.lineTo(r[i].x,r[i].y);
}
k.graphics.endFill();
return k;
}
public function breakIt(mc:MovieClip):void //破裂
{
var sp_z:Number = (Math.random()>0.2?-1:1)*Math.random() * 5;
var sp_y:Number = (mc.y - pcenter.y) * Math.random() / 7-40;
var sp_x:Number = (mc.x - pcenter.x) * Math.random() / 7;
sp_y = (sp_y < -40) ? -40:40;
var sp_rx:Number = (Math.random()>0.2?-1:1)*Math.random() * 10;
var sp_ry:Number = (Math.random()>0.2?-1:1)*Math.random() * 10;
var sp_rz:Number = (Math.random()>0.2?-1:1)*Math.random() * 10;
var dec_x:Number = (mc.x-pcenter.x)/Math.abs(mc.x-pcenter.x)*2;
mc.addEventListener(Event.ENTER_FRAME,fl_run);
function fl_run(e:Event):void //运动效果,每帧一循环
{
mc.z += sp_z / sps;
mc.y += sp_y / sps;
mc.x += sp_x / sps;
mc.rotationX += sp_rx / sps;
mc.rotationY += sp_ry / sps;
mc.rotationZ += sp_rz / sps;
sp_y += 10 / sps;
sp_x -= dec_x * 2 / sps;
if (sps>=4)
{
sps -= 0.01;
}
if (mc.y > stateH)
{
mc.removeEventListener(Event.ENTER_FRAME,fl_run);
mc.visible = false;
removeChild(mc);
++compNum;
if (compNum>=(lengths.length-1)*breakpoints)
{
played = false;
}
}
}
}
public function main():void
{
var i:Number;
var j:Number;
rounds = [];
for (i=0; i<=lengths.length-1; ++i)
{
rounds.push(getRound(lengths[i],breakpoints));
}
for (i=0; i<=lengths.length-2; ++i)
{
var ar:Array = [];
pieces[i] = new Array ;
pieces2[i] = new Array ;
for (j=1; j<=breakpoints; ++j)
{
var m:Number= (j+1>breakpoints)?1:(j+1);
var ok:Object = new Object ;
var br:Number=((Math.random()>0.6)?15:-15)*Math.random()*2; //随机生成各个近似同心圆碎片组合
ar[1] = rounds[i][j];
ar[2] = rounds[i + 1][j];
ar[3] = rounds[i + 1][m];
ar[4] = rounds[i][m];
ok = getMost(ar);
ar = ok.arr;
pieces[i][j] = getPieces(ar);
pieces[i][j].x = ok.x;
pieces[i][j].y = ok.y;
pieces[i][j].x += pcenter.x;
pieces[i][j].y += pcenter.y;
pieces2[i][j] = attachBitmap(img,pieces[i][j],br);
addChild(pieces2[i][j]);
}
}
}
public function onClick(e:MouseEvent):void
{
if (! played)
{
pcenter.x = stage.mouseX;
pcenter.y = stage.mouseY;
if (pcenter.x > stateW / 2)
{
lastR = pcenter.x * Math.sqrt(2);
}
else
{
lastR = (stateW - pcenter.x) * Math.sqrt(2);
}
lengths = new Array(20,80,240,lastR);
main();
sps = 6;
compNum = 0;
played = true;
img.gotoAndStop(img.currentFrame==img.totalFrames?1:(img.currentFrame+1));
timer.start();
}
}
public function onTimer(e:TimerEvent):void
{
timer.reset();
for (var i=0; i<=lengths.length-2; ++i)
{
for (var j=1; j<=breakpoints; ++j)
{
breakIt(pieces2[i][j]);
}
}
}
public function attachBitmap(mc:MovieClip,shape:MovieClip=null,brightness:Number=0):MovieClip
{
var datax:Number = shape.x;
var datay:Number = shape.y;
var rect:Rectangle = new Rectangle(datax,datay,shape.width,shape.height);
var bmp:BitmapData = new BitmapData(stateW*Math.sqrt(2),stateH*Math.sqrt(2),true,0x000000);
var nbmp:BitmapData = new BitmapData(shape.width,shape.height,true,0x000000);
var gf:GlowFilter=new GlowFilter((Math.random()>0.4)?(0x000000):(0xFFFFFF));
var bmp2:Bitmap = new Bitmap ;
var mc2:MovieClip = new MovieClip ;
var mc3:MovieClip = new MovieClip ;
gf.blurX = 2;
gf.blurY = 2;
gf.strength = 10;
bmp.fillRect(bmp.rect,0x000000);
bmp.draw(mc);
nbmp.lock();
nbmp.copyPixels(bmp,rect, new Point(0,0));
nbmp.unlock();
bmp2.bitmapData = nbmp;
mc2.addChild(bmp2);
shape.x = 0;
shape.y = 0;
mc3.addChild(mc2);
mc3.addChild(shape);
mc2.mask = shape;
mc3.z = 20 - Math.random() * 40;
mc3.x = datax;
mc3.y = datay;
mc3.filters = new Array(gf);
setBrightness(mc3,brightness);
return mc3;
}
public function setBrightness(obj:DisplayObject,value:Number):void //亮度调节
{
var colorTransformer:ColorTransform = obj.transform.colorTransform;
var backup_filters:* = obj.filters;
value /= 100;
if (value >= 0)
{
colorTransformer.blueMultiplier = 1 - value;
colorTransformer.redMultiplier = 1 - value;
colorTransformer.greenMultiplier = 1 - value;
colorTransformer.redOffset = 255 * value;
colorTransformer.greenOffset = 255 * value;
colorTransformer.blueOffset = 255 * value;
}
else
{
value = Math.abs(value);
colorTransformer.blueMultiplier = 1 - value;
colorTransformer.redMultiplier = 1 - value;
colorTransformer.greenMultiplier = 1 - value;
colorTransformer.redOffset = 0;
colorTransformer.greenOffset = 0;
colorTransformer.blueOffset = 0;
}
obj.transform.colorTransform = colorTransformer;
obj.filters.push(backup_filters);
}
}
}