[新闻资讯] 使用Flex和Actionscript开发Flash游戏——设定关卡
来源:互联网 发布:手机热点软件 编辑:程序博客网 时间:2024/05/22 07:05
我的评论:倒数第二篇~
对这篇文你有啥看法,跟贴说说吧!欢迎口水和板砖,哈哈。欢迎大家和我们一同分享更多资讯。
这一部分,我们要实现一个系统,来定义游戏的关卡。
这里首先指出,我们所指的关卡,就是一个无限随机出现敌人的关卡。很显然,这个关卡不需要开发人员考虑合适游戏会结束。为题提供一个关卡结构的设计,我们需要对关卡进行统一的架构设计。听起来很有挑战,但是我们有很多选择,每个选择均有其各自的优缺点。
第一个想法就是使用xml来定义关卡。Actionscript对XML支持非常好,其自身就拥有XML类型变量。同样支持对XML进行遍历。使用XML的不便之处是你需要定义和解释XML中的节点。例如,你用一个节点定义了敌人位置。为了在游戏中实现效果,首先需要解析、保存xml,然后传值到方程中,才能实际的创建一个敌人。虽然不难,但是确实很繁琐。
幸好,Actionscript为我们提供了其它的可能。Function对象可以把方法看作一个对象,能够像其它object那样被调用和传递。甚至,我们可以传递匿名方法到Function对象的构造函数中。我们可以使用这个方法直接创建新的敌人对象。这个敌人对象直接存储在Function对象中,在游戏的level中被直接调用。听起来有点复杂,但是当你看到代码就会明确很多了。
首先我们需要创建一个类:LevelDefinitionElement.
LevelDefinitionElement.as复制代码创建这个类的目的是保存Function对象,这个对象会在level经历了一个固定时间后被调用。例如:你希望游戏开始10秒后出现一架敌机。
这个类有两个属性:time和func。time定义了func对象被调用的时间点。func属性保存了方法对象。这个方法能够做很多事情:创建一个敌人、创建一个背景元素、创建一个音效等等。事实上,这个属性可以赋值为任何方法,我们可以对关卡的结构进行非常灵活的定义。
sort方法用来对LevelDefinitionElements数组排序,这样做是为了缩短敌机的出现时间(如果前后敌机设定出现的时间过长)。
LevelDefinitions类也起到了容器的作用,许多具体的LevelDefinitionElements需要定义来完成一个完整的游戏。请看下面的代码:
LevelDefinitions.as复制代码除了单件模式实现所需属性外只有一个其它属性:levelDefinitions。这个一个字典(dictionary),key是level ID(例如:level 1,2,3等等),值value是LevelDefinitionElements数组。记住,一个LevelDefinitionElement定义了一个经过特定时间可调用的方法。所以,levelDefinitions[1][0].func()就是调用了预先存在里面的方法——记住他们是以time属性升序排列的(针对level 1)。
我们看一下startup方法,就更加明晰了。让我们设置一个敌人的位置。复制代码我们进行了一次调用在addLevelDefinition中,实际上仅仅是添加了一个LevelDefinitionElement到levelDefinitions字典中。第一个传递的参数是level ID。我们设置为1,就是我们在第一关中添加的。
第二个参数是一个LevelDefinitionElement。第一个变量是LevelDefinitionElement执行的间隔时间。我们设置为4,就是说LevelDefinitionElement将在进入关卡后4秒执行。
我们传入的第二个变量是一个匿名方法。就是说,这个方法没有名字,只能通过Function对象调用。其它与普通代码一样。从代码中可以看到,我们创建了2个敌机。
效果就是,进入游戏4秒后,画面会出现2个敌机。
一旦你脑中清楚了方法就是一个对象,就会发现这样做使我们更加简单的创建关卡结构。我们没有采用XML格式,尽管XML可以直接解析。我们采用代码的方式创建敌机,当然,方法都是无限可能的~
(一个小的变化是我们把colliding GameObject pairs的定义移到了startup方法中。保证对游戏的“定义”全部在一处)。当然,我们需要这些方法在正确的时候被调用。下面是代码:
(待续)
这里首先指出,我们所指的关卡,就是一个无限随机出现敌人的关卡。很显然,这个关卡不需要开发人员考虑合适游戏会结束。为题提供一个关卡结构的设计,我们需要对关卡进行统一的架构设计。听起来很有挑战,但是我们有很多选择,每个选择均有其各自的优缺点。
第一个想法就是使用xml来定义关卡。Actionscript对XML支持非常好,其自身就拥有XML类型变量。同样支持对XML进行遍历。使用XML的不便之处是你需要定义和解释XML中的节点。例如,你用一个节点定义了敌人位置。为了在游戏中实现效果,首先需要解析、保存xml,然后传值到方程中,才能实际的创建一个敌人。虽然不难,但是确实很繁琐。
幸好,Actionscript为我们提供了其它的可能。Function对象可以把方法看作一个对象,能够像其它object那样被调用和传递。甚至,我们可以传递匿名方法到Function对象的构造函数中。我们可以使用这个方法直接创建新的敌人对象。这个敌人对象直接存储在Function对象中,在游戏的level中被直接调用。听起来有点复杂,但是当你看到代码就会明确很多了。
首先我们需要创建一个类:LevelDefinitionElement.
LevelDefinitionElement.as
- package
- {
- public class LevelDefinitionElement
- {
- public var time:Number = 0;
- public var func:Function = null;
- public function LevelDefinitionElement(time:Number, func:Function)
- {
- this.time = time;
- this.func = func;
- }
- static public function sort(objectA:LevelDefinitionElement, objectB:LevelDefinitionElement):int
- {
- if (objectA.time < objectB.time) return -1;
- if (objectA.time == objectB.time) return 0;
- return 1;
- }
- }
- }
这个类有两个属性:time和func。time定义了func对象被调用的时间点。func属性保存了方法对象。这个方法能够做很多事情:创建一个敌人、创建一个背景元素、创建一个音效等等。事实上,这个属性可以赋值为任何方法,我们可以对关卡的结构进行非常灵活的定义。
sort方法用来对LevelDefinitionElements数组排序,这样做是为了缩短敌机的出现时间(如果前后敌机设定出现的时间过长)。
LevelDefinitions类也起到了容器的作用,许多具体的LevelDefinitionElements需要定义来完成一个完整的游戏。请看下面的代码:
LevelDefinitions.as
- package
- {
- import flash.geom.*;
- import flash.utils.Dictionary;
- public class LevelDefinitions
- {
- protected static var instance:LevelDefinitions = null;
- protected var levelDefinitions:Dictionary = new Dictionary();
- static public function get Instance():LevelDefinitions
- {
- if ( instance == null )
- instance = new LevelDefinitions();
- return instance;
- }
- public function LevelDefinitions()
- {
- }
- public function addLevelDefinition(levelID:int, element:LevelDefinitionElement):void
- {
- if (levelDefinitions[levelID] == null)
- levelDefinitions[levelID] = new Array();
- (levelDefinitions[levelID] as Array).push(element);
- levelDefinitions[levelID].sort(LevelDefinitionElement.sort);
- }
- public function getNextLevelDefinitionElements(levelID:int, lastTime:Number):Array
- {
- var returnArray:Array = new Array();
- var nextTime:Number = -1;
- if (levelDefinitions[levelID] != null)
- {
- for each (var levelDefElement:LevelDefinitionElement in levelDefinitions[levelID])
- {
- if (levelDefElement.time > lastTime && nextTime == -1)
- {
- returnArray.push(levelDefElement);
- nextTime = levelDefElement.time;
- }
- else if (levelDefElement.time == nextTime)
- {
- returnArray.push(levelDefElement);
- }
- else if (levelDefElement.time > nextTime && nextTime != -1)
- break;
- }
- }
- return returnArray.length == 0?null:returnArray;
- }
- public function getNextLevelID(levelID:int):int
- {
- if (levelDefinitions[levelID + 1] == null) return 0;
- return levelID + 1;
- }
- public function startup():void
- {
- GameObjectManager.Instance.addCollidingPair( CollisionIdentifiers.PLAYER, CollisionIdentifiers.ENEMY);
- GameObjectManager.Instance.addCollidingPair( CollisionIdentifiers.ENEMY, CollisionIdentifiers.PLAYERWEAPON);
- GameObjectManager.Instance.addCollidingPair( CollisionIdentifiers.PLAYER, CollisionIdentifiers.ENEMYWEAPON);
- LevelDefinitions.Instance.addLevelDefinition(
- 1,
- new LevelDefinitionElement(
- 1,
- function():void {(Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallBluePlaneGraphics,
- new Point(100, -ResourceManager. SmallBluePlaneGraphics.bitmap.height),
- 55);}));
- LevelDefinitions.Instance.addLevelDefinition(
- 1,
- new LevelDefinitionElement(
- 4,
- function():void
- {
- for each (var xPos:int in [150, 350])
- {
- (Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallBluePlaneGraphics,
- new Point(xPos, -ResourceManager. SmallBluePlaneGraphics.bitmap.height),
- 55);
- }
- }
- ));
- LevelDefinitions.Instance.addLevelDefinition(
- 1,
- new LevelDefinitionElement(
- 5,
- function():void {(Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallBluePlaneGraphics,
- new Point(500, -ResourceManager. SmallBluePlaneGraphics.bitmap.height),
- 55);}));
- LevelDefinitions.Instance.addLevelDefinition(
- 2,
- new LevelDefinitionElement(
- 1,
- function():void {(Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallGreenPlaneGraphics,
- new Point(100, -ResourceManager. SmallGreenPlaneGraphics.bitmap.height),
- 55);}));
- LevelDefinitions.Instance.addLevelDefinition(
- 2,
- new LevelDefinitionElement(
- 3,
- function():void
- {
- for each (var xPos:int in [150, 350])
- {
- (Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallGreenPlaneGraphics,
- new Point(xPos, -ResourceManager. SmallGreenPlaneGraphics.bitmap.height),
- 55);
- }
- }
- ));
- LevelDefinitions.Instance.addLevelDefinition(
- 2,
- new LevelDefinitionElement(
- 5,
- function():void {(Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallGreenPlaneGraphics,
- new Point(500, -ResourceManager. SmallGreenPlaneGraphics.bitmap.height),
- 55);}));
- }
- public function shutdown():void
- {
- }
- }
- }
我们看一下startup方法,就更加明晰了。让我们设置一个敌人的位置。
- LevelDefinitions.Instance.addLevelDefinition(
- 1,
- new LevelDefinitionElement(
- 4,
- function():void
- {
- for each (var xPos:int in [150, 350])
- {
- (Enemy.pool.ItemFromPool as Enemy).startupBasicEnemy(
- ResourceManager.SmallBluePlaneGraphics,
- new Point(xPos, -ResourceManager.SmallBluePlaneGraphics.bitmap.height),
- 55);
- }
- }
- ));
第二个参数是一个LevelDefinitionElement。第一个变量是LevelDefinitionElement执行的间隔时间。我们设置为4,就是说LevelDefinitionElement将在进入关卡后4秒执行。
我们传入的第二个变量是一个匿名方法。就是说,这个方法没有名字,只能通过Function对象调用。其它与普通代码一样。从代码中可以看到,我们创建了2个敌机。
效果就是,进入游戏4秒后,画面会出现2个敌机。
一旦你脑中清楚了方法就是一个对象,就会发现这样做使我们更加简单的创建关卡结构。我们没有采用XML格式,尽管XML可以直接解析。我们采用代码的方式创建敌机,当然,方法都是无限可能的~
(一个小的变化是我们把colliding GameObject pairs的定义移到了startup方法中。保证对游戏的“定义”全部在一处)。当然,我们需要这些方法在正确的时候被调用。下面是代码:
(待续)
- 1
评分次数
辛苦 威望 + 1 点 银子 + 20 两
达达
本主题由 达达 于 昨天 19:09 审核通过
收藏 分享 评分
我是小辛~
回复 引用
订阅 TOP
立刻订阅天地会人人快报,时刻同步全球RIA技术与资讯热点! RSS订阅地址: http://feeds.feedburner.com/9RIAnews
linus1115
- 发短消息
- 加为好友
linus1115 当前离线
- UID
- 2178
- 帖子
- 114
- 精华
- 0
- 积分
- 822
- 威望
- 12 点
- 银子
- 292 两
- 阅读权限
- 50
- 来自
- 北京
- 在线时间
- 40 小时
- 注册时间
- 2007-12-31
- 最后登录
- 2009-9-12
香坛护法
沙发
发表于 21 小时前 | 只看该作者
Level.as复制代码
- package
- {
- import flash.events.*;
- import flash.geom.*;
- import flash.media.*;
- import flash.net.*;
- import flash.utils.*;
- import mx.collections.ArrayCollection;
- import mx.core.*;
- public class Level
- {
- protected static var instance:Level = null;
- protected static const TimeBetweenLevelElements:Number = 2;
- protected static const TimeBetweenClouds:Number = 2.5;
- protected static const TimeToLevelEnd:Number = 2;
- protected var nextDefinitions:Array = null;
- protected var levelID:int = 0;
- protected var totalTime:Number = 0;
- protected var timeToNextLevelElement:Number = 0;
- protected var levelElementGraphics:ArrayCollection = new ArrayCollection();
- protected var timeToNextCloud:Number = 0;
- protected var timeToLevelEnd:Number = 0;
- protected var backgroundMusic:SoundChannel = null;
- public var levelEnd:Boolean = false;
- static public function get Instance():Level
- {
- if ( instance == null )
- instance = new Level();
- return instance;
- }
- public function Level()
- {
- levelElementGraphics.addItem(ResourceManager. SmallIslandGraphics);
- levelElementGraphics.addItem(ResourceManager. BigIslandGraphics);
- levelElementGraphics.addItem(ResourceManager. VolcanoIslandGraphics);
- }
- public function startup(levelID:int):void
- {
- timeToNextLevelElement = 0;
- new Player().startupPlayer();
- timeToLevelEnd = TimeToLevelEnd;
- levelEnd = false;
- backgroundMusic = ResourceManager.Track1FX.play(0, int.MAX_VALUE);
- this.totalTime = 0;
- this.levelID = levelID;
- nextDefinitions = LevelDefinitions.Instance. getNextLevelDefinitionElements(levelID, 0);
- }
- public function shutdown():void
- {
- backgroundMusic.stop();
- backgroundMusic = null;
- }
- public function enterFrame(dt:Number):void
- {
- totalTime += dt;
- if (nextDefinitions == null)
- {
- if (Enemy.pool.NumberOfActiveObjects == 0)
- levelEnd = true;
- }
- else
- {
- var nextLevelDefTime:Number = (nextDefinitions[0] as LevelDefinitionElement).time;
- if (totalTime >= nextLevelDefTime)
- {
- for each (var levelDefElement:LevelDefinitionElement in nextDefinitions)
- levelDefElement.func();
- nextDefinitions = LevelDefinitions.Instance.getNextLevelDefinitionElements(levelID, nextLevelDefTime);
- }
- }
- // add a background element
- timeToNextLevelElement -= dt;
- if (timeToNextLevelElement <= 0)
- {
- timeToNextLevelElement = TimeBetweenLevelElements;
- var graphics:GraphicsResource = levelElementGraphics.getItemAt(MathUtils.randomInteger(0, levelElementGraphics.length)) as GraphicsResource;
- var backgroundLevelElement:BackgroundLevelElement = BackgroundLevelElement.pool.ItemFromPool as BackgroundLevelElement;
- backgroundLevelElement.startupBackgroundLevelElement(
- graphics,
- new Point(Math.random() * Application.application.width, -graphics.bitmap.height),
- ZOrders.BackgoundZOrder,
- 50);
- }
- // add cloud
- timeToNextCloud -= dt;
- if (timeToNextCloud <= dt)
- {
- timeToNextCloud = TimeBetweenClouds;
- var cloudBackgroundLevelElement:BackgroundLevelElement = BackgroundLevelElement.pool.ItemFromPool as BackgroundLevelElement;
- cloudBackgroundLevelElement.startupBackgroundLevelElement(
- ResourceManager.CloudGraphics,
- new Point(Math.random() * Application.application.width, -ResourceManager.CloudGraphics.bitmap.height),
- ZOrders.CloudsBelowZOrder,
- 75);
- }
- if (levelEnd)
- {
- timeToLevelEnd -= dt;
- var scale:Number = timeToLevelEnd / TimeToLevelEnd;
- if (scale < 0) scale = 0;
- var transform:SoundTransform = backgroundMusic.soundTransform;
- transform.volume = scale;
- backgroundMusic.soundTransform = transform;
- }
- if (timeToLevelEnd <= 0)
- Application.application.currentState = "LevelEnd";
- }
- }
- }
我是小辛~
新手看过来:天地会入会必读
回复 引用
TOP
linus1115
- 发短消息
- 加为好友
linus1115 当前离线
- UID
- 2178
- 帖子
- 114
- 精华
- 0
- 积分
- 822
- 威望
- 12 点
- 银子
- 292 两
- 阅读权限
- 50
- 来自
- 北京
- 在线时间
- 40 小时
- 注册时间
- 2007-12-31
- 最后登录
- 2009-9-12
香坛护法
板凳
发表于 21 小时前 | 只看该作者
我们把所有关于随机创建敌人的代码和属性都移除掉了。尽管最终关卡将在LevelDefinitions类中定义,不过目前我们还是随机产生BackgroundElements交由Level管理。
一共添加了3个新属性:nextDefinitions, levelID和totalTime。nextDefinitions属性存储了一个由LevelDefinitionElements组成的数组,表示下一个将要执行的对象(Function对象)。在enterFrame方法中,Level类通过LevelDefinitions的getNextLevelDefinitionElements方法请求下一批要执行的LevelDefinitionElements。当时间到达,LevelDefinitionElements执行,同时请求了下一批要执行的对象。当没有LevelDefinitionElements(例如:nextDefinitions == null)时Level类等待所有敌人被击毁,然后关卡结束(设置levelEnd为true)。
levelID属性为当前的关卡。与addLevelDefinition方法中的相同。
totalTime属性表示当前关卡已经执行的时间。这是nextDefinitions适时请求下一批LevelDefinitionElements的保障。
定义了顺序的关卡结构之后,我们就有了为游戏添加更多很酷的东西的能力了。
最终结果:http://flexfighters.sourceforge.net/flexfighters9.html
源码:https://sourceforge.net/project/ ... p;release_id=634503
一共添加了3个新属性:nextDefinitions, levelID和totalTime。nextDefinitions属性存储了一个由LevelDefinitionElements组成的数组,表示下一个将要执行的对象(Function对象)。在enterFrame方法中,Level类通过LevelDefinitions的getNextLevelDefinitionElements方法请求下一批要执行的LevelDefinitionElements。当时间到达,LevelDefinitionElements执行,同时请求了下一批要执行的对象。当没有LevelDefinitionElements(例如:nextDefinitions == null)时Level类等待所有敌人被击毁,然后关卡结束(设置levelEnd为true)。
levelID属性为当前的关卡。与addLevelDefinition方法中的相同。
totalTime属性表示当前关卡已经执行的时间。这是nextDefinitions适时请求下一批LevelDefinitionElements的保障。
定义了顺序的关卡结构之后,我们就有了为游戏添加更多很酷的东西的能力了。
最终结果:http://flexfighters.sourceforge.net/flexfighters9.html
源码:https://sourceforge.net/project/ ... p;release_id=634503
- [新闻资讯] 使用Flex和Actionscript开发Flash游戏——设定关卡
- [新闻资讯] 使用Flex和Actionscript开发Flash游戏——重复背景绘制
- 使用Flex和Actionscript开发Flash游戏
- 使用FLEX 和 Actionscript开发FLASH 游戏—嵌入资源和增加游戏元素
- 使用Flex和Actionscript开发Flash游戏 —— 双缓冲渲染
- 使用Flex和Actionscript开发Flash游戏——碰撞检测
- 使用FLEX和Actionscript开发FLASH 游戏-位图动画
- 使用FLEX和Actionscript开发FLASH 游戏-碰撞检测
- 使用FLEX 和 Actionscript开发FLASH 游戏(一)
- 使用FLEX 和 Actionscript 开发FLASH 游戏2
- 使用FLEX和 Actionscript 开发FLASH游戏(三)-1
- 使用FLEX和 Actionscript 开发FLASH游戏(三)-2
- 使用FLEX和 Actionscript 开发FLASH游戏(三)-3
- 使用FLEX和 Actionscript 开发FLASH游戏(三)-4
- 使用FLEX和 Actionscript 开发FLASH游戏(四)-1
- 使用FLEX和 Actionscript 开发FLASH游戏(四)-2
- 使用FLEX和 Actionscript 开发FLASH游戏(五)
- 使用FLEX和 Actionscript 开发FLASH游戏(六) -1
- Flash视频广告的定位兼容性问题
- .NET 连接池
- 项目管理软件Trac的安装与调试
- DrGraph群
- asp.net中数据库的备份与js的验证示例
- [新闻资讯] 使用Flex和Actionscript开发Flash游戏——设定关卡
- API CreateWindow
- c#怎么把一个彩色的图片处理成灰色的呢。
- 理解ActiveX控件的一些背景知识
- 创建同义词-基于远程服务器视图
- [新闻资讯] Flash搜索引擎优化工具
- 浅析FTP的工作原理
- 奇怪的 this 指针 (续)
- FTP原理