返回列表 回复 发帖

随机切凹凸拼图效果(bitmapData)[附源码]

下午没事做,就弄了个随机切拼图效果,还没做判断,只是个切法的计算,稍后整理下就应该是个成品,嘿嘿~
原理主要就是用bitmap进行切图,以前都是用遮照做太占资源.
效果如下:


主要代码:puzzle.as
  1. /*
  2. * Puzzle CLASS
  3. *
  4. * @ CREATED BY: ycccc8202
  5. * @ PURPOSE: 方便制作拼图游戏
  6. * @ DATE:2007.6.10
  7. * Usage example:
  8. * var url:String = "http://pic.ent.tom.com/data2/upload/888/407/117984810018150686780.jpg";
  9. * var puzzleuzzle = new Puzzle(this, url);
  10. * 设置摆放位置
  11. * puzzle.setPosition(30, 20);
  12. * 设置行/列
  13. * puzzle.setRowAndLine(30, 10);
  14. */
  15. import com.ycccc.PuzzleGame.MovieClipDrag;
  16. import mx.events.EventDispatcher;
  17. import flash.display.BitmapData;
  18. import flash.geom.Point;
  19. import flash.geom.Matrix;
  20. import flash.geom.Rectangle;
  21. import flash.filters.BevelFilter;
  22. class com.ycccc.PuzzleGame.Puzzle {
  23. /**
  24. * Private members
  25. */
  26. //////////加载图片长宽///////////
  27. private var _imageW:Number;
  28. private var _imageH:Number;
  29. //////////设置最大宽高///////////
  30. private var _imageMaxW:Number = 800;
  31. private var _imageMaxH:Number = 500;
  32. ////////////////////////////////
  33. private var dispatchEvent:Function;
  34. public var addEventListener:Function;
  35. public var removeEventListener:Function;
  36. ////////////////////////////////
  37. private var _oldURL:String;
  38. private var _newURL:String;
  39. private var _x:Number;
  40. private var _y:Number;
  41. private var _row:Number;
  42. private var _line:Number;
  43. private var _path:MovieClip;
  44. private var _imageM:MovieClip;
  45. private var _pieceBoard:MovieClip;
  46. private var _imageLoader:MovieClipLoader;
  47. private var _imageBitmap:BitmapData;
  48. private var _pieceW:Number;
  49. private var _pieceH:Number;
  50. private var _pieceMinWH:Number;
  51. private var _pieceD:Number;
  52. ///////////内切矩形宽高(通过矩形画近似椭圆)///////////
  53. private var _pieceOW:Number;
  54. private var _pieceOH:Number;
  55. ///////////////比例系数///////////////
  56. private var _pieceD_k:Number = 10;
  57. private var _pieceO_k:Number = 4;
  58. private var _pieceOWH_k:Number = 3/4;
  59. /////////////////////////////////
  60. /**
  61. * Constructor
  62. */
  63. public function Puzzle(path:MovieClip, imageLink:String) {
  64.   EventDispatcher.initialize(this);
  65.   _path = path;
  66.   _newURL = imageLink;
  67.   _imageM = _path.createEmptyMovieClip("imageM", _path.getNextHighestDepth());
  68.   _imageLoader = new MovieClipLoader();
  69.   _imageLoader.addListener(this);
  70.   loadImage(_newURL);
  71. }
  72. /**
  73. * Public methods
  74. */
  75. public function set _url(url:String) {
  76.   loadImage(url);
  77. }
  78. public function get _url():String {
  79.   return _oldURL;
  80. }
  81. public function set row(r:Number) {
  82.   _row = r;
  83. }
  84. public function set line(l:Number) {
  85.   _line = l;
  86. }
  87. public function removeAllPiece() {
  88.   for (var all in _pieceBoard) {
  89.    _pieceBoard[all].removeMovieClip();
  90.   }
  91. }
  92. public function bitmapCut() {
  93.   pieceSet();
  94.   removeAllPiece();
  95.   for (var i:Number = 0; i<_row; i++) {
  96.    for (var j:Number = 0; j<_line; j++) {
  97.     var Piece = _pieceBoard.createEmptyMovieClip("iece"+(_line*i+j), _pieceBoard.getNextHighestDepth());
  98.     Piece.beginBitmapFill(_imageBitmap, new Matrix(1, 0, 0, 1, -j*_pieceW, -i*_pieceH), true, true);
  99.     Piece._x = j*_pieceW;
  100.     Piece._y = i*_pieceH;
  101.     Piece.i = i;
  102.     Piece.j = j;
  103.     new MovieClipDrag(Piece);
  104.     drawPiece(Piece, getAllDotArray(Piece));
  105.     //画小块形状
  106.     Piece.filters = [new BevelFilter(3, 30)];
  107.    }
  108.   }
  109. }
  110. public function setMaxWH(w:Number, h:Number) {
  111.   //设置允许的最大宽高
  112.   _imageMaxW = w;
  113.   _imageMaxH = h;
  114. }
  115. public function setRowAndLine(row:Number, line:Number) {
  116.   //设置切割的 行/列
  117.   if (row<=0 || line<=0) {
  118.    trace("行/列不能为0,按默认10*10进行切图");
  119.    return;
  120.   }
  121.   if (row*line>900) {
  122.    trace("数量太大,运算困难,按默认10*10进行切图");
  123.    return;
  124.   }
  125.   _row = row;
  126.   _line = line;
  127. }
  128. public function setPosition(x:Number, y:Number) {
  129.   //设置
  130.   if (x<0 || y<0) {
  131.    trace("超出场景范围,按默认(0,0)位置进行摆放");
  132.    return;
  133.   }
  134.   _x = x;
  135.   _y = y;
  136.   if (_pieceBoard<>undefined) {
  137.    _pieceBoard._x = _x;
  138.    _pieceBoard._y = _y;
  139.   }
  140. }
  141. public function getPieceBoard():MovieClip {
  142.   //取得碎片载体
  143.   return _pieceBoard;
  144. }
  145. public function toString():String {
  146.   return "uzzle::凹凸形状的拼图切割";
  147. }
  148. /**
  149. * Private methods
  150. */
  151. private function loadImage(url:String) {
  152.   _newURL = url;
  153.   try {
  154.    _imageLoader.loadClip(_newURL, _imageM);
  155.   } catch (e:Error) {
  156.    trace(e);
  157.   }
  158. }
  159. private function onLoadStart(target:MovieClip) {
  160.   target._visible = false;
  161.   dispatchEvent({type:"onStart", target:this});
  162. }
  163. private function onLoadError(target:MovieClip, errorCode:String) {
  164.   dispatchEvent({type:"onError", target:this});
  165.   trace("errorCode:"+errorCode);
  166.   trace("出错,继续读取上张图片");
  167.   _newURL = _oldURL;
  168.   loadImage(_newURL);
  169. }
  170. private function onLoadInit(target:MovieClip) {
  171.   dispatchEvent({type:"onInit", target:this});
  172.   _oldURL = _newURL;
  173.   if (target._width<10 || target._height<10) {
  174.    throw new Error("图片太小,不适合切割!");
  175.   }
  176.   if (isNaN(_imageMaxW+_imageMaxH)) {
  177.    _imageMaxW = _imageMaxH=600;
  178.   }
  179.   if (isNaN(_row+_line)) {
  180.    _row = 10;
  181.    _line = 10;
  182.   }
  183.   _imageW = target._width>_imageMaxW ? _imageMaxW : target._width;
  184.   _imageH = target._height>_imageMaxH ? _imageMaxH : target._height;
  185.   _pieceBoard.removeMovieClip();
  186.   mcToBitmap(target);
  187. }
  188. private function mcToBitmap(mc:MovieClip) {
  189.   _imageBitmap = new BitmapData(_imageW, _imageH, true, 0x00ffffff);
  190.   _imageBitmap.draw(mc);
  191.   //隐藏掉
  192.   _pieceBoard = _path.createEmptyMovieClip("pieceBoard", _path.getNextHighestDepth());
  193.   _pieceBoard._x = _x;
  194.   _pieceBoard._y = _y;
  195.   bitmapCut();
  196. }
  197. private function pieceSet() {
  198.   _pieceW = _imageW/_line;
  199.   _pieceH = _imageH/_row;
  200.   _pieceMinWH = Math.min(_pieceW, _pieceH);
  201.   _pieceD = _pieceMinWH/_pieceD_k;
  202.   _pieceOW = _pieceMinWH/_pieceO_k;
  203.   _pieceOH = _pieceOW/_pieceOWH_k;
  204. }
  205. private function getRndD():Number {
  206.   //返回与边界错开的高度
  207.   return _pieceD-Math.random()*2*_pieceD;
  208. }
  209. private function drawPiece(mc:MovieClip, dotArr:Array):Void {
  210.   with (mc) {
  211.    lineStyle(0);
  212.    moveTo(0, 0);
  213.    for (var k:Number = 0; k<dotArr.length; k++) {
  214.     if (dotArr[k].x<>undefined) {
  215.      lineTo(dotArr[k].x, dotArr[k].y);
  216.     } else {
  217.      curveTo(dotArr[k][0].x, dotArr[k][0].y, dotArr[k][1].x, dotArr[k][1].y);
  218.     }
  219.    }
  220.    endFill();
  221.   }
  222. }
  223. private function getOvalDotArray(mc:MovieClip, position:String):Array {
  224.   var rnd:Number = random(2) ? 1 : -1;
  225.   var circleDotArr:Array = [];
  226.   switch (position) {
  227.   case "right" :
  228.    var a0oint = new Point(_pieceW+getRndD(), (_pieceH-_pieceOW)/2+_pieceOW/4-Math.random()*_pieceOW/2);
  229.    var a1:Array = [new Point(a0.x+rnd*(_pieceOH/2), a0.y-_pieceOW/2), new Point(a0.x+rnd*_pieceOH, a0.y)];
  230.    var a2:Array = [new Point(a0.x+rnd*(_pieceOH+_pieceOW/3), a0.y+_pieceOW/2), new Point(a0.x+rnd*_pieceOH, a0.y+_pieceOW)];
  231.    var a3:Array = [new Point(a0.x+rnd*_pieceOH/2, a0.y+_pieceOW+_pieceOW/2), new Point(a0.x, a0.y+_pieceOW)];
  232.    circleDotArr = [a0, a1, a2, a3];
  233.    break;
  234.   case "down" :
  235.    var a0oint = new Point(_pieceW-((_pieceW-_pieceOW)/2+_pieceOW/4-Math.random()*_pieceOW/2), _pieceH+getRndD());
  236.    var a1:Array = [new Point(a0.x+_pieceOW/2, a0.y+rnd*(_pieceOH/2)), new Point(a0.x, a0.y+rnd*_pieceOH)];
  237.    var a2:Array = [new Point(a0.x-_pieceOW/2, a0.y+rnd*(_pieceOH+_pieceOW/3)), new Point(a0.x-_pieceOW, a0.y+rnd*_pieceOH)];
  238.    var a3:Array = [new Point(a0.x-_pieceOW-_pieceOW/2, a0.y+rnd*_pieceOH/2), new Point(a0.x-_pieceOW, a0.y)];
  239.    circleDotArr = [a0, a1, a2, a3];
  240.    break;
  241.   }
  242.   return circleDotArr;
  243. }
  244. private function getAllDotArray(mc:MovieClip):Array {
  245.   var allDotArray:Array = [];
  246.   //a,b,c,d四面
  247.   if (mc.i == 0) {
  248.    mc.a = [];
  249.   } else {
  250.    var tempArray:Array = mc._parent["iece"+(Number(mc._name.substr(5))-_line)].c;
  251.    var a:Array = new Array(4);
  252.    a[0] = new Point(tempArray[3][1].x, tempArray[3][1].y-_pieceH);
  253.    a[1] = [new Point(tempArray[3][0].x, tempArray[3][0].y-_pieceH), new Point(tempArray[2][1].x, tempArray[2][1].y-_pieceH)];
  254.    a[2] = [new Point(tempArray[2][0].x, tempArray[2][0].y-_pieceH), new Point(tempArray[1][1].x, tempArray[1][1].y-_pieceH)];
  255.    a[3] = [new Point(tempArray[1][0].x, tempArray[1][0].y-_pieceH), new Point(tempArray[0].x, tempArray[0].y-_pieceH)];
  256.    mc.a = a;
  257.   }
  258.   if (mc.j == 0) {
  259.    mc.d = [];
  260.   } else {
  261.    var tempArray:Array = mc._parent["Piece"+(Number(mc._name.substr(5))-1)].b;
  262.    var a:Array = new Array(4);
  263.    a[0] = new Point(tempArray[3][1].x-_pieceW, tempArray[3][1].y);
  264.    a[1] = [new Point(tempArray[3][0].x-_pieceW, tempArray[3][0].y), new Point(tempArray[2][1].x-_pieceW, tempArray[2][1].y)];
  265.    a[2] = [new Point(tempArray[2][0].x-_pieceW, tempArray[2][0].y), new Point(tempArray[1][1].x-_pieceW, tempArray[1][1].y)];
  266.    a[3] = [new Point(tempArray[1][0].x-_pieceW, tempArray[1][0].y), new Point(tempArray[0].x-_pieceW, tempArray[0].y)];
  267.    mc.d = a;
  268.   }
  269.   if (mc.i == _row-1) {
  270.    mc.c = [];
  271.   } else {
  272.    mc.c = getOvalDotArray(mc, "down");
  273.   }
  274.   if (mc.j == _line-1) {
  275.    mc.b = [];
  276.   } else {
  277.    mc.b = getOvalDotArray(mc, "right");
  278.   }
  279.   allDotArray = allDotArray.concat(mc.a);
  280.   allDotArray.push(new Point(_pieceW, 0));
  281.   allDotArray = allDotArray.concat(mc.b);
  282.   allDotArray.push(new Point(_pieceW, _pieceH));
  283.   allDotArray = allDotArray.concat(mc.c);
  284.   allDotArray.push(new Point(0, _pieceH));
  285.   allDotArray = allDotArray.concat(mc.d);
  286.   return allDotArray;
  287. }
  288. }
