发新话题
打印

[action] 智能拼图游戏

智能拼图游戏

前两天在论坛看到有人用位图类操作制作了个拼图游戏。感觉很新鲜,很好很强大,我拿来稍稍改进 做成教程放给大家,游戏虽小五脏俱全,基本上每个游戏编程人员都经历过拼图游戏的制作。小小的游戏一番改造后涉及的知识面还是比较全的。

   制作一个拼图游戏,已经是个老的不想再被人拿出来提的话题,然而小游戏是不容小看的。因为制作方法的不同,因为创意元素等等,小游戏也是有生命力的。诸如此类的还有连连看,俄罗斯方块等依然是很多人初学的必经之路。

   思路:1.准备图片素材,(为了方便用户通过加载xml加载外部图片);

            2.分割图片         (这里用到位图类的操作);

            3.拖动判断   过关难度,时间。

没错一个拼图游戏无论怎么变换,其核心要素无非就这三点。那通过一个拼图游戏我们能应用到哪些知识呢,首先是xml,你至少要学会套用xml因为很多时候你用到xml时会发现到他的极大便利之处。接着是数组,(随机数组,二维数组) 然后位图类操作  增加些效果的时候用到缓动类 加载图片用到事件监听 ; 时间用到setInterval.......接下来我们还是具体来看看吧

第一步:在电脑中新建一个文件夹并准备6张图片(大小最好统一),这里flash文件与图片及xml放在同一目录下;

第二步:(制作xml)新建一个名为pic.txt文本在里面输入如下信息:

            <?xml version="1.0" encoding="utf-8"?>
<picLists>
  <item title="image1.jpg" />
  <item title="image2.jpg" />
  <item title="image3.jpg" />
  <item title="image4.jpg" />
  <item title="image5.jpg" />
  <item title="image6.jpg" />
</picLists>

保存文本并将后缀改为xml即可。(里面内容可根据自己需要更改)

第三步:创建flash;我们通过三帧代码完成,在第三帧新建一个元件timeBar。时间进度条。

打开动作面板

在第一帧输入以下代码 (详细解释)

stop();
var imag_array = new Array();//创建图片存放数组
var myxml = new XML();//新建一个XML对象
myxml.load("pic.xml");//加载外部的XML
myxml.ignoreWhite = true;//带有空白的文本节点不受影响
System.useCodepage = true;//防止乱码
myxml.onLoad = function(suc) {
if(suc){
var e = myxml.firstChild.childNodes;//XML 对象的子级的数组
for (var i = 0; i<e.length; i++) {
  imag_array.push(e
.attributes["title"]);//将“image1.jpg~image6”存放到数组
}
imag_array.sort(function () {
  return Math.round(Math.random()) ? 1 : -1;
});//老外写的强悍的一句话随机排列数组元素的方法。会用就行了。
}
};
//===初始化变量 walk  决定是否拼完了所有图片
var walk:Boolean = true;
//===   缓动类,图片产生运动特效 水平 垂直和旋转运动
import mx.transitions.Tween;
import mx.transitions.easing.*;
function img_mc_tween(target:MovieClip, xstart:Number, xend:Number, ystart:Number, yend:Number) {
var myTweenx:Tween = new Tween(target, "_x", Strong.easeOut, xstart, xend, 1, true);
var myTweeny:Tween = new Tween(target, "_y", Strong.easeOut, ystart, yend, 1, true);
var myTweenr:Tween = new Tween(target, "_rotation", Strong.easeOut, 0, 360, 1, true);
}
//===   loading 检测//舞台上建一个 load_txt用来显示加载进度
onEnterFrame = function () {
var l:Number = _root.getBytesLoaded();
var t:Number = _root.getBytesTotal();
var p:Number = Math.round(l/t)*100;
load_txt.text = "loading: "+p+"%";
if (l == t) {
  delete onEnterFrame;
  this.play();
}
};

