打砖块游戏大家都很熟悉:游戏者用一个挡板对小球进行反弹,上方排列了一些方块砖,游戏的目的就是利用鼠标对挡板进行左右移动控制,以便将小球挡回去,避免小球落到挡板的下方,挡回去的小球将与上面的方砖发生碰撞,被碰撞的方砖会自动显示,玩家每打掉一块方砖,会得到一定的分数。
在本实例中每局中玩家的生命值为5,如果将当前界面中的方砖全部打完,则进入下一关。游戏开始允许玩家选择游戏难度:初级、中级和高级,不同的难度中方砖的数量和小球运动的速度不同,玩家可以根据自己的水平来选择合适的游戏难度。
游戏制作思路:
本游戏主要涉及到以下几种主要控制:
1.鼠标拖动:游戏中需要使用鼠标拖动档板左右移动来挡小球,此功能也是很多游戏中常用的,用startdrag函数很容易就解决了。
2.小球的反弹控制:游戏中小球会不断和墙壁、挡板或者方砖发生碰撞,所以需要使用Action来控制小球的反弹。
3.方砖和小球的碰撞测试:游戏中需要检测小球是否碰到了方砖,此功能可以使用hitTest碰撞测试函数来检测。
4.游戏的记分和生命值:在游戏中需要动态的显示当前玩家的游戏得分和玩家剩余的生命值,这里使用动态文本框(Dynamic text)实现显示分数的功能。
通过以上几点的分析,可以大概理顺游戏的制作思路,下面我们就来进行本游戏的具体制作。
游戏的制作步骤:
1.小球的制作:此类游戏中小球是必不可少的对象,所以我们可以随意绘制一个小球,再填充上合适的颜色,不过因为我们需要在后面使用Action对小球进行控制,所以这里我们将小球做成movie clip,命名为ball,如图1所示:
图1
2.小球反弹效果制作:因为游戏中小球要在多个场合进行反弹,所以需要制作一个小球进行反弹的效果,这里我们新建一个movie clip,命名为ball_jmp,进入组件的编辑状态后,在原有图层layer1的上方新建一个图层layer2,我们要的效果是小球由下自上弹起来,所以图层layer1制作小球阴影由小到大的的shpae形状变化效果,图层layer2制作小球由下自上的motion运动效果,如图2所示:
图2
3.背景变幻效果:如果在游戏的过程中能不断的变换游戏背景,可以使游戏气氛显的很紧张,玩起来也很刺激,所以就制作一个背景颜色快速变化的Mc,新建一个movie clip,命名为background,在第一帧使用矩形工具绘制一个填充色为蓝色的矩形,如图3所示:
图3
然后在图层layer1的第2帧插入一个关键帧,在第8帧也插入一个关键帧,并将第8浈中的矩形填充色改变为浅蓝色,然后建立第2帧到第8帧的shape形状过度效果,最后将时间线延长到第10帧,如图4所示,
图4
在图层layer1的第1帧添加AS:
play = 0;
stop(); //定义变量play,然后暂停播放
在图层layer1的第2帧添加AS:
play = Number(play)+1;
setProperty("/ball", _visible, false);
tellTarget ("/")
//变量play的值为当前值增一,然后设置小球为不可见,主场景停止播放
在图层layer1的第8帧添加AS:
if (Number(play)<3) else {
if (Number(endgame) == Number(false)) {
tellTarget ("/")
}
if (Number(/:endgame) == Number(false)) {
setProperty("/ball", _visible, true);
}
gotoAndStop(1);
}
//根据变量play和endgame的不同值,跳转到不同的帧,并设置小球为可见
4. 游戏难度选择按钮的制作:本游戏可以在游戏开始前选择游戏难度,游戏中一共分为三种难度,分别是初级,中级和高级,不同的难度方砖的数量和小球运动的速度将不同,玩家可以根据自己的水平来选择合适的游戏难度。这里以其中一个按钮为例进行说明,其它两个按钮制作方法类似。
新建一个button按钮组件,命名为advanced,进入组件编辑状态后,在按钮的UP帧处输入advanced几个字,代表高级难度,然后在OVER帧插入一个关键帧,将前面做好的组件ball_jmp拖到文字的左方,然后分别在DOWN帧和Hit帧插入关键帧,如图5所示:
图6
按照同样的方法制作其它两个按钮,分别为beginner和intermediate,代表了初级和中级。
5.档板的制作:接下来制作游戏中另一个很重要的角色——档板,档板在游戏中被鼠标控制,用来挡回小球,因为游戏中需要使用Action对挡板进行控制,所以档板也需要制作成movie clip.新建一个Movie clip,命名为paddle,进入组件的编辑状态后,使用矩形工具绘制一个填充色为红色渐变的矩形,如图6所示;
图6
6.砖块的制作:游戏的目的就是利用小球击中更多的方砖,所以方砖是必不可少的,为了使游戏的视觉效果更加突出,本游戏一共制作了四种不同颜色的方砖,分别为黄色,红色,蓝色和绿色的砖块,这里我们只对其中的一种蓝色转块的制作进行讲解,其它三中的制作方法类似。
新建一个movie clip,命名为brickblue,进入组件的辨别状态后,先用矩形工具绘制一个填充色为蓝色渐变的矩形,如图7所示:
图7
然后在图层layer1的第2帧插入关键帧,将矩形的填充色改变为红色,并且将矩形分解为不同的几部分,以便制作砖块爆炸开的效果,如图8所示:
图8
在图层layer1的第9帧插入关键帧,在此帧将矩形的几部分拖拉成扩散状,并将每一碎片进行适当的缩小,然后在第2帧到第9帧之间建立shape形状过渡动画,图9为打开洋葱皮功能的效果:
图9
为了使爆炸效果更加逼真,我们在进行一下修饰,新建一个图层layer2,再第2帧插入一个关键帧,然后使用椭圆工具绘制一个具有红色渐变填充色的圆形,如图10所示;
图10
然后在第2帧到第10帧之间做一个圆形放大且透明度增加的shape形状过渡,如图11所示:
图11
这样,砖块的爆炸效果就很好的体现出来了。
最后还需要添加一些控制用的Action,在图层layer1的第1帧添加如下AS:
vis = 1;
stop();
在图层layer1的第2帧添加如下AS:
todest = /:destroy;
在图层layer1的第10帧添加如下AS:
removeMovieClip("/brick" add todest);
stop();
到此为止,游戏中需要用到的所有组件就准备好了,下面我们来进行主场景的布置。
二、布置主场景
1.回到主场景中,将原来的图层layer1更名为background,此层放置游戏的背景。使用矩形工具在舞台上绘制一个和舞台同样大小的填充色为深蓝色的矩形,作为游戏的整体背景,然后将组件background拖到舞台的靠右的位置,作为游戏的主体背景,如图12所示:
图12
2.新建一个图层命名为bricks,此层用来放置四种颜色的砖块,将四种不同颜色的砖块分别自上而下拖放到舞台的左边,并给四中颜色的砖块分别设置实例名为brick, brickred, brickblue和brickgreen,如图13所示:
图13
3.再分别新建两个图层,分别命名为ball和paddle,将小球和档板分别拖放到主背景的靠下的位置,并分别设置实例名为ball和paddle,如图14所示:
图14
4.新建一个图层命名为info,此层用来放置记分和生命值用的文本框,分别用文本工具绘制三个文本框,设置其属性为Dynamic text动态文本框,然后给文本框添加说明性文字,从上到下分别为分数,生命值和等级,最后分别给此三个文本框设置变量名为score,balls和level_I,如图15所示:
图15
5. 新建一个图层命名为button,此图层放置游戏开始前的难度选择按钮,将前面制作的三个难度按钮分别拖到主背景的中间位置,由上自下分别为beginner, intermediate和Addvanced。
给beginner按钮添加AS:
on (release) {
speed = 8;
balls = 5;
play();
}
给intermediate按钮添加AS:
on (release) {
balls = 4;
speed = 10;
play();
}
给Addvanced按钮添加AS:
on (release) {
speed = 12;
balls = 3;
play();
}
最后主场景如图16所示:
图16
6.最后一步就需要在主场景中添加游戏控制代码了,新建一个图层命名为action,在此图层第1 帧添加as:
setProperty("/paddle", _visible, true);
setProperty("/ball", _visible, true);
score = 0;
stop();
//刚开始设置小球和挡板为可见,并且设置初始得分为0,然后影片停止在第一帧,//等待玩家选择游戏难度。
在此图层第2 帧添加as:
startDrag("/paddle", false, 240, 420, 560, 420);
//对挡板进行拖动
ballx = 300;
bally = 400;
speedx = 8;
speedy = -8;
ballwidth = 16;
paddlewidth = 80;
brickwidth = 40;
Level_index = 10;
bricknumber = 0;
Level_i = 1;
modified = true;
endgame = false;
border = 250;
//定义并初始化一系列变量,将在后面的代码中用到这些变量
在此图层第3帧添加as:
if (endgame)
//变量endgame标识游戏是否结束,如果游戏结束,则跳转到第5帧
if (Number(bricknumber)<=0) {
Level_i = Level_index-9;
call(Level_index);
//设置游戏等级,也就是等级文本框中的内容,将调用自定义函数level_index.
setProperty("/brick", _visible, false);
setProperty("/brickblue", _visible, false);
setProperty("/brickgreen", _visible, false);
setProperty("/brickred", _visible, false);
//设置工作区中的方砖不可见
ballx = 300;
bally = 400;
speedx = Number(speed)+Number(xspeed)-5;
speedy = -speed-xspeed;
}
//设置小球位置和运动速度,ballx和bally代表小球坐标,speedx和speedy代//表小球横向和纵向的移动速度。
ballx = Number(ballx)+Number(speedx);
bally = Number(bally)+Number(speedy);
//根据小球移动速度改变小球坐标
if (Number(bally)<=Number(border)) {
b = int(ballwidth/2);
c1 = int((ballx-200)/40);
r1 = int((bally-b-40)/20);
c2 = int((ballx-b-200)/40);
r2 = int((bally-40)/20);
c3 = int((ballx-200)/40);
r3 = int((Number(bally)+Number(b)-40)/20);
c4 = int((Number(ballx)+Number(b)-200)/40);
r4 = int((bally-40)/20);
i = 1;
while (Number(i)<=4) {
r = eval ( "r" add i );
c = eval ( "c" add i );
IsVisible = getProperty ("brick" add r add c,_currentframe);
if (Number(IsVisible) == 1) {
bricknumber = bricknumber-1;
score = Number(score)+100;
destroy = r add c;
tellTarget ("brick" add destroy)
if ((Number(i) == 2) or (Number(i) == 4)) {
speedx = -speedx;
ballx = Number(ballx)+Number(speedx);
i = 5;
} else {
speedy = -speedy;
bally = Number(bally)+Number(speedy);
i = 5;
}
}
i = Number(i)+1;
}
}
//上面的一系列代码用来判断和小球和方砖的碰撞,然后方砖消失
if ((Number(ballx)>=Number(600-ballwidth/2)) or (Number(ballx)<=Number(200+Number(ballwidth/2)))) {
speedx = -speedx;
ballx = Number(ballx)+Number(speedx);
tellTarget ("/sound")
}
if (Number(bally)<=Number(41+Number(int(ballwidth/2)))) {
tellTarget ("/sound")
speedy = -speedy;
bally = Number(bally)+Number(speedy);
//判断小球和墙壁的碰撞,然后计算反弹方向和速度
paddlex = getProperty("paddle", _x);
if ((Number(bally)>404) and (Number(ballx)>Number((paddlex-paddlewidth/2-8))) and (Number(ballx)<Number((Number(Number(paddlex)+Number(paddlewidth/2))+8)))) {
if (Number(ballx)<Number(Number(paddlex-paddlewidth/2)+Number(int(paddlewidth/5)))) {
speedx = speedx-6;
} else if (Number(ballx)>Number(Number(paddlex)+Number(paddlewidth/2)-int(paddlewidth/5))) {
speedx = Number(speedx)+6;
} else if (Number(ballx)<Number(Number(paddlex-paddlewidth/2)+Number(int(paddlewidth/3)))) {
speedx = speedx-3;
} else if (Number(ballx)>Number(Number(paddlex)+Number(paddlewidth/2)-int(paddlewidth/3))) {
speedx = Number(speedx)+3;
}
speedy = -speedy;
bally = Number(bally)+Number(speedy);
tellTarget ("/sound")
}
//判断小球和挡板的碰撞,然后计算反弹方向和速度
setProperty("/ball", _x, ballx);
setProperty("/ball", _y, bally);
//设置小球的新位置,从而移动小球
在此图层第4 帧添加as:
if (Number(balls)<1) {
endgame = true;
gotoAndStop(6);
}
//如果生命值balls为0,则游戏结束
gotoAndPlay("loopback");
在此图层第5 帧添加as:
setProperty("/paddle", _visible, false);
//设置档板为不可见
tellTarget ("background")
在此图层第6 帧添加as:
stopDrag();
//停止拖动挡板
c = 0;
r = 0;
//c和r为两个循环变量
while (Number(r)<18) {
while (Number(c)<10) {
removeMovieClip("brick" add r add c);
c = Number(c)+1;
}
r = Number(r)+1;
c = 0;
}
//初始化变量,对游戏进行数值统计
在此图层第7 帧添加as:
stop();
在此图层第10 帧添加as:
xspeed = 0;
border = 240;
bricknumber = 50;
Level_index = Number(Level_index)+1;
//设置游戏的等级
c = 0;
r = 0;
//c和r为两个循环变量
count = 1;
index = 0;
while (Number(r)<5) {
while (Number(c)<Number(10-index)) {
duplicateMovieClip("/brickred", "brick" add r add c, Number(count)+1);
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
//复制对象brickred
r = Number(r)+2;
index = Number(index)+2;
c = index;
}
c = 1;
r = 1;
//c和r为两个循环变量
index = 0;
while (Number(r)<5) {
while (Number(c) duplicateMovieClip("/brickblue", "brick" add r add c, Number(count)+1);
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
//复制对象brickblue
r = Number(r)+2;
index = Number(index)+2;
c = Number(index)+1;
}
c = 0;
r = 7;
//c和r为两个循环变量
while (Number(r)<9) {
while (Number(c)<10) {
duplicateMovieClip("/brickgreen", "brick" add r add c, Number(count)+1);
//复制对象brickgreen,一共复制16个
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
//设置复制出的砖块的坐标
c = 0;
r = Number(r)+1;
}
setProperty("/brick", _visible, false);
在此图层第11 帧添加as,下面的as和第10帧相类似,不过游戏的等级更高
xspeed = 1;
border = 150;
bricknumber = 50;
Level_index = Number(Level_index)+1;
c = 0;
r = 0;
//c和r为两个循环变量
count = 1;
while (Number(r)<5) {
while (Number(c)<10) {
if (((Number(r)<=Number(c)) and (Number(c)<5)) or ((Number(c)>=5) and (Number(c)<=Number(9-r)))) {
duplicateMovieClip("/brick", "brick" add r add c, Number(count)+1);
} else {
duplicateMovieClip("/brickgreen", "brick" add r add c, Number(count)+1);
}
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
count = Number(count)+1;
c = Number(c)+1;
}
//复制对象brick
r = Number(r)+1;
c = 0;
}
在此图层第12 帧添加as, 下面的as和第11帧相类似,不过游戏的等级更高
xspeed = 2;
border = 330;
bricknumber = 60;
c = 0;
r = 0;
//c和r为两个循环变量
count = 1;
while (Number(r)<14) {
while (Number(c)<10) {
if ((Number(r) == 5) or (Number(r) == 8)) {
duplicateMovieClip("/brickred", "brick" add r add c, Number(count)+1);
} else if ((Number(r) == 13) or (Number(r) == 0)) {
duplicateMovieClip("/brickblue", "brick" add r add c, Number(count)+1);
} else if ((Number(r) == 7) or (Number(r) == 6)) {
duplicateMovieClip("/brick", "brick" add r add c, Number(count)+1);
}
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
r = Number(r)+1;
c = 0;
}
setProperty("/brick", _visible, false);
在此图层第13 帧添加as,下面的as和第12帧相类似,不过游戏的等级更高
xspeed = 3;
border = 250;
bricknumber = 72;
c = 0;
r = 0;
//c和r为两个循环变量
count = 1;
while (Number(r)<10) {
while (Number(c)<10) {
if (((Number(r)>1) and (Number(r)<8) and (Number(c)>3) and (Number(c)<6)) or ((Number(c)>1) and (Number(c)<8) and (Number(r)>3) and (Number(r)<6))) {
duplicateMovieClip("/brickgreen", "brick" add r add c, Number(count)+1);
} else if (((Number(r) == Number(Number(5-9)+Number(c))) and (Number(r)>0) and (Number(r)<5)and (Number(c)>4) and (Number(c)<9)) or ((Number(r) == Number(5-c)) and (Number(r)>0) and (Number(r)<5) and (Number(c)>0) and (Number(c)<5)) or ((Number(9-r) == Number(5-c)) and (Number(r)>4) and (Number(r)<9) and (Number(c)>0) and (Number(c)<5)) or ((Number(9-r) == Number(Number(5-9)+Number(c))) and (Number(r)>4) and (Number(r)<9) and (Number(c)>4) and (Number(c)<9))) {
duplicateMovieClip("/brickred", "brick" add r add c, Number(count)+1);
} else if ((Number(r)>8) or (Number(r) == 0) or (Number(c) == 0) or (Number(c) == 9)) {
duplicateMovieClip("/brickblue", "brick" add r add c, Number(count)+1);
}
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
r = Number(r)+1;
c = 0;
}
setProperty("/brick", _visible, false);
在此图层第14 帧添加as,下面的as和第13帧相类似,不过游戏的等级更高
border = 370;
bricknumber = 116;
c = 0;
r = 0;
//c和r为两个循环变量
count = 1;
while (Number(r)<16) {
while (Number(c)<10) {
if (((Number(r)>1) and (Number(r)<9) and (Number(c) == 3)) or ((Number(r)>1) and (Number(r)<9)and (Number(c) == 6))) {
duplicateMovieClip("/brickblue", "brick" add r add c, Number(count)+1);
} else if (((Number(r)>1) and (Number(r)<9) and (Number(c) == 1)) or ((Number(r)>1) and (Number(r)<9) and (Number(c) == 8))) {
duplicateMovieClip("/brickred", "brick" add r add c, Number(count)+1);
} else if (((Number(r) == 0) and (Number(c)>2) and (Number(c)<7)) or ((Number(r) == 7) and (Number(c)>2) and (Number(c)<7)) or ((Number(r) == 8) and (Number(c)>2) and (Number(c)<7))) {
duplicateMovieClip("/brickblue", "brick" add r add c, Number(count)+1);
} else if ((Number(r) == 1)) {
duplicateMovieClip("/brickgreen", "brick" add r add c, Number(count)+1);
} else if (Number(r)>8) {
duplicateMovieClip("/brick", "brick" add r add c, Number(count)+1);
}
setProperty("brick" add r add c, _x, 220+Number(40*c));
setProperty("brick" add r add c, _y, 50+Number(20*r));
c = Number(c)+1;
count = Number(count)+1;
}
r = Number(r)+1;
c = 0;
v}
setProperty("/brick", _visible, false);
在此图层第15 帧添加as:
endgame = true;
Level_index = Number(Level_index)+1;
最后时间线如图17所示:
图17
最后您就可以进行游戏的测试了。本游戏的制作难度属于中等难度,掌握好此游戏的制作方法,您还可以尝试更复杂一些的游戏制作。