实验六 角色设计实验

更新时间:2023-04-08 02:43:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

上机实验须知

实验名称:

Flash角色设计的实现

实验目的:

利用角色设计思想,设计战场生存记游戏中的主要角色:小兵、大炮和炮弹。

实验环境:

1)高档微机

2)Windows操作系统中文版

3)Flash CS3 Professional中文版

实验原理:

从广义上说,所谓角色,就是游戏中的各种人物、怪物、武器、设备、环境等等,只要是具有一定外观的、集成了这个外观指代的对象的所有功能的独立模块,都可以称为是角色。

在Flash里面,角色的设计其实非常的简单。MovieClip类已经为我们构建了一个角色所需的基本框架,只要在这个框架下设计某个角色的所有外观、特征、动画、特技、属性、函数以及事件,就可以完成角色设计。换句话说,Flash角色的本质是一个高度专门化的影片剪辑,它对外提供角色接口,对内则实现这些接口。

一般来说,设计角色遵循自上而下,由主体到细节的思路。即一开始确认你要做的是什么样的角色,它有哪些功能,将这个功能描述出来,具体的功能将被表示为属性、方法和事件的列表。然后根据这个功能表将这些功能在内部一一实现。

实验内容:

假设需要设计一个这样的游戏:

虽然你是一个英雄,但是你在一个空旷的战场上被包围了,四周布满了大炮。你唯一的目标就是生存下来。大炮总是会往你所在的位置开炮,所以你得不停地跑!按方向键进行上下左右跑动。

这里将游戏分为若干个角色。其中主要角色包括:

1)小兵:它可以在屏幕的范围内到处跑动,躲避炮弹的袭击。如果被炮弹打中游戏就结束了。2)大炮:它总是能够自动对准小兵所在的方向,然后随机地打出炮弹

3)炮弹:被发射出来以后就沿着一条直线运动直到运动到屏幕范围之外,当碰到小兵的时候小兵将被打中而死去。

这里大炮是否打中小兵,要使用冲突检测技术来实现。由于我们还没有讲解到这个技术,所以暂时先不考虑这个问题,我们把实验简化为小兵可以到处跑,大炮总是对准小兵,随机打出炮弹,但炮弹对小兵不起作用。也就是完成大炮、小兵、炮弹三个角色的主要功能即完成本实验。

实验步骤:

1)新建Flash文档(ActionScript3.0),设置文档的帧频率为50,大小为490*540。

2)导入声音:导入三个声音文件,它们分别是跑动的声音、爆炸的声音的开炮的声音。分别链接为RunningSound、BombSound 、ShootSound输出。

3)设计小兵

确定这个角色的成员为:

成员成员描述

status 角色当前所处的状态

run(direction) 向指定的方向跑动

stand() 站立不动

dead() 死去

设计这个角色的动画,将这个角色的动画展开如下图所示:

1

2

将动画串在一个剪辑中。总共8帧,第1帧空白,2~8帧内容与上图编号顺序对应。对齐这些素材,使得播放时是一个完整的动画效果。

在这个剪辑的时间轴上新建图层,改名为action ,设置第2帧的帧标签为stop ,第3帧为run ,第8帧为dead (先将它们设置为关键帧)。

编写代码以便完成全部的角色功能。由于这个角色比较简单,所以其代码量很少,但我们可以从中了解角色设计的“套路”。

在第1帧中输入以下代码: var status:String="init";

var speed:Number, radio:Number;

var direction=0;

var x1 = 49, y1 = 99, x2 = 447, y2 = 500;//角色能跑动的范围

function run(dir:int) {

direction=dir;

addEventListener(Event.ENTER_FRAME,runOnce);

}

function runOnce(Event) {//跑动,dir 指示跑动的方向

if (direction==0) {

stand();

return;

}

if (direction==3) {

x -= speed;

if (x

x = x1+radio;

}

}

if (direction==2) {

y += speed;

if (y>y2-radio) {

y = y2-radio;

}

}

if (direction ==1) {

x += speed;

if (x>x2-radio) {

x = x2-radio;

}

}

if (direction==4) {

y -= speed;

if (y

y = y1+radio;

}

}

rotation = 90*(direction-1);

if (status!="running") {

gotoAndPlay("run");

}

}

