您的位置: 首页 > 技术文档 > 多媒体制作 > Flash 区块游戏开发
Flash MX 2004 pro 帮助 CHM 版 回到列表 如何防止SWF文件被反编译
 Flash 区块游戏开发

作者:qhwa 时间: 2004-05-22 文档类型:原创 来自:蓝色理想

第 1 页 欢迎
第 2 页 为什么用方块?
第 3 页 地图
第 4 页 关于地图的东西
第 5 页 创建方块
第 6 页 再谈谈区块原型的定义
第 7 页 英雄/主角
第 8 页 键盘控制的移动
第 9 页 碰撞检测
第 10 页 芝麻开门-地图切换
第 11 页 跳跃
第 12 页 腾云驾雾
第 13 页 梯子
第 14 页 愚蠢的敌人
第 15 页 更多关于敌人的东西
第 16 页 射击
第 17 页 拾取物品
第 18 页 浮动区块
第 19 页 卷屏
第 20 页 未完待续 | coming soon

本页由Kalloer翻译,在此深表谢意

卷屏

在我们开始这部分之前,有件事得先解释清楚。Flash很慢。Flash非常慢。卷屏意味着以每秒20-30次的速度移动屏幕上数以百计的方块。而太多移动的方块意味着Flash不能及时地完成重绘,于是速度下降。你的游戏将慢得像条睡着的蜗牛在爬。
“什么?”你可能会问,“难道不用卷屏吗?怎么会慢得像睡着的蜗牛在爬呢?”
你可以用移动的方块,但是你得小心,别让卷屏的区域太大,而且移动的方块别太多。多大算“太大”,多少又算“太多”,这就得你自己体会了。记住,Flash游戏大多数时候是在浏览器上玩的,游戏者可能同时打开了多个窗口,后台可能有多个程序在同时运行,而且不是所有游戏者都有那么好的电脑配置。可以用低配置的电脑来测试你的游戏,如果觉得速度慢,就把它改小点。
来看看我们接下来要做的:

原理

左边的图中是非卷屏游戏。主角向右移动,而其它的东西原地不动。现在看右边的图,这是个卷屏游戏。主角仍然是要向右移动,但是我们实际上并没有移动主角,为了让他看起来是在向仍然右移动,我们将其它东西向左移了。

所以,原理很简单:
当需要变换主角的位置时,向反方向移动其它部分就行了。但是,由于我们习惯于将主角与其它背景区块一起放入MC中,主角会跟他们一起往反方向移动。为了固定主角的位置,我们仍然将所有物体向反方向移,同时,将主角向正确的方向移动相同的距离。

来看个卷屏游戏的例子。假设主角要向右移10px。我们先将所有方块(包括主角)向左移10px,并将主角向右移10px。最后看起来主角并没有动,而其它方块向左移了。

卷屏的最简单的方法是将所有方块都放到屏幕上,但是只显示其中一小部分,然后整个一起移动。这可能会让你的游戏速度非常慢,因为没显示出来的那上千个方块也在移动。另一个办法是将移出可见区域的方块删除,并在另一头添加新的方块。这会好一点儿,但是Flash花费在删除/复制MC上的时间又太多了。
最后一个办法是:只把可见部分的方块放到舞台上,当它们移出可见区域时,我们将相同的方块移动到另一端,重命名,并再次使用相同的MC。这被称作“gotoAndStop”卷屏引擎:

如图所示,当方块从右边消失,我们将它移动到左边。同时我们要重命名MC,因为所有的MC都是以“t_3_4”(表示它位于y=3,x=4)这样的名字命名的。而在新位置的方块可能要显示不同的帧(图片)。这就是为什么我们要将它发送到含有正确图片的帧,也是这种方法叫做“gotoAndStop”的原因。

准备卷屏

在大多数卷屏游戏中,主角的位置是始终在屏幕中央的。

你可以看见,主角左边的方块数和右边的方块数是相等的。这就是说,总的列数是3、5、7、9、11……而绝不会是2、4、6、8。行数也是一样。
来声明一个游戏对象:
game = {tileW:30, tileH:30, currentMap:1, visx:7, visy:5, centerx:120, centery:90};
属性 visx 代表可见的列数,visy 代表可见的行数。我们还需要属性centerx/centery来标记影片的中心点。

当我们移动方块时,可能需要显示一些在地图数组中没有声明的方块。例如,当主角高高兴兴地走到地图数组中已声明的最左边的方块上以后,就需要显示更左边的方块。对于这类方块,我们会建立新的不含图片的方块类型(这样对Flash来说负担比较小)。在方块MC的第20帧创建关键帧。以下是声明这类方块的代码:
game.Tile4 = function () { };
game.Tile4.prototype.walkable = false;
game.Tile4.prototype.frame = 20;