第二帧什么动不输;为了循环使用第三帧的代码


[ 本帖最后由 sstpc 于 2008-1-25 23:57 编辑 ]

TOP

第三帧输入下列代码:

stop();
//导入位图等类
import flash.display.BitmapData;
import flash.filters.*;
import flash.geom.Rectangle;
import flash.geom.Point;
//   初始切割水平与垂直数,以及递增量
if (index == undefined && num == undefined) {
index = 0;
var n:Number = 4;
num = n;
} else {
//  最多水平与垂直数切割12刀
if (num<14) {
  num += 2;
}
//  取下一张图片                                                   
index += 1;
if (index>Number(imag_array.length-1)) {
  timeBar_mc._visible = false;
  walk = false;
  gameOver_txt.text = "你是拼图高手!";
  gameover();
}
}
now_txt.text = index+1+" / "+imag_array.length;//舞台新建一个now_txt用于显示第几张图
var mcImg:MovieClip = _root.createEmptyMovieClip("mcImg", -600);//创建一个空MC用来存放加载的图片
var bmp:BitmapData = new BitmapData(300, 347);//创建一个大小适中的位图,自己定义;用来将外部的图片转换成位图
var objLoad:Object = new Object();//创建一个OBJET对象,用来监听加载;
var myLoader:MovieClipLoader = new MovieClipLoader();//添加MovieClipLoader对象用于加载图片
//=======加载完成调用
objLoad.onLoadInit = function() {
bmp.draw(mcImg);//外部的图片转换成位图
};
mcImg._x = -1200;//把此MC移出舞台
myLoader.addListener(objLoad);
myLoader.loadClip(imag_array[index], mcImg);//存放数组编号的图片,index从0开始
var w:Number = bmp.width/num;//获得此位图的宽高
var h:Number = bmp.height/num;
var filter:BevelFilter = new BevelFilter(2, 45);// 新建一个滤镜对象
//====================
//===  将转换后的位图显示出来并为其添加滤镜特效 ======================================================================
showImage = this.createEmptyMovieClip("showImage", -5);
showImage.attachBitmap(bmp, -4);
showImage.filters = [new ConvolutionFilter(3, 3, [-2, -1, 0, -1, 1, 1, 0, 1, 2]), new ColorMatrixFilter([-1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0])];
//浮雕  底片效果,颜色反转
var x0:Number = Stage.width/2-showImage._width/2;
showImage._x = x0;
showImage._y = 10;//定位
showImage._alpha = 40;
var w0:Number = showImage._width;





//==============  各张小图片的坐标   ======================================================
var xy_array:Array = [];//创建二维数组
for (var i:Number = 0; i<num; i++) {
for (var j:Number = 0; j<num; j++) {
  xy_array.push([x0+i*w, j*h]);
}
}
//====================  画背景方格  ===================================================
this.createEmptyMovieClip("viewLine_mc", -1);
with (viewLine_mc) {
lineStyle(1, 0x669933, 80);
moveTo(0, 0);
lineTo(w, 0);
lineTo(w, h);
lineTo(0, h);
lineTo(0, 0);
_visible = false;
}
var init_array:Array = [];
for (var i:Number = 0; i<num*num; i++) {
init_array.push([i, 1]);
viewLine_mc.duplicateMovieClip("view"+i, i, {_x:xy_array[0], _y:10+xy_array[1]});
}