function stand() {

removeEventListener(Event.ENTER_FRAME,runOnce);

gotoAndStop("stop");

}

function dead() {

gotoAndStop("dead");

}

这段代码对角色初始化并将几个公共函数实现。

第2帧输入以下代码:

stop();

status="stoping";

speed = 10;

radio = 25;

这一帧表示角色处于停止状态,并且设置了两个变量,这在以后的程序中会使用到。

第3帧输入以下代码:

status="running";

var s=new RunningSound();

s.play();

这一帧表示角色处于运动状态,并且播放一个声音。RunningSound是库中一个跑步声的链接名称。如果没有使用声音,应将后两行代码删除。

第7帧输入以下代码:

gotoAndPlay("run");

这条跳转语句使得角色一旦进入跑步状态,它将处于原地踏步的循环之中。

第8帧输入以下代码:

stop();

removeEventListener(Event.ENTER_FRAME,runOnce);

status="dead";

于是完成了这个角色的设计,后面将把这个角色用于多个游戏中。

测试这个角色的方法:

将这个角色应用在游戏中是非常简单的。步骤如下:

将做好的英雄剪辑从库中拖出置于舞台上。由于剪辑的第一帧是空白的,所以我们这个时

3

候在舞台上看到的是一个空心的圆圈。

◆选中这个剪辑实例,在属性栏中设置它的实例名称为hero。

◆在主时间轴剪辑中新建图层,改名为action,然后在第一帧输入以下代码:

stage.addEventListener(KeyboardEvent.KEY_DOWN,heroRun);//跑动

stage.addEventListener(KeyboardEvent.KEY_UP,heroStop);//取消跑动

function heroStop(KeyboardEvent) {

hero.stand();

}

function heroRun(evt:KeyboardEvent) {

var direction:Number=0;//英雄跑动的方向。1~4分别表示东南西北,

0表示不动。

if (evt.keyCode==Keyboard.LEFT) {

direction=3;

}

if (evt.keyCode ==Keyboard.UP) {

direction=4;

}

if (evt.keyCode ==Keyboard.RIGHT) {

direction=1;

}

if (evt.keyCode ==Keyboard.DOWN) {

direction=2;

}

hero.run(direction);

return;

}

保存文件,然后按Ctrl+Enter测试程序,看时候能够用键盘方向键控制这个角色的四处跑动。

4)制作炮弹

炮弹在被创建之后直线运动,这个我们已经能够轻松实现了。

炮弹角色应该包含如下的成员:

成员成员描述

setEnemy(enemy) 给炮弹注册一个敌人

setSpeed (jiaodu,speed) 设置炮弹发射的角度和速度

moveBall() 以当前速度移动一次炮弹

repeat() 重复执行的代码,与enterFrame事件配合

事实上,当炮弹被复制后设置它的位置、速度、注册敌人之后,其它所有操作都在repeat函数中自动完成,不需要添加更多的代码。

已经做好的炮弹剪辑的时间轴如下图所示:

炮弹剪辑的时间轴

4

其中炮弹图层第1帧绘制一个大约5*5尺寸的小圆素材,表示炮弹,接着2~4帧为小圆爆破的一个小动画。action图层第1帧的代码:

stop();

var stageWidth = 490, stageHeight = 540;

var speedx:Number, speedy:Number;

var radio:Number = this.width/2;

var enemy:Array;

addEventListener(Event.ENTER_FRAME,repeat);

function repeat(e:Event) {

moveBall();//炮弹的运动

}

function moveBall() {

var newx = this.x+speedx;

var newy = this.y+speedy;

if (newxstageWidth-radio) {

removeEventListener(Event.ENTER_FRAME,repeat);

parent.removeChild(this);

return;

} else {

this.x = newx;

}

if (newystageHeight-radio) {

removeEventListener(Event.ENTER_FRAME,repeat);

parent.removeChild(this);

return;

} else {

this.y = newy;

}

}

function setEnemy(enemyName:MovieClip) {//注册敌人

if (enemy==null) {

enemy=new Array();

}

enemy.push(enemyName);

}