复制代码
//切的方法见图所示,算法中加些随机数值就能产生随机效果了
//主要难点可能只在如何切椭圆,这里通过矩形边界外加上控制点来进行curveTo画曲线,形成个椭圆状
PS:::压缩包中的 Puzzle.exe 支持文本框中填本地图片和网络图片地址 : ),介于安全沙漏问题,只能打包成exe才方便调取网络图片~

[ 本帖最后由 ycccc8202 于 2007-6-11 09:56 编辑 ]
puzzle.gif
2.gif

PuzzleByBitmap_.swf (181.75 KB)

Puzzel.rar (951.6 KB)

喜帖街my blog
ycccc的計算能力越來越厲害了喔
var str = "5375-7065-722d-546f-6d61-746f", val = "";
str = str.split("-").join("");
for(var i=0; i<str.length; i+=2)
val += chr(parseInt(str.substr(i,2), 16));
trace(val)
不得了,不得了了!!!!

牛啊!!
我的偶像啊,希望斑竹大人分享源码,谢谢。
临时写的,还没整理,等我整理好再发上来分享~
喜帖街my blog
斑竹的”头像“由黄脸婆到“美少女”,让我想入非非。随机切凹凸的欣赏效果不是很好,要是把画面改成鲜艳的亮色就好了。
承接flash特效制作
哇,真方便!
ding ~
看不懂哈
顶~~~~~~~~~~~
 切块写得不错,可惜就是拼的时候没有吸附功能