var k=1;
var finish_array:Array = new Array(num*num);//分割的图片数组
//=====  图片分割  响应MOUSEDOWN是因为位图从外部加载进来的。  ======================================================================================
_root.onMouseDown = function() {
if (k == 1) {
  k++;//只按一次
  for (var i:Number = 0; i<num*num; i++) {
   this["b"+i] = new BitmapData(w, h);//再创建一个位图对象,用来形成小图快
   //===============复制像素
   this["b"+i].copyPixels(bmp, new Rectangle(xy_array[0]-x0, xy_array[1], w, h), new Point(0, 0));
   this["mc"+i] = this.createEmptyMovieClip("mc"+i, this.getNextHighestDepth());
   this["mc"+i].attachBitmap(this["b"+i], this.getNextHighestDepth());
   this["mc"+i].no = 0;//初始对象属性
   this["mc"+i]._x = xy_array[0];
   this["mc"+i]._y = 10+xy_array[1];
   this["mc"+i].filters = [filter];
   //======  图片产生运动特效
   img_mc_tween(this["mc"+i], 10+xy_array[0], random(2) == 1 ? 10+random(160-w/2) : x0+w0+10+random(160-w/2), 10+xy_array[1], 10+random(bmp.height-h));
   //=====拖动
   this["mc"+i].onPress = function() {
    d = this.getDepth();
    this.swapDepths(_root.getNextHighestDepth());
    this.startDrag();
   };
   //=====判断
   this["mc"+i].onRelease = this["mc"+i].onReleaseOutside=function () {
    var n = this._name.substr(2, 3);//就是对应i的值
    var temNum:Number = 0;
    if (this.hitTest(_root["view"+n])) {
     this._x = _root["view"+n]._x;
     this._y = _root["view"+n]._y;
     // ==  对象属性变1,表示放对了
     this.no = 1;
     finish_array[n] = [n, 1];//存放放对的数组
     trace(finish_array[n])
     //  判断是否结束
     for (var i:Number = 0; i<num*num; i++) {
      if (finish_array[1] != undefined) {
       temNum += Number(finish_array[1]);//呵呵相当于temNUM+=1;
      }
      //====  如果两个二元数组中的元素一一对应了 ,游戏结束,重新出图        
      if (temNum == num*num && init_array[0] == finish_array[0] && init_array[1] == finish_array[1]) {
       gameover();
      }
     }
    } else {
     //======  图片产生运动特效
     img_mc_tween(this, this._x, random(2) == 1 ? 10+random(160-w/2) : x0+w0+10+random(160-w/2), this._y, 10+random(bmp.height-h));
    }
    this.swapDepths(d);
    this.stopDrag();
   };
  }
}
};
//=======  时间表
var s:Number = 0;
timeBar._xscale = 100;
function runTimer() {
s += 1;
//300 =五分钟
timeBar._xscale = 100-100*(s/300);
//=====                                                                                                                             
if (timeBar._xscale<=1) {
  gameover();
}
}
var ID:Number;
if (walk) {
ID = setInterval(runTimer, 1000);
}
//====  gameover                                                            
function gameover() {
clearInterval(ID);
for (var i:Number = 0; i<num*num; i++) {
  _root.bmp.dispose();
  _root["b"+i].dispose();
  _root["mc"+i].removeMovieClip();
  viewLine_mc.removeMovieClip();
  _root["view"+i].removeMovieClip();
}
timeBar_mc._xscale = 0;
if (walk) {
  gotoAndPlay(2);
}
}

至此游戏结束 舞台上需要三个动态文本前后名字分别为 load_txt now_txt  gameOver_txt 一个影片剪辑timeBar

ENJOY IT!

爱好flash小游戏编程的朋友们加我QQ群:22583847。


[ 本帖最后由 sstpc 于 2008-1-25 23:56 编辑 ]

TOP

我会坚持闪下去,直到真的闪了为止!QQ群:22583847

TOP

TOP

虽然现在还不懂,但还是对楼主说声谢谢.

TOP

我贴了代码怎么不出效果呢

TOP

好好学习。

TOP

厉害

TOP

牛啊!!不过不懂!!没事!!给我一个月!!!我把它都消化了!!

TOP

继续努力

TOP

呵呵,顶

TOP

哇,好难哦,lz真棒

TOP

LZ感谢分享了代码.但您能否提供源码下载?谢谢

TOP

发新话题