你可能还想部分地遮住一些方块,这就需要新建含有名为“frame”的关联的新MC,该MC的中间挖空,只显示经过挖空处的方块。

建立卷屏的世界

让我们从 buildMap 函数开始。
function buildMap (map) {
_root.attachMovie("empty", "tiles", 1);
game.halfvisx=int(game.visx/2);
game.halfvisy=int(game.visy/2);

我们将为game对象计算两个新的属性。halfvisx和halfvisy被分别用来存放主角与可见区域边缘之间的列数和行数。当总列数visx=5时,halfvisx=2,就是说主角右边有2列、左边有2列,中间就是主角所在的那一列。

game.clip = _root.tiles;
game.clip._x = game.centerx-(char.xtile*game.tileW)-game.tileW/2;
game.clip._y = game.centery-(char.ytile*game.tileH)-game.tileH/2;

我们得根据以下两个变量的值来决定包含主角和所有方块的MC的位置:游戏的中心点和主角的位置。游戏的中心点在game对象中由centerx/centery声明;主角的位置在char对象中由xtile/ytile声明。当主角被放在x坐标的(char.xtile*game.tileW)+game.tileW/2处时,方块MC必须被放在相反的坐标上,所以我们要用centerx减去这个值。

for (var y = char.ytile-game.halfvisy; y<=char.ytile+game.halfvisy+1; ++y) {
    for (var x = char.xtile-game.halfvisx;
    x<=char.xtile+game.halfvisx+1; ++x) {
        var name = "t_"+y+"_"+x;
        if(y>=0 and x>=0 and y<=map.length-1 and x<=map[0].length-1){
            game[name] = new game["Tile"+map[y][x]]();
        }else{
            game[name] = new game.Tile4();
        }
        game.clip.attachMovie("tile", name, 1+y*100+x*2);
        game.clip[name]._x = (x*game.tileW);
        game.clip[name]._y = (y*game.tileH);
        game.clip[name].gotoAndStop(game[name].frame);
   }
}

这个循环创建了所有的可见方块对象,并且复制该方块对象相应的MC到舞台上。如你所见,这个循环并不是从0开始,而是从ytile-halfvisy开始。同理它也不是在map数组的末尾结束的,而是在ytile+halfvisy+1结束。然后,if条件句检查将被创建的方块是否已经在map数组中。如果不在,我们就使用tile4模版中的空白方块。
为了使卷屏的过程平滑,我们得在舞台右边和底部分别增加一行和一列方块。这些方块可以保证,哪怕我们把半个方块移到舞台的另一边,也不会出现任何空白区域。
_root.attachMovie("frame", "frame", 100);
最后一行复制帧来覆盖影片中你不想显示的区域。

char.clip = game.clip.char;
char.x = (char.xtile*game.tileW)+game.tileW/2;
char.y = (char.ytile*game.tileW)+game.tileW/2;
char.width = char.clip._width/2;
char.height = char.clip._height/2;
char.clip._x = char.x;
char.clip._y = char.y;
char.clip.gotoAndStop(char.frame);
char.xstep=char.x;
char.ystep=char.y;

char的创建方法与前面一样。仅有的不同是增加了两个新的属性:xstep和ystep。我们将在后面用它们来检查当前是否是移动方块行或列到另一端的合适时间。

卷屏!卷屏!

既然卷屏的世界已经建好了,下面就该让它真正“卷”动起来了。在为主角计算出ob.xtile/ob.ytile的值以后,在moveChar函数的末尾加上如下代码来进行卷屏:
game.clip._x = game.centerx-ob.x;
game.clip._y = game.centery-ob.y;
if(ob.xstep<ob.x-game.tileW){
    var xtile = Math.floor(ob.xstep/game.tileW) + 1;
    var xnew=xtile+game.halfvisx+1;
    var xold=xtile-game.halfvisx-1;
    for (var i = ob.ytile-game.halfvisy-1; i<=ob.ytile+game.halfvisy+1; ++i) {
       changeTile (xold, i, xnew, i, _root["myMap"+game.currentMap]);
    }
    ob.xstep=ob.xstep+game.tileW;
} else if(ob.xstep>ob.x){
    var xtile = Math.floor(ob.xstep/game.tileW);
    var xnew=xtile+game.halfvisx+1;
    var xold=xtile-game.halfvisx-1;
    for (var i = ob.ytile-game.halfvisy-1; i<=ob.ytile+game.halfvisy+1; ++i) {
        changeTile (xold, i, xnew, i, _root["myMap"+game.currentMap]);
    }
    ob.xstep=ob.xstep-game.tileW;
}
if(ob.ystep<ob.y-game.tileH){
    var ytile = Math.floor(ob.ystep/game.tileH)+1;
    var ynew=ytile+game.halfvisy+1;
    var yold=ytile-game.halfvisy-1;
    for (var i = ob.xtile-game.halfvisx-1; i<=ob.xtile+game.halfvisx+1; ++i) {
        changeTile (i, yold, i, ynew, _root["myMap"+game.currentMap]);
    }
    ob.ystep=ob.ystep+game.tileH;
} else if(ob.ystep>ob.y){
    var ytile = Math.floor(ob.ystep/game.tileH);
    var yold=ytile+game.halfvisy+1;
    var ynew=ytile-game.halfvisy-1;
    for (var i = ob.xtile-game.halfvisx-1; i<=ob.xtile+game.halfvisx+1; ++i) {
        changeTile (i, yold, i, ynew, _root["myMap"+game.currentMap]);
    }
    ob.ystep=ob.ystep-game.tileH;
}
return (true);

首先,我们根据中心点的位置和主角的坐标值将包含主角和所有方块的game.clip放到相应的位置。然后我们写了4段相似的代码,每一段定义一个方向。当主角的移动距离大于方块的大小时,循环会调用含有相应变量的changeTile函数。循环结束,方块被移动/重命名/修改以后,就该更新属性ystep/xstep的值了。

现在,让我们来编写changeTile函数:

function changeTile (xold, yold, xnew, ynew, map) {
 var nameold = "t_"+yold+"_"+xold;
 var namenew = "t_"+ynew+"_"+xnew;
 if(ynew>=0 and xnew>=0 and ynew<=map.length-1 and xnew<=map[0].length-1){
  game[namenew] = new game["Tile"+map[ynew][xnew]]();
  game.clip[nameold]._name = namenew;
  game.clip[namenew].gotoAndStop(game[namenew].frame);
  game.clip[namenew]._x = (xnew*game.tileW);
  game.clip[namenew]._y = (ynew*game.tileH);
 }else{
  game[namenew] = new game.Tile4();
  game.clip[nameold]._name = namenew;
  game.clip[namenew].gotoAndStop(game[namenew].frame);
 }
}

这样,我们会分别得到方块的2个旧的和2个新的坐标值。为了检查方块是否还在map数组之内,我们还增加了map参数。 “nameold”是这些方块的旧名字,而“namenew”是它们的新名字。在我们用新名字创建了新的tile对象以后,语句:
game.clip[nameold]._name = namenew;
将方块MC重命名。新的MC是空的,所以我们不必将它放到新的_x/_y,让它留在原处就行了。

下载源文件

出处:蓝色理想
责任编辑:qhwa

上一页 浮动区块 下一页 未完待续 | coming soon

◎进入论坛Flash专栏版块参加讨论

相关文章 更多相关链接
Flash 酷站猎手
中文ID3乱码问题MX解决方案
用AS2解决中文ID3的乱码
Flash常用效果-移动模糊效果
Flash MX 2005 制作环境预览
作者文章 更多作者文章
中文ID3乱码问题MX解决方案
Flash 区块游戏开发
Flash 中如何显示清晰的字体
JavaScript 和 Flash 的通信
在 ListBox 组件中应用 HTML
关键字搜索 常规搜索 推荐文档
热门搜索:CSS Fireworks 设计比赛 网页制作 web标准 用户体验 UE photoshop Dreamweaver Studio8 Flash 手绘 CG
站点最新 站点最新列表
周大福“敬•自然”设计大赛开启
国际体验设计大会7月将在京举行
中国国防科技信息中心标志征集
云计算如何让安全问题可控
云计算是多数企业唯一拥抱互联网的机会
阿里行云
云手机年终巨献,送礼标配299起
阿里巴巴CTO王坚的"云和互联网观"
1499元买真八核 云OS双蛋大促
首届COCO桌面手机主题设计大赛
栏目最新 栏目最新列表
浅谈JavaScript编程语言的编码规范
如何在illustrator中绘制台历
Ps简单绘制一个可爱的铅笔图标
数据同步算法研究
用ps作简单的作品展示页面
CSS定位机制之一:普通流
25个最佳最闪亮的Eclipse开发项目
Illustrator中制作针线缝制文字效果
Photoshop制作印刷凹凸字体
VS2010中创建自定义SQL Rule
>> 分页 首页 前页 后页 尾页 页次:19/201个记录/页 转到 页 共20个记录

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
网站可用性测试及优化指南
《写给大家看的色彩书1》
《跟我去香港》
众妙之门—网站UI 设计之道
《Flex 4.0 RIA开发宝典》
《赢在设计》
犀利开发—jQuery内核详解与实践
作品集 更多内容

杂⑦杂⑧ Gold NORMANA V2