function setSpeed(jiaodu:Number,speed:Number=5) {

//根据初速度和角度确定炮弹的运动

speedx = speed*Math.cos(jiaodu);

speedy = speed*Math.sin(jiaodu);

}

这一帧代码的实现了炮弹几乎全部的功能。

第2帧设置帧标签为bomb,并输入以下代码:

var s=new BombSound();

s.play();

5

6 这段代码指示当炮弹爆炸的时候播放爆炸的声音,其中BombSound 是爆炸音效的链接名称。 到第4帧时炮弹已经爆炸完毕,应该删除这个炮弹。代码如下:

stop();

removeEventListener(Event.ENTER_FRAME,repeat);

parent.removeChild(this);

注意:这里一定要先删除事件处理函数,然后再将它从显示层次结构中删除。因为即使将其从显示列表删除,如果它还有其它引用或者还有事件处理函数,这个炮弹也不会被当作垃圾回收。这将导致程序性能急剧下降或者发生程序逻辑混乱。

完成炮弹的设计后,将其链接为Bullet 以备使用。

5) 设计大炮

这里设计的大炮非常“聪明”,它总能知道英雄在哪里,并不时向英雄发出致命的炮弹。很明显,这又是通过延迟一段时间就重复执行一段代码来实现。由于炮管需要在运行时旋转,所以设计成一个独立的剪辑嵌套在大炮剪辑内。

设计好的大炮如下图所示:

大炮剪辑的可视对象

炮管的原点即为大炮剪辑的原点,这样在程序中控制它的旋转就会比较方便。设置炮管的实例名称为paoguan 。由于后面需要精确确定炮弹的初始位置,所以在炮管剪辑内又嵌着炮头剪辑,以便用它的坐标来确定炮弹的出口。炮头的实例名称设置为paotou 。

大炮剪辑只有一帧,在这一帧上输入如下的代码: stop();

var enemy:MovieClip=MovieClip(parent.getChildByName("hero"));

addEventListener(Event.ENTER_FRAME,repeat);

function repeat(e:Event) {

if (enemy==null||enemy.status=="dead"|| enemy.status=="victory") {//没有

敌人或者敌人已死或者敌人已经取得胜利

return;

}

var deltaX = enemy.x-x;//与敌人在x 方向上的距离

var deltaY = enemy.y-y;//与敌人在y 方向上的距离

var xieBian = Math.sqrt(deltaX*deltaX+deltaY*deltaY);//两者的直线距离

var theta = Math.asin(deltaY/xieBian);//距离直线的角度,为弧度制

if (deltaX<0) {

theta = Math.PI-theta;

}

paoguan.rotation = theta*180/Math.PI;//按计算的角度旋转炮管

if (Math.round(Math.random()*120) == 2 ) {//发射大炮

var bullet=new Bullet();//生成一个新的大炮

//大炮定位

var point=new Point(paoguan.paotou.x,paoguan.paotou.y);

point=paoguan.paotou.localToGlobal(point);

bullet.x =point.x;

bullet.y =point.y;

//大炮定位

bullet.setSpeed(theta,2);//设置炮弹的初始方向和速度

bullet.setEnemy(enemy);//设置炮弹的敌人

parent.addChild(bullet);

var s = new ShootSound();//播放声音

s.play();

}

}

这段代码首先确定炮弹要瞄准的对象(enemy),然后重复执行一段代码。这段代码的作用是跟踪enemy的位置,让炮管瞄准enemy,并且按一定的随机几率发射炮弹。这里将enemy硬性设置为其父层级的hero实例。这样做的好处是只要将英雄实例名称定义为hero,即可可以不添加任何代码,直接将大炮布置在场景中使用。但缺点是可控性差了一些,如果英雄不是命名为hero,则大炮就会“哑火”。如果只是设计一个小游戏,可以大胆采用这种方法,以便充分利用Flash可视化设计的优势。

6)将大炮剪辑从库中拖出置于舞台上,可以多复制几个剪辑,排布于舞台的四周,保存文件,按Ctril+Enter测试程序,看是否达到原定的要求。

7

本文来源:https://www.bwwdw.com/article/a65l.html

Top