zoukankan      html  css  js  c++  java
  • 从零开始学AS3游戏开发【六】 设置地图

    注:本系列教程每周一篇,旨在引导刚刚接触FLASH的新手通过实例进行游戏开发的学习。在过程中逐步说明涉及到的类及对应的使用方法。从一个光秃秃的方块开始,根据不同的控制方式、玩法产生不同的分支,最终完善成一个个可玩的游戏。希望对各位入门的朋友有所帮助!在教程涉及的各种处理方法,可能不够完善,也希望各位高手指正:)

    转载请注名来源于天地会

    前篇勘误:在Monster.as中,第44行对计算频率进行控制时,if (date.time-_lastAction.time > _fps/1000)应为if (date.time-_lastAction.time > 1000/_fps)。感谢各位兄弟的提示!

    第六篇 设置地图

    上一篇教程中。我们对游戏进行了美化,同时加入了简单的碰撞检测。在本篇中,我们将设置地图,先来看一下我们预期的效果
    1.jpg 

    像上图这样,如果像我们原来那样通过for循环去生成地图,那基本上写if和else就可以把我们累死了。我们需要寻找规律,来达到批量处理的目的。

    从上图我们可以看出,所有的游戏对象都是比较整齐的摆放的。摆放的间距也基本上与游戏对象的宽度成比例。如果我们把可以通过的位置以0来表示,不能通过的位置以1来表示,那么,可以得到下图:
    2.jpg 

    这让你想到了什么吗?是的,是数组,我们可以用数组来标识地图:

    1. private var mapconfig:Array = [
    2.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    3.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    4.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    5.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    6.                         [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1],
    7.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    8.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    9.                         [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1],
    10.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    11.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]                        
    12.                 ];
    复制代码

    在上面这个数组中,mapconfig[line]记录了第line行的全部地图元素,例如,当line为0的时候,也就是mapconfig[0]的元素“[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]”,可以看出,在这一行中,全部都是空位置。而当line为1的时候,mapconfig[1]的元素“[0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0]”告诉我们,中间有6个元素的位置是障碍物,无法通过。同样的,我们可以用2来表示敌人出现的位置,用3来表示自己的坦克出现的位置,于是,上面的数组就变成了现在这样

    1. private var mapconfig:Array = [
    2.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
    3.                         [0, 2, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    4.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    5.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    6.                         [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1],
    7.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    8.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    9.                         [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1],
    10.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    11.                         [0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]                        
    12.                 ];
    复制代码

    可以看出,在第一行的倒数第三个位置,出现了一个敌人,在第二行的第二个位置,出现了一个敌人,而自己则出现在最后一行的第五个元素。如果你喜欢用y来表示行,用x来表示列的话,那么第y行第x列的地图元素数据应该为mapconfig[y][x]。

    好了,下面让我们来用程序实现对这个地图数据的解析。

    我们新建一个类,继承自gameScene,暂时定义为D5Scene吧,当然,如果你喜欢其他的名字,可以自己定义:)

    在这个类里,我们声明一个用来保存地图数据的变量

    1.                 /**
    2.                  * 地图数据
    3.                  */
    4.                 protected var _mapData:Array;
    复制代码

    还有一个解析方法,我们需要对_mapData进行循环解析,把其中的数字转换成可以通过的位置,或者障碍物,或者敌人,或者我们自己的角色。

    1.                  /**
    2.                  * 配置地图
    3.                  * 
    4.                  * @param        arr        地图数据
    5.                  */
    6.                 public function setup(arr:Array):void
    7.                 {
    8.                         _mapData = arr;
    9.                         if (arr[0] == null || arr[0][0]==null) return;
    10.                         var y:uint = 0;
    11.                         var x:uint;
    12.                         
    13.                         for each(var line:Array in arr)
    14.                         {
    15.                                 x = 0;
    16.                                 for each(var data:uint in line)
    17.                                 {
    18.                                         if (data != 0)
    19.                                         {
    20.                                                 
    21.                                         }
    22.                                         x++;
    23.                                 }
    24.                                 y++;
    25.                         }
    26.                 }
    复制代码

    我们需要为setup传递入一个参数arr,即地图的配置文件,而接下来,arr应该是一个2维数组,也就是必须有arr[y][x]这样的结构。因此arr[0]和arr[0][0]都不应该为空,否则就是不符合格式要求的数据,程序将不予以解析。所以,我们在这里做了一个格式判断:if (arr[0] == null || arr[0][0]==null) return;。而接下来,则对数组中的全部数据进行了循环解析。如果发现data不为0,也就是不可通过的位置,则进行相关的处理。

    到这里,我们已经可以分析到数组中的全部元素数据了,但是,我们现在得到的是0,1,2,3这样的数字,而不是最终的游戏对象。所以,我们需要有一个函数对这些数字来进行翻译:

    1. /**
    2.                  * 通过数字ID获取对应的元素
    3.                  * 
    4.                  * @param        id        地图数字
    5.                  * @return gameObject
    6.                  */
    7.                 protected function getObjById(id:uint):gameObject
    8.                 {
    9.                         var result:gameObject;
    10.                         switch(id)
    11.                         {
    12.                                 case 1:
    13.                                         result = new Stone(new stuff());
    14.                                         result.part = 1;
    15.                                         break;
    16.                                 case 2:
    17.                                         result = new Monster(new MonsterControler(), new Skin2());
    18.                                         result.part = 2;
    19.                                         break;
    20.                                 case 3:
    21.                                         result = new Player(new KeyController(), new Skin1());
    22.                                         result.part = 3;
    23.                                         break;
    24.                         }
    25.                         return result;
    26.                 }
    复制代码

    代码都是我们熟悉的,只是根据不同的ID进行了区分而已,不再过多的描述。这样,我们可以在刚才的setup函数中,if (data != 0)后面做文章了,来看一下完整的setup代码:

    1. /**
    2.                  * 配置地图
    3.                  * 
    4.                  * @param        arr        地图数据
    5.                  */
    6.                 public function setup(arr:Array):void
    7.                 {
    8.                         _mapData = arr;
    9.                         if (arr[0] == null || arr[0][0]==null) return;
    10.                         var y:uint = 0;
    11.                         var x:uint;
    12.                         
    13.                         var obj:gameObject;
    14.                         for each(var line:Array in arr)
    15.                         {
    16.                                 x = 0;
    17.                                 for each(var data:uint in line)
    18.                                 {
    19.                                         if (data != 0)
    20.                                         {
    21.                                                 obj = getObjById(data);
    22.                                                 if (obj != null)
    23.                                                 {
    24.                                                         addObject(obj);
    25.                                                         obj.x = obj.width * x;
    26.                                                         obj.y = obj.height * y;
    27.                                                 }
    28.                                         }
    29.                                         x++;
    30.                                 }
    31.                                 y++;
    32.                         }
    33.                 }
    复制代码

    这里,我们认为所有的游戏对象均使用了相同的规格,因此,可以根据他们在地图元素中的下标来计算其在场景中的坐标。

    最后,对游戏的主入口函数做出修改:

    1. private var mapconfig:Array = [
    2.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
    3.                         [0, 2, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    4.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    5.                         [0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
    6.                         [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1],
    7.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    8.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    9.                         [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1],
    10.                         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    11.                         [0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]                        
    12.                 ];
    13.                 public function Main() 
    14.                 {
    15.                         var scene:D5Scene = new D5Scene(stage);                // 声明游戏舞台
    16.                         scene.setup(mapconfig);
    17.                         // 生成基地
    18.                         var base:Base = new Base(new basicController(),new Skin_base());
    19.                         base.x = (stage.stageWidth-base.width)/2;
    20.                         base.y = stage.stageHeight-base.height;
    21.                         Global.base = base;
    22.                         scene.addObject(base);
    23.                         
    24.                         // 显示游戏舞台
    25.                         addChild(scene);
    26.                 }
    复制代码

    代码看起来比原来精简多了吧。运行测试一下吧

    小问题:现在基地没有放到场景里去,你可以自己修改程序,把基地也通过地图数组来进行管理

    小提示:背景改为黑色后,是不是子弹看不见了?去子弹类里把填充色由0x000000改为0xffffff就可以了,白色的子弹就可以看清楚了。

    最终效果:
     main.swf (20.31 KB) 

    源代码:
     Teach.rar (409.92 KB) 


    第七篇教程,也将是从零开始系列的最后一篇。我们将研究简单效果的实现思路,声音的播放,以及游戏道具的实现方法。之后,从零开始系列教程将结束,我们将引入位图缓冲等概念,开启新一系列的教程。

  • 相关阅读:
    物理删除文件 业务层
    页面在本机可以显示,其它机器不可以看到页面
    我对asp.net并行请求数量的理解
    分布式缓存Memcached
    任意两个对象赋值,用Spring.Objects.ObjectWrapper效率比直接反射还慢?
    在Linux(RHEL5.5)里用mono2.8.2和jexus4.1运行.net3.5下的MVC2.0过程记录
    Nhibernate连接oracle数据库,主键ID用序列生成时连接数据库IO次数分析
    Sqlserver别太信任SysComments表中的text字段
    .net4.0线程池取消执行的实际应用
    spring.net、castle windsor、unity实现aop、ioc的方式和简单区别
  • 原文地址:https://www.cnblogs.com/keng333/p/2304963.html
Copyright © 2011-2022 走看看