周云的FLASH小游戏开发教室_基础篇

来源:互联网 发布:python中try和except 编辑:程序博客网 时间:2024/05/22 05:08
[作者:周云 原创 首发经典论坛 联系方式:danyun1982@163.com]
原文地址:http://bbs.blueidea.com/thread-2799019-1-1.html

最近累,虽然有很多朋友都在等勇者2,但我实在没心情开发。
闲着也是闲着,开一贴给刚刚踏上FLASH游戏开发的爱好者们写点东西。

老鸟就不用看了,呵呵,贻笑大方了。

FLASH游戏这东西吧,总入不了大流。国内拿FLASH做美术方面的应用比较多,而传统的游戏程序员又把FLASH当小儿科,不屑搞这个,事实上开发FLASH游戏也赚不了钱,七七八八的原因加起来,就变成了没多少职业程序员来开发FLASH游戏,学校也不会培养学生深入学习开发FLASH,搞这块的人少,人少交流讨论的也少,正正规规的教材也少,当然优秀作品更少。
目前国内大部分的FLASH游戏开发爱好者没有好教材的指引,自己摸索着就上路了(NND,我也是这样开始的),开发流程和习惯都是各人一套,很多人因为没有接受正确的学习而走了很多歪路(MD,好像我也是)

于是乎,话题转回来,我就开一贴跟菜鸟们多交流吧……

=================================================================
LESSON 1 游戏制作前的准备

突然灵光一闪:老子要做个XX类型游戏!
于是立马打开电脑,打开FLASH,找图片,建元件,F9一按,代码蹭蹭的打啊……结果做了一半做不下去了。

以上情况常常发生……

做游戏首先脑子里先要有整个游戏的规划,最好是拿笔画个流程简图,然后再下手。
游戏流程的规划是很重要的,我在做一个游戏游戏前,草稿纸上来来回回要打个半天的草稿才开工,我一直认为游戏的规划部

分是很难的,如果真等到全部想好了,做起来其实是个很轻松的过程,只是耗时间罢了。

理论知识多说没用……
我们不如来实践下,跟我一起做个简单的游戏吧……

【吃金币游戏-策划】(我在草稿纸头上写下以下几点)
基本描述:
1.天上掉宝物,地下小人物由自己控制,去接宝得分
2.时间限制30秒

写到这里,顺手画了张草图

 

画好草图,我继续在草稿纸上又写下详细的几处描述:
1.宝物分四种:金币10、金币50、增加时间的宝物、瞬间获得屏幕所有金币的宝物
2.要有两个人能选,一个人物太无聊
3.人物样子不能太傻(这条请忽略)
4.最好来点技能~!(晕- -不是说简单游戏么……)
5.要能记录我最高得分,有点挑战性!
6.玩到后面最好难度慢慢增加,就让下落物品速度加快吧!
7.即使小游戏,音乐音效也应该有的
8.(占位中...)

写到这里,我又想了想,又画了张草图
大概想了下这个小游戏的运行过程

 


鉴于我这个人脑子不好使,我又一样样统计了下一共有多少东西。
见下图

 
 

1.人物
2.宝物
3.时间显示的东西
4.分数显示的东西
5.选择人物还有游戏结束后历史高分的两个提示板
6.背景图片和音乐音效

好了,游戏不管大小,我基本动手干活前这些基本的流程都要走。
为的是明确整个游戏的过程,然后统计下有多少东西要做,然后一样样做呗。

接下来就是搜集要用到的素材。
我找了张背景图,找了两张火影的卡通人物:鸣人和小李。

 
 
 



接下去就是先把要用到的动画元件做好。然后就开始考虑程序部分(后面几讲重点)。


P.S.看到这里,有人要骂了,小样是不是发个半吊子帖子来骗分啊?为了表明我不是骗子- -...我今天把这个小东西做了下。因为纯教学讲解用,所以只简单做了两个人物和几个道具,等大家学完后可自行扩充改写。(为了写这个帖子我今天特意做的,没功劳也有点苦劳啊~)版主给点分升级啦~很多图我都传不上~

FLASH不能直接引用这贴,大家只能自己下载下来看看了(鼠标右点另存为)
[见附件]

控制,键盘方向左右操作,上键小李长按是加速,鸣人是跳跃。

下节讲讲AS方面的开发布局,请随时留意本贴哦~

 

 

 

LESSON 2 AS该怎么写?

大家好,趁没下班,我再短短的写一节。

先补充一下我草稿纸上对于游戏又多两条设想描述:
9.吃了宝得的分应该有显示
10.显示得分或者时间到了宝消失,不要太呆板,稍微做点小动画,来个过渡渐变什么的……

好,现在回到本节主要内容。
我们讨论下AS的问题。
先不急于动手打代码,我们先要想好这代码怎么个写法,怎么个安排。
好,现在小鸟们排好队,一个个来回答,你准备怎么写:
10个小菜鸟9个会回答:我X你的傻X~!还能怎么写?F9按了开始写啊……gotoandplay啊,onrelease啊,if啊……该写啥写啥……

咳咳,事实上,也没错。
游戏也能这么出来。
不过我个人推荐我们该融入点面向对象编程的概念。

啥?NONONO……我不是要开始讲复杂的东西……
我尽量把话往简单了讲……
我们上讲统计过游戏大致那几个东西是吧?我们现在就把那几个东西独立开来做。
用你听过的,就是分几个CLASS(类)来做。
比如,人物,我们就搞个人的CLASS,宝物,我们就搞个宝物的CLASS,和传统的F9按开一股脑的打代码不同,CLASS类文件是另外写的.AS文件,然后游戏主的.SWF主文件调用的。
来张图:




每个CLASS都会被绑定在对应的MC上

 


上节统计过的,游戏一共就那么几个MC,每人把自己对应的小蜜绑好合成一体,在舞台上一合成,就是个完整的能运作的游戏了

 

这样的结构有什么好处?
1.清晰,修改起来方便,知道哪的问题上哪个地方改
2.CLASS封装性好,不受其它MC和CLASS的影响
3.因为2的原因,所以适合好几个人一起开发。比如今天你要去谈恋爱,你就拉了隔壁阿三,告诉他要做个怎么样的CLASS,名称和哪几个变量以及实现的功能,然后阿三做好,你就拿来可以直接用了。
4.把整个游戏一个个零件拆开做,不容易犯错。
5.看上去比较专业,不懂行的一看,NND,搞的跟专业开发人员一样,拉风毙了……

下班了,这节到这里。
不懂CLASS的朋友找点文章复习起来,下节写点CLASS方面的东西……


 

 

 

 

 

LESSON 3 CLASS是什么东东?(上)

在具体讲解CLASS构造前,想花点篇幅帮小鸟们理解下CLASS是什么东东。
还是来举个例子,有一个机械战士的MC,这个MC里有机械战士完整的构造,手脚、身体、武器……
但这个机械战士仍然不能动,因为它只是一具机械,没有大脑程序告诉它该怎么走动,怎么攻击……
而我们做的“机械战士控制.as”的CLASS,绑定在这个战士身上。
这个CLASS可以看作为一个封闭的黑匣子,里面装载了指导机械人行动的程序,包括怎么移动、怎么攻击、怎么做事情A、怎么做事情B。
而这一切都是封闭在黑匣子里的,影响不到外界程序,外接程序也影响不到它。是个独立的东西。
这个黑匣子可以装载到任何一个机械战士身上,任何一个机械战士躯体的MC一旦绑定上这个CLASS,就能立即行动起来。
而且我们可以给这个CLASS做个外界可以调用的接口。
就像黑匣子上装了个可以给外界摁的按钮,你摁一次它就发一次绝招。

 

象上一节说的,CLASS模式做游戏可以团队开发。我可以让别人帮我做CLASS,做好我拿来用。我不需要知道他代码怎么写的,我只需要知道这个CLASS能让这个机械人按照什么规则行动,有什么按钮可以让我摁。
封装性的好处由此显示出来了。

再闯关游戏里,经常出现比如画面上主角一人对N个敌人的场面。这些敌人每个都可以绑定同一个CLASS。就是说写了一个CLASS分别装载到N个实例化的MC中去,而不用每个敌人都各自写一段代码。

 

可能其中两个敌人的生命和攻击力不同。这也很简单,在CLASS里做一个接收外部传入生命和攻击力两个参数的功能,在敌人MC绑定CLASS后,再传生命和攻击力两个变量的值到MC里即可。

不过要说明,CLASS并不是只能实例化在MC上,还可以装在例如Object之类的上面。
比如我们很常用的一个FLASH本来就有的CLASS:SOUND
mySound=new Sound()
mySound.attachSound("a.mp3")
mySound.start(0,1)
这里我们就可以看作Sound类实例化了在mySound的上,而attachSound和start都是Sound类的“按钮”,可以让外部操控这个装载了Sound类的mySound。我们并不知道Sound这个CLASS内部代码是如何的,但我们知道按钮可以用来干什么,用的也不是很爽吗?

 

 

LESSON 4 CLASS是什么东东?(下)

上节说了CLASS的基本应用,可能有鸟鸟们要问了,我做个function一样可以用啊,或者在MC里敲代码,跟你写CLASS一样。
那为什么还要写CLASS啊?

那这节我就来写点CLASS的另外个重要的特性-“继承”

先来个小例子:
隔壁阿三写了个类“机器人控制.as”,里面写了若干行的代码,包括“移动、跳跃”两个个功能。
我现在也想写个类“超级流氓机器人.as”,里面包括“移动、跳跃、攻击”三个功能。

和阿三写的类比较起来,“移动、跳跃”两个功能是一样的啦,我想写的类只多了个“攻击”功能~
于是可以偷懒了。

在我写的类“超级流氓机器人.as”第一行加句简单的代码,就可以把阿三写的类完全COPY过来。(代码语法命令后面的课程会讲的)
然后我的“超级流氓机器人.as”文件里,内容就只有段写“攻击的代码”。

看到这里,鸟鸟们又要问了,为什么不直接ctrl+c然后ctrl+v把阿三写的类复制过来,然后在里面加?
呵呵。
1.别人写的代码,复杂的要死,反正我脑子转不过来,不想去分析别人的东西。分析别人写的代码,痛苦的来~
2.日后我再要写个“移动、跳跃、翻滚”的代码,我不是还要再ctrl+c然后ctrl+v?多麻烦!
3.假使我用ctrl+c然后ctrl+v的方法做了,但突然发现“移动”功能里有个错误要改……郁闷吧?你要一个个.as文件改了。而如果是继承的方法做的,你只要让阿三把他写的类修改了,你自己写的两个类就一点不需要改动了,因为“移动”部分的功能,是直接继承过来的嘛~