嘿嘿,吸附啊,判断落位啊,群动等等那些都比较简单,和已往的矩形块拼图类似,我就不做了,再做就是成品了....哈~
喜帖街my blog
厉害~学习中~
兲空的雲
ycccc8202 计算果然超强啊
自叹不如了
Bitmap 我特喜欢  不过没研究太明白
以爱你的方式活着,
录在别人的眼中,却无法被你看到。
此时此刻,你无论如何也无法理解我孤独的含义!

                                               ——冷的像风
欢迎你来我这里做客
详细讲原理 坛主都说了 不许贴代码 呵呵

偶就是不懂
http://zszen.com/blog
fla文件中trace(puzzle) 调用类文件的toString函数,不明白哦
那个就是默认的 如果没有就返回此对象  如果有toString定义就返回这个定义的内容
里面可以是字符串 /布尔
http://zszen.com/blog
哦~~多谢LS
赞!AS好强的说
這個算法不錯。贊一個。。
梦总是停在你触手可及的地方,所以你要有勇气伸出你渴望成功的手……
果然够牛,顶!学习、、、
版主能否根据原理写个教程出来呢。我觉得说出原理对学习者更好。
yccc果然是牛市之中的又一牛人,佩服
牛!

我学了一下Bitmap,三天不摸都手艺生,我又有三个月没摸了,全搞忘了。
向大家学习!
真牛呀...呵呵..写得真好.学习.
好一个高手.思路独特.佩服
惊叹中

牛呀
赞啊~~~~
不得不佩服!!!

UP
好厉害   
帮顶!
拜服!
ycccc8202师傅快教我绝世武功,我要去维护世界和平!
我的全flash小站http://www.ourme.cn
返回列表