说到这里,顺带再提下,FLASH里我们经常也在用类,只是你感觉不到。
做游戏用到最多,同时也是FLASH里最重要的类,就是~~~~~~~~~“MovieClip类”!
鸟鸟们不知不觉的就一直在用MovieClip类,比如你有没有经常写:mc.onEnterFrame..
onEnterFrame就是MovieClip类里的一个方法,只要是个MC(自动被绑上了MovieClip类),就都能用onEnterFrame。

现在回到第一节说的那个天上掉宝地下人物接的游戏。
人物有两个:小李和鸣人
经过分析,这两个人物基本控制部分是一样的,然后就区别在两个人的各自的特殊技能不一样。
于是我们可以这么做:
1.先建个“人物基本控制.as”类
2.建个“小李.as”类,第一行一句代码继承“人物基本控制.as”类,然后在正文内容里写上小李特殊技能
3.建个“鸣人.as”类,第一行一句代码继承“人物基本控制.as”类,然后在正文内容里写上鸣人特殊技能

见图
 

大家可以看到,“人物基本控制.as”类也是继承了MovieClip类,因为要用到MovieClip类里的功能嘛~比如人物移动要用到onEnterFrame,MC._x,MC._y这点功能。

类的继承,还可以覆盖继承过来类里的方法。
比如A类有move、jump、attack三个方法
我要写个B类,也包括这三个方法,但是attack这个方法和A类的attack有点不同,而move、jump这两个方法则和A类里的一模一样。
于是我们写B类,第一行先写句话继承了A类。然后在正文里把attack方法重写一次,就自动覆盖掉了继承过来的A类的attack方法。其它的方法就不用写了,因为直接继承过来了。

让我们来换个思路做上面那个例子。
直接写了“小李.as”类,然后让“鸣人.as”类继承小李类,正文里只需要把特殊技能方法重写遍就OK了。

见图
 

看了那么多概念,小鸟们要想,咋还不教具体怎么写CLASS呢?
别急啊,下节里会简单的教些的。
其实我对这种死东西教学还是比较头大的,鸟鸟们也可以自己网上搜下具体CLASS撰写格式、规矩和变量、方法类型。肯定比我教的要详细。因为我在CLASS方面也只能算只比小鸟略微胖点点的中鸟啊,哈哈

明天要去阳澄湖吃大闸蟹,等周一上班了再来更新吧~

 

LESSON 5 CLASS的基本撰写规范

NND,哥哥电话来说大闸蟹还不肥,他一哥们吃过了,所以大闸蟹之行做罢了。继续回来写教程。
本来不想写这节的,因为这节的内容很多书上或者网上资料都有,而且写的比我要详细正规得多。
但后来想想,还是写吧!
为啥?
凑篇幅呗~啊哈哈~
而且后面几节要结合接宝的范例游戏,具体分析它的几个CLASS,所以,还是用一节把CLASS的写法说一下。
可能我对CLASS的写法也不是很正规,有老鸟看了后,最好也能指点一下。

P话少说,先来个CLASS基本的模式。
文件名:Time_control.as

复制内容到剪贴板
代码:
class Time_control {
    //第一部分:声明本CLASS要用到的变量
    static var a:Number=2;
    private var b:Number;
    private var c:Number=1;        
    public var d:Number;
    //第二部分:构造函数
    function Time_control() {
        init();
    }
    //第三部分:隐式设置-获取法
    public function set _d(sss:Number):Void {
        d = sss;
    }
    public function get _d():Number {
        return (d);
    }
    //第四部分:私有和公有方法
    private function init() {
        //一般写点初始化的内容
    }    
    private function aa() {        
        
    }
        public function bb() {        
        
    }
}

如果是要继承类,比如继承MovieClip类,第一行就改写成
class Time_control extends MovieClip {

下面简单解释下各个部分(……我最不擅长解释说明这类东西)
CLASS类都是以

复制内容到剪贴板
代码:
class 类名称 {
    内容
}

的形式,而且类名称和文件名要相同。

CLASS的内容分四部分

第一部分声明本CLASS所用到的变量,这里要提的是,和在SWF里定义变量不同。SWF里你可以用比如a=1这种自动变量形式,而在CLASS里你必须写明a的类型是Number,再定义变量值是1
第二部分是CLASS的构造函数,什么意思呢?就是当CLASS的实例出现后,自动执行这个function里的内容,一般都是些初始化的内容。function的名称要和CLASS类的名称一样哦~而且这里初始化一般都是用个init()函数,init函数具体在后面回自己定义。为什么要这样而不直接把初始化内容写在构造函数内呢?因为当继承其它类的时候,构造函数是不能继承的,还得自己再写一次,而init函数是可以继承的,于是……呵呵,懒人懒办法嘛~直接把内容写在构造函数里的话,每次继承就还要重写次,用自定义init函数的话,就可以偷懒咯~
第三部分是定义隐式设置-获取的function,什么意思呢?上节我们说过,class可以看作一个封闭的盒子,跟外界无关。但有时候我们必须读取或者改变CLASS类内的某个变量。这时候就必须借助隐式设置-获取的function。只有定义后,外界才能读取和设置CLASS内的变量。定义的方法就是比普通function多了get/set这个单词。而且必须要指定返回变量类型,无需返回则用Void表示。
第四部分就是写function咯~这个就不具体说了,function大家老写了~

可能大家看到,class里比平时大家写的,多了private和public,还有static这三个词
啥意思捏?
简单简单的说下:
private与public定义的变量和方法都能在CLASS内一样使用,没啥区别
而不同的地方就是,public定义的变量和方法能够被外界读取设置和使用,而private则不能,只能在封闭的CLASS内使用。

比如public var d:Number=1设置了变量d是public型的
然后在第三部分写下

复制内容到剪贴板
代码:
public function set _d(sss:Number):Void {
        d = sss;
    }
public function get _d():Number {
        return (d);
    }

当CLASS实例化在了一个MC后
trace(MC._d)就得到1
输入MC._d=2后,MC内的d就变成2啦~而private设定的变量,你从外部既不能读取也不能赋值
自己仔细体会下

同理,例如

复制内容到剪贴板
代码:
public function 发绝招{
}

就像上几节图里那个封闭盒子上的发绝招按钮,实例化到MC后,就可以直接
MC.发绝招()
来让MC执行 发绝招() 这个function

而static定义的变量,怎么跟大家描述呢……它不存在于CLASS的实例化里。
而且static定义的变量,是被所有CLASS实例共享的。
还是来个例子吧:
舞台ATTACH个MC,绑定的ccc.as类。类里有个static变量s=1。ccc类里初始化函数init()里让s++,这时候s就等于2了是吧?
然后继续在舞台ATTACH个MC,绑定的ccc.as类,这个MC的s就直接等于2了。然后它在初始化函数里同样执行了s++,这时候两个MC里的s都同时变成了3
这就是所有CLASS实例共享static变量。

怎么说呢,CLASS撰写方面,我自己也不是很行,可能还存在少许的理解误区或者缺少技巧经验。希望老鸟也指导下。
关于这节,我建议新鸟鸟们最好自己再找点正规教材自己学习下。

单靠这节写的些鸟文,小鸟对CLASS还不能很好的认识。
正常。
所有的知识只有通过实战才能真正的理解。
在下节里,我会详细的开始教那个接宝游戏怎么做。具体的代码怎么写。CLASS怎么写怎么用。手把手的教鸟们学做这个范例游戏。

 

 

LESSON 6 范例接宝游MC戏详细分析

搞了半天的鸟CLASS,我们又回到了做游戏的内容上来。
咱们学那么多知识,目的也只为了更好的来做游戏。这个游戏吧,前面也有朋友说到了,根本不用CLASS,做个单个FLA文件F9按了猛打代码,然后MC里点开了东鸟点代码,西鸟点代码,也能完成。
没错,确实这样。
我自己相当长一段时间内也是不懂CLASS之流,只用一个FLA文件,代码全死敲里面,也做出不少洋洋得意自以为是的小游戏。
我自己本身就不是科班出身的鸟,当年差了十分没能进计算机系,错过了接受正规编程教育的大好光阴。(不过事后发现世界是奇妙的,我做过几个单位从事正职编程的都不是计算机系毕业的)

但当小游戏逐渐变成大游戏后,一个FLA里,root里,MC里代码开始多起来,关系开始复杂起来,于是制作者头也开始大起来,直接影响到睡觉睡不好,饭也吃不好,肠胃不通,消化不良,上班没精神……
于是,就必须要正规的,能让脑子清醒的,能轻松分辨游戏里各类关系的开发方法。
再于是,我每天买瓶水,学习了CLASS方面的知识。(日,学CLASS和买水有啥关系??)

话题扯远了,让我们再次回到接宝上来。
一楼那个我做的简单范例SWF大家看过了没?
什么?没?
赶快去下了,试着玩玩。给你5分钟,玩好再继续往下看。

……(5分钟的等待)

好,试玩过了对吧?
我现在问你,要你分析游戏里的逻辑关系,你怎么分析?
给你5分钟思考。

……(5分钟的等待)

是不是:天上不间断掉宝-当地下人物碰到宝,就获得相应的奖励。时间到就结束游戏。
是这样的。

但我思考问题,是按:
1.游戏时画面上有几大元素?(MC)
2.每个MC要实现什么功能?
从每个MC的角度来思考分析游戏的构成。
你也要习惯这样,因为我们以后要从MC的角度来编写CLASS,每类MC都会有个对应的CLASS类来告诉这个MC在游戏中该做什么。
各个MC拼合起来,就成了一个游戏。
简单游戏和复杂游戏的一个区别,就是游戏里元素多少,元素多了,逻辑复杂,元素少了,逻辑简单。

好,请鸟鸟们继续思考,接宝游戏里有几大元素(MC)?它们各自要做点什么?
给你10分钟……

……(10分钟的等待)

见图:
 



公布答案:
1.人物
2.宝物
3.分数(右上角)
4.时间(左上角)
5.游戏总控制(包括选人、最后最高分显示)

每类各自要做的事情:
【人物】
1.能够左右按键移动控制移动
2.移动范围限定(不能跑出屏幕吧?)
3.按上键技能
4.一些初始化设定(刚开始出现的坐标,移动速度)
【宝物】
1.按随机速度下落,落出屏幕消失
2.碰撞检测,是否碰到人物
3.碰到人物后产生加分、加时间等不同的效果
4.初始化设定(刚开始出现的坐标,移动速度)
【分数】
1.显示分数
【时间】
1.30秒倒计时,显示时间变化
2.到了0秒,通知‘游戏控制’执行‘结束游戏’的function
【游戏控制】
很重要的部分,要控制协调以上几个元素之间的关系,以及游戏的过程。
集合了很多种function供调用
以下规整下包含的function
1.人物选择:按照人物选择框的选择,attach人物MC到舞台(人物attach进来后,就会自动按照他自己的CLASS行动啦),同时调用‘掉宝控制’的function开始掉宝以及‘时间控制’里倒计时方法,开始30秒倒计时。
2.掉宝控制:按照随机时间间隔,随机的attach宝物种类到舞台(一样~!宝物attach进来后,就会自动按照他自己的CLASS行动)
3.金币消失:这个funtion要在时间到0时被调用,作用是让屏幕上的金币原地消失
4.游戏结束:这个function是被‘时间控制’里当时间=0的时候调用的,作用为判断比较当前得分和最高分,显示框出现显示最高分。

说了那么多,不知道大家思路跟不跟的上
按我说的仔细思考下吧
要直到能理解我说的,才能继续看下一小节。

下一小节开始,我要一个个放出各个CLASS的具体代码了,并进行详解,请时刻关注哦!

【附】
编写好的CLASS怎么关联到MC?
就拿上节例子Time_control.as来说吧,要关联到库里的元件'时间'
老鼠右击元件'时间',然后……

见图
 




如果是自己拖到舞台上,“第一帧导出”就不选
如果是attach上舞台,则就要选哦~!

 

 

 

 

LESSON 7 范例接宝游戏中人物类的CLASS讲解

一般兄弟叫我小周
我的游戏玩家称呼我周哥
同事称呼我周大师
象我讨教问题的喜欢称呼我周老师
虽然我身为一名正职的FLASH设计师,大家也是可以可以称呼我为周老师的。因为一年前我作为未婚妻大人的御用陪读,不经意间居然也通过BT的几门考试得到了《上海市教师资格证》……(虽然我不知道我要这张证有什么用)……

那个……话题又乱扯了(不过也证明了我思维活跃嘛~如果你的思维有我一半的扯,日后你可以去考个证当老师了,纵使比现在的计算机老师水平高些,但也足以误人子弟)

回到本节主题上来,我们来学习范例游戏的具体代码。
首先请下载源文件:
http://images.cntvs.com/temp/CLASS范例.rar
(斑竹看到帮忙传下,1.8M的附件我没权限传到坛子上)

下载好,打开一看,如下
一个FLA主文件:  run_game.fla
三个目录:player,items,game
我把.as类文件分门别类的存放,这样看上去清晰,更重要的是别人看了会觉得我很专业~

目录player里有:Player_1.as   Player_2.as
目录items里有:Jin.as   Bao1.as   Bao2.as
目录game里有:Game_control.as   Score_view.as   Time_control.as
.as具体意义看文件名就应该能知道,这里要说的是,一般默认的规则,放CLASS目录用小写字母命名,.as的类文件名的首字母用大写

这节详细讲下人物类的CLASS,首先是Player_1.as,人物小李的类
首先去源文件里点进人物1的MC,看下结构。
由两帧组成,一是“stand”,二是“run”
人物上面有一层有个圆形的MC,我把它命名为hit,靠这个mc来做碰撞检测。
金币里面也有这个名叫hit的MC,我判断人物和金币是不是相碰是用这个语句的: 金币MC.hit.hitTest(人物MC.hit)
传统碰撞检测都这么做。

又开始扯话题了,马上拉回来~!
现在拿出Player_1.as的代码

复制内容到剪贴板
代码:
class player.Player_1 extends MovieClip {
    private var hit:MovieClip; //人物MC里出现的东西都要声明,hit这个MC也不例外
    public var speed:Number;//这个是人物移动的速度
    //构造函数
    function Player_1() {
        init();//初始化的人物打包在init()里了
    }
    //隐式设置-获取法
    public function set _speed(sss:Number):Void {
        speed = sss;
    }//可供外界用MC._speed=X修改speed的数值
    public function get _speed():Number {
        return (speed);
    }//可供外界读取speed的数值
    //私-公有方法
    //---初始化方法---
    private function init() {
        _y = 310;
        _x = 300;//人物来到舞台后的初始位置
        speed = 6;//移动速度
        onEnterFrame = Move;//人物来到舞台后就开始onEnterFrame,内容见Move这个function
    }
    //---人物移动---
    private function Move() {
        if (Key.isDown(37)) {
            _xscale = -100;
            _x -= speed;
            this.gotoAndStop("run");
        } else if (Key.isDown(39)) {
            _xscale = 100;
            _x += speed;
            this.gotoAndStop("run");
        } else {
            this.gotoAndStop("stand");
        }
        //以上是左右键的定义,应该看得懂吧?
        if (Key.isDown(38)) {
            speed = 12;
        } else {
            speed = 6;
        }
                //以上是上键的定义,按着后速度就加倍咯
        range();//范围定义,内容见下面
    }
    //---限定移动范围---
    private function range() {        
        if (_x>540) {
            _x = 540;
        }
        if (_x<10) {
            _x = 10;
        }//不让人物出界
    }
}

这个CLASS文件就是这样。按照前几节我说的结构,鸟鸟们对照这看下。能不能看懂。
这里要说的是,第一行的player.Player_1,其中前面的player表示路径“.”就相当于"/"
player.Player_1就相当于player/Player_1
关联到MC的时候也要这么写的。

小李的CLASS写完了
然后写鸣人的CLASS

记得前几节我说的“继承”这个概念么?
快去翻出来看看。

鸣人和小李就是上键技能不同,所以继承过来后,正文把按键控制重写一次就行了,其它就全继承小李的类了
代码如下

复制内容到剪贴板
代码:
class player.Player_2 extends player.Player_1 {
    //继承了player.Player_1类,所以只需要把两者间唯一不同的Move函数重写次就可以啦~当然构造函数还是要的
    function Player_2() {
        init();
    }
    //人物2的Move函数
    private function Move() {
        if (Key.isDown(37)) {
            _xscale = -100;
            _x -= speed;
            if (_currentframe != 3) {
                gotoAndStop("run");
            }//这句自己体会下,不加的话,按上键后鸣人就一直不停的在跳跃了
        } else if (Key.isDown(39)) {
            _xscale = 100;
            _x += speed;
            if (_currentframe != 3) {
                gotoAndStop("run");
            }
        } else {
            if (_currentframe != 3) {
                gotoAndStop("stand");
            }
        }
        //
        if (Key.isDown(38)) {
            gotoAndStop("jump");
        }
        range();
    }
}

好了,人物类就写完了。
消化下。后面的宝物类大同小异,下一节再写。

 

 

 

 

 

 

 

LESSON 8 范例接宝游戏中宝物类的CLASS讲解

先补充个游戏里的结构:
_root下有三个空MC: pl,item和xs
pl这个空MC是用来attach人物的
item这个空MC是用来attach宝物的
xs这个MC是用来attach显示得分的
为什么要这么做呢?……因为管理方便呀~以后你会慢慢体会到的。

严重警告:第7课未搞懂看明白者,请回上节反复研究,直至搞懂。不然继续往下看会让你体内真气逆行,任、督二脉自锁,全身犹如蚂蚁咬,饭吃不下,觉睡不着,放P恶臭,对FLASH丧失学习信心……

(……)

好了,能看到这行的,说明你已经是个消化第7节内容的鸟了。
这一节我也话不多说,直接放代码了。用你第7节学到的内容自我检验下。

金币10和50共用的CLASS

复制内容到剪贴板
代码:
class items.Jin extends MovieClip {
    static var basic_speed:Number = 3; //下落基础速度    
    public var score:Number = 10;    //得分
    public var speed:Number;    //下落速度
    private var hit:MovieClip;    //声明碰撞检测的MC
    private var depth:Number;    //当宝物被人物获得,显示得分的MC的深度        
    //---构造函数---
    function Jin() {
        init();
    }
    //隐式设置-获取方法
    public function set _score(kkk:Number):Void {
        score = kkk;
    }//得分10还是50,传入这个参数就能解决
    public function _bspeed(){
        basic_speed= 3;
        trace(basic_speed)
    }//这个要说明下,静态变量basic_speed每实例化一个MC都会自我增加,所以基础速度越来越快。这个方法是让basic_speed变回原始的3。用于每回合开始时初始化使用。
    public function set _speed(sss:Number):Void {
        speed = sss;
    }
    //共有-私有方法    
    private function init() {
        _x = 50+random(450);
        _y = -15;
        speed = basic_speed+random(50)/10;//下落速度是由基础速度+随机增量
        basic_speed+=0.03
        //trace(basic_speed)
        onEnterFrame = Move;
    }
    private function Move() {
        _y += speed;
        if (_y>380) {
            this.removeMovieClip();
        }
        /////////////////////////////////  
        if (hit.hitTest(_root.pl.player.hit)) {
            getItem();
        }
        ///////////////////////////////// 碰撞检测哦~
    }
    public function getItem() {
        _root.music_control.snd("jin");//声音控制,以后会讲到
        _root.score += score;
        depth = _root.xs.getNextHighestDepth();
        var a:MovieClip = _root.xs.attachMovie("getScore", "getScore"+depth, depth++);//ATTACH显示得分的MC
        a.aaa.score = "+"+score;
        a._x = _x;
        a._y = _y;
        this.removeMovieClip();
    }
}

然后是两个宝物的CLASS,继承了金币的类,只不过改写了被人物吃到后的效果

爱心

复制内容到剪贴板
代码:
class items.Bao1 extends items.Jin {
    public function getItem() {        
        _root.music_control.snd("bao");
        depth = _root.xs.getNextHighestDepth();
        var a:MovieClip = _root.xs.attachMovie("getScore", "getScore"+depth, depth++);
        a.aaa.score = "TIME";
        a._x = _x;
        a._y = _y;
        ////////
        _root.time_c._time += 8;
        ///////调时间控制类的public方法,后面会讲到
        this.removeMovieClip();
    }
}

五角星

复制内容到剪贴板
代码:
class items.Bao2 extends items.Jin {
    public var score:Number = 30;
    public function getItem() {
        //_root.score+=score            
        _root.music_control.snd("bao");
        ///////                
        for (var i in _root.item) {
            if (_root.item[i]._name.substr(0, 3) != "bao") {
                _root.item[i].getItem();
            }
        }
        _root.score += score;
        depth = _root.xs.getNextHighestDepth();
        var a:MovieClip = _root.xs.attachMovie("getScore", "getScore"+depth, depth++);
        a.aaa.score = "+"+score;
        a._x = _x;
        a._y = _y;
        ///////
        this.removeMovieClip();
    }
}

宝物这类,和人物类有点相似的。
下节会把时间控制类和分数控制类一起讲掉。大家快把这节的内容消化了吧~

 

 

LESSON 9 范例接宝游戏中得分显示类和时间控制类的CLASS讲解

事实上这两部分比较简单
所以并在一起讲解了
讲解前先点开FLA文件,把这两个MC看看,对MC构造了解了,才能写CLASS嘛~

看下得分显示类的代码

复制内容到剪贴板
代码:
class game.Score_view extends MovieClip {
    private var w1:MovieClip;
    private var w2:MovieClip;
    private var w3:MovieClip;
    private var w4:MovieClip;
    private var w5:MovieClip;
    private var w6:MovieClip;
    private var i:Number
    //构造函数
    function Score_view() {
        init();
    }
    //公-私有方法
    public function init() {
        onEnterFrame = Control;
    }
    private function Control() {
        for (i=1; i<=6; i++) {
            if (i<=int(String(_root.score).length)) {
                this["w"+i].gotoAndStop(int(String(_root.score).substr(i*(-1), 1))+1);
            } else {
                this["w"+i].gotoAndStop(1);
            }
        }
    }
}

原理很简单,就是让这个MC一直onEnterFrame着,按照总得分来不断操控MC里的6个数字MC变化
仔细思考下Control()里的代码,想通了其实很简单哦~~
不多说了,懂了后就跟我看时间控制类的(不懂就继续看,直到看懂为止)

下面是时间控制类

复制内容到剪贴板
代码:
class game.Time_control extends MovieClip{
    private var t:Number
    public var time:Number
    //------------------------------------------
    /*
    function Time_control(){
        init()
    }
    */这段被注销掉了,因为我不要它一出现在舞台就开始倒计时。什么时候倒计时,游戏控制类会给本类发出命令(调用本类中的Go()的function)
    //-------------------------------------------
    public function set _time(ttt:Number):Void{
        time=ttt
    }
    public function get _time():Number{
        return(time)
    }
    //===========================================    
    private function TimeGo(){
        t++
        if(t%30==0) time--
        if(time==0) {
            delete onEnterFrame
            _root.game_c.endGame()
        }
    }//倒计时代码,当时间=0,通知游戏控制类作出endGame()的行为。
    public function Go(){
        t=1
        time=30        
        onEnterFrame=TimeGo
    }//初始化,并开始倒计时
}

有了前两节的基础,这节显的很简单……(感觉好像应该先教这节啊……- -……是不是难度顺序颠倒了??)
下节会讲最后的,也是很重要的类-游戏控制类,尽请期待~!

 

 

 

LESSON 10 范例接宝游戏中游戏控制类的CLASS讲解

终于讲到这节了,累死,也饿死,为了明年年初要拍婚纱,我每天中午就吃个苹果减肥,然后靠苹果的能量再给鸟鸟们写教程……
今天算是暴走式的更新速度了,从第7节写到了第10节,胃软导致了手软,手软导致了脚软,较软导致了XX也软……
版主看到,体恤下吧,加点分,我好早日升中级会员……(咳咳)

本节讲的是最后一个类:游戏控制类
我自己每个游戏都会在舞台上有这个MC帮我看场子,指挥调度手下的兄弟,提供各类凶器,把握整个进程……

这个游戏的游戏控制类:Game_control.as
先点开FLA里的MC,看看它的构造。
有两个框,一个是选择人物的,一个是显示最高得分的。
我用它们两的visible属性控制它们可见和不可见。

Game_control.as把握着整个游戏的进程,提供了一些方法。

先看它怎么控制游戏的:
1.先初始化游戏参数,然后让选人框可见,让玩家选人。
2.玩家选好人,它就把人物attach到舞台上,同时通知‘时间控制类’这个小弟你可以30秒倒计时了,又同时开始在天上撒金币和宝物。
3.‘时间控制类’小弟一看时间到0了,马上又来通知大哥,时间到0了
4.大哥收到风声后,停止撒金币,让画面上已有的金币宝物全部消失,同时一番比较后显示出你的历史最高分,同时提供你个重新游戏的按钮
5.按重新游戏,大哥就回到第1步……
(好像所有小弟里,只有分数显示自管自工作,没有被大哥叫到)

它包含了一些方法,供小弟和自己用:
1.初始化数据:init()
2.根据玩家选择,在舞台上attach人物:chose(n:Number)
3.天上播撒金币和宝物:onGame()
4.屏幕上宝物消失:jin_disappear()
5.结束游戏,比较得分和最高分,让显示框显示最高分:endGame()

对照着我们来看下代码

复制内容到剪贴板
代码:
class game.Game_control extends MovieClip {
    private var t:Number = 1;    
    private var game_begin:MovieClip
    private var game_end:MovieClip    
    private var depth:Number
    private var topScore:Number=0
    public var time:Number;
    //构造函数
    function Game_control() {        
        init();
    }
    //隐式设置方法
    public function set _time(ttt:Number):Void {
    }
    //公-私有方法
    public function init() {        
        time=35
        _root.score = 0;
        _root.createEmptyMovieClip("pl", 3);        
        _root.createEmptyMovieClip("item", 2);
        _root.createEmptyMovieClip("xs", 1);
        //初始化里建立空MC,同时也就是把以前的MC删除覆盖
        game_begin._visible=true
        game_end._visible=false
        _root.music_control.bg(1)
    }    
    public function chose(n:Number) {
        game_begin._visible=false        
        _root.pl.attachMovie("ren"+n, "player", 1);
        _root.time_c.Go()//时间控制小弟~号开始倒计时啦~
        _root.music_control.bg(2)
        onEnterFrame = onGame;
    }
    private function onGame() {        
        t++;
        if (t%time == 0) {
            depth=_root.item.getNextHighestDepth()
            if (random(8) == 0) {
                var a:MovieClip=_root.item.attachMovie("bao"+(1+random(2)), "bao"+depth, depth++);                
            }
            else if (random(5) == 0) {
                var a:MovieClip=_root.item.attachMovie("jin2", "jin"+depth, depth++);
                a.score=50                
            } else {
                _root.item.attachMovie("jin1", "jin"+depth, depth++);
            }
            time = 20+random(30);
        }//这段自己仔细看下,就明白怎么随机时间间隔里播撒出随即类型的宝物了
    }
    private function jin_disappear() {
        for(var i:String in _root.item){
            _root.item[i]._speed=0
            _root.item[i]._bspeed()//这个方法Jin.as里写过的,还记得吗?哈哈
            _root.item[i]._alpha-=5
            _root.item[i]._xscale+=2
            _root.item[i]._yscale+=2
            if(_root.item[i]._alpha<0) {
                _root.item[i].removeMovieClip()
                delete onEnterFrame
            }
        }//大小和alpha同时变化直到宝物消失~
    }
    public function endGame(){
        onEnterFrame=jin_disappear
        game_end._visible=true
        if(_root.score>topScore) {
            topScore=_root.score
            game_end.sc=topScore
        }//判断和记录历时最高分,同时显示最高分框显示~
    }
}

事实上在人物选择框,两个人物是按钮,用来调用‘游戏控制’类里的chose(n:Number)方法。
当chose(n:Number)被调用时,后面一连串的进程就都自动展开了……

今天一下子讲的太多了,能消化掉吗?
游戏主体也就这样了。剩下点小东西,比如声音控制,下节课讲。

 

 

 

LESSON 11 声音控制&我对FLASH创作游戏的看法

【响应正版号召,再次宣传】

本文作者:周云(老鸟可以直接叫小弟我小周,粉丝必须称呼周哥,讨教的嫩鸟就叫声周老师吧,满足下我的欲望,啊哈哈哈~)
联系方式:danyun1982@163.com
首发于蓝色经典论坛

欢迎转载呀~(不欢迎又咋样……要转照样转……)
转载必须保留我的作者名称和联系方法,不然转载者生个儿子+String(a)
c=["gu","yan"]
b=["长不高","没P"+c[random(c.length)],"是女孩"]
a=b[random(b.length)]+"呀~!"

我喝了半瓶子水~幻想自己刚吃了个鸡腿~死撑着把这最后节不缩水的写完~
让我们来看看声音控制部分吧~

声音控制,我个人不习惯用类来控制。
我一直是在游戏第一帧先用Sound类把库里的声音关联起来
然后做个Object,在里面定义function来控制声音的
当然你也可以写个类来控制,这随你的,用痰盂还是马桶,我们谁也不能强求谁,对吧?

把第一帧的声音控制代码拿出来~~~

复制内容到剪贴板
代码:
/////////---声音控制---/////////////
music_bg1 = new Sound();
music_bg1.attachSound("bg1");
music_bg2 = new Sound();
music_bg2.attachSound("bg2");
music_bg_jin = new Sound();
music_bg_jin.attachSound("bg_jin");
music_bg_bao = new Sound();
music_bg_bao.attachSound("bg_bao");
//库里的声音文件都关联起来~
music_control = new Object();
music_control.bg = function(n) {
    for (i=1; i<=2; i++) {
        _root["music_bg"+i].stop();
    }
    _root["music_bg"+n].start(0, 999);
};
music_control.snd = function(n) {
    _root["music_bg_"+n].start(0, 1);
};
//music_control这个Ob里定义了bg()和snd两个方法,bg用来放长段背景音乐,snd用来放音效
_root.music_control.bg(1)
//看,就是这么用的

现在前面几节那些CLASS里写到的声音调用语句知道是怎么回事了吧?

----------------------饥肠辘辘的分割线------------------------

游戏开发基础的课程,至此已经全部写完了。
范例游戏有很多地方可以扩充,比如加点掉宝种类,再加几个人物和技能,玩到一半掉下只猪……等等等等
我只是抛砖引玉下而已~
要玩我做的游戏?等我找找……随便先找个
http://www.mhhf.net/games_786.html
如果喜欢,我可以再开贴教这类STG射击型的,或者动作闯关型的,或者FMS联机型的,或者XX型的,或者YY型的都可以……

关于做游戏,事实上正规的团队应该有三种人:
1.策划
2.美工
3.程序员
但实际上,FLASH这种东西,相比其它,真的属于不赚钱的。所以搞的专业人士不多。
大多数情况下,都是闪客单干。
所以很多时候开发都不正规,比如代码不注释~在一个FLA里,帧里,隐蔽的很多MC的小边小角里,敲了很多代码,如果有人接手,必然会分析到晕倒……
这种不正规,在长时间单干下,是不会被意识到并且改正的。但如果参加过团队制作,就会立即意识到这个问题。

一个好程序员,或者懂的很多的牛人,并不会必定是个好的游戏开发者
我自己见过好几个自己认为技术很牛的人,他们并不做游戏,或者游戏做出来并不受欢迎
他们自己分析原因是没好美工,导致画面粗糙,不吸引人
而我则认为更主要的原因是缺少好的游戏策划
在我心里,游戏受欢迎程度取决的因素:策划>程序>美工
就比如细节方面,好的策划知道怎么样的设定更体贴玩家,知道什么元素能抓牢玩家,什么能激起玩家欲望,什么能让玩家HIGH
老实说,这比懂CLASS重要得多了

如果你跟我一样是一名独立创作FLASH游戏的制作者,那你先要成为一名很好的游戏玩家。
要能从玩家的角度来设计制作游戏。
当然,策划游戏,是需要天赋的。

我们不能要求每个人样样都完美,毕竟每个人都有自己擅长的和不擅长的。
继续努力吧。

最后一句,如果以后来上海想请我吃饭我一定会带上老婆给你DOUBLE面子的……

 

 

 

这篇教程足以让我研究几天了……