从零开始学AS3游戏开发【五】 告别方块,添加碰撞
2011-12-28 16:14
375 查看
注:本系列教程每周一篇,旨在引导刚刚接触FLASH的新手通过实例进行游戏开发的学习。在过程中逐步说明涉及到的类及对应的使用方法。从一个光秃秃的方块开始,根据不同的控制方式、玩法产生不同的分支,最终完善成一个个可玩的游戏。希望对各位入门的朋友有所帮助!在教程涉及的各种处理方法,可能不够完善,也希望各位高手指正:)
转载请注名来源于天地会。
第五篇 告别方块,添加碰撞
在上一篇教程中。我们新增了基地的概念,并让敌人可以向基地开火。但是,敌人和自己还都是四四方方一大块,分不清哪是脸哪是屁股。另外在游戏界面里,各个对象依然可以重叠在一起。这显然不太合理。在本次的教程中,我们将一一修正这些问题。
首先,换个脸。在FLASH里对原有的组件进行编辑,我们随便画一个坦克的样子,大概像下面这样:
这样,就有了比较像样(至少不是方块)的素材了。不过,新的问题出现了。这个时候测试影片,我们可以发现,当坦克向上开的时候,是没问题的,但是向其他方向移动,素材并没有发生变化,而是横着走,或者倒退了。我们需要根据坦克的方向来调整素材的旋转角度。于是,我们重写了FaceObject的direction方法:
override public function set direction(dir:uint):void
{
super.direction = dir;
var angle:Number;
var tx:Number;
var ty:Number;
switch(dir)
{
case ActionObject.UP:
angle = 0;
tx = 0;
ty = 0;
break;
case ActionObject.RIGHT:
angle = Math.PI * 0.5;
tx = _face.width;
ty = 0;
break;
case ActionObject.DOWN:
angle = Math.PI;
tx = _face.width;
ty = _face.height;
break;
case ActionObject.LEFT:
angle = Math.PI * 1.5;
tx = 0;
ty = _face.height;
break;
}
_face.transform.matrix = new Matrix(Math.cos(angle), Math.sin(angle),Math.sin(angle)*-1,Math.cos(angle),tx,ty);
}
复制代码
从代码中我们可以看出,是通过设置的方向值的不同,获取了一个特定的角度(向上0度,向右90度,向下180度,向左270度。注意这里的angle是用弧度来表示角的。)最后,我们定义了一个矩阵,并通过_face的transform来进行了形状的变化。
有兄弟可能会问为什么需要tx,ty两个属性呢?你可以把最后一行里的tx和ty去掉测试一下。可以发现,当素材旋转的时候,产生了位移。这是由于我们使用的素材的注册点是在左上角(可以看到图片上左上角那个十字么)。而旋转是围绕注册点进行的,也就是说,坦克的旋转是按照以下方式进行的:
可以看到,在旋转的过程中,坦克由于环绕左上的注册点旋转,实际上在4个方位各产生了与本身的宽度和高度相关的位移,因此,我们需要把他们移动相应的位置,使他们看起来还在原来的位置上。因此使用了tx,ty。
矩阵(Matrix)是一个非常有用的类。在我们的教程中也是第一次用到。矩阵的构造函数:
new Matrix(a,b,c,d,tx,ty)
其中各参数的说明如下:
在Adobe官方提供的文档中有详细的说明。这里不再过多描述,你可以看这里查看详细的说明:http://help.adobe.com/zh_CN/AS3L ... sh/geom/Matrix.html
现在,坦克的方向可以很清楚的看到了,下面,我们来看一下如何放置游戏场景里的物品与其他的物品撞到一起。我们来进行碰撞检测。
首先,随着游戏的扩展,并不是所有的游戏物体都能碰到(比如草丛可以踩过去等等),因此,游戏对象需要增加一个开关,来控制他是否参与碰撞检测.我们修改gameObject类,增加这个属性:
/**
* 是否参与碰撞检测
*/
protected var _hitTest:Boolean = false;
/**
* 是否参与碰撞检测
*/
public function get hitTest():Boolean
{
return _hitTest;
}
复制代码
为什么设置为protected?因为我们不需要从外部来更改它的碰撞属性,而只需要读取是否可以碰撞就可以了。
gameObject是继承自Sprite对象的。而Sprite提供了两种检测碰撞的方法,一是hitTestObject,另一个则是hitTestPoint。从API(http://help.adobe.com/zh_CN/AS3L ... /DisplayObject.html)中我们可以很清楚的看到,hitTestObject只是进行了外框的检测,也就是说,如果我们的图形不是正方形,而是其他不规则图形,哪怕图形上没有发生碰撞,只要图形的范围发生了交叠,FLASH就认为他们碰撞了。这显然不符合我们的要求(虽然我们的坦克基本上是个方块)。因此,我们还是和判断子弹的碰撞一样,选择hitTestPoint。但hitTestPoint需要一个指定的点。如何处理呢?
我们定义了8个检测目标,分别位于图形的四周(如下图所示),如果这8个目标点发生了碰撞,就认为物体撞在了一起。
由于只有ActionObject才需要检测碰撞,所以,我们根据上图给ActionObject增加检测点数组:
/**
* 碰撞检测点
*/
protected var _hitPoint:Array = [[0,0],[22,0],[45,0],[45,22],[45,45],[22,37],[0,45],[0,22]];
复制代码
进而修改nextCanMove方法:
/**
* 下一目标点是否可以移动
*/
public function get nextCanMove():Boolean
{
...
// 如果下一目标点超出屏幕范围,则不能移动
if (nx > Global.stage.stageWidth - width || nx < 0) return false;
if (ny > Global.stage.stageHeight - height || ny < 0) return false;
// 计算下一目标点的碰撞测试(本部分为新增代码)
for each(var obj:gameObject in Global.scene.AllObject)
{
if (obj == this || !obj.hitTest) continue;
for each(var p:Array in _hitPoint)
{
if (obj.hitTestPoint(nx + p[0], ny + p[1], true)) return false;
}
}
...
}
复制代码
我们循环了游戏场景中的所有游戏对象,如果发现游戏对象是自己或者对象并不参与碰撞检测,跳过检测,接下来,循环数组中的8个位置点,逐个判断是否发生了碰撞。如果发生,则返回false。
ActionObject是肯定参与检测的,因此,我们修改了一下ActionObject的构造函数:
public function ActionObject(ctrl:basicController)
{
super();
controller = ctrl;
controller.target = this; // 将控制器的控制目标设置为自己
_hitTest = true;// 打开碰撞检测开关
}
复制代码
在加入碰撞检测后,我们原来的子弹飞行也可以用碰撞检测开关来判断了,因此,我们修改了BulletObject的Do方法:
for each(var obj:gameObject in Global.scene.AllObject)
{
if (obj.hitTest && obj.part!=_shooter.part && obj!=this && obj.hitTestPoint(x, y, true))
{
// 击中目标
if(obj.hasOwnProperty('Hurt')) (obj as FaceObject).Hurt(20);
die();
break;
}
}
复制代码
我们改成了用碰撞开关来控制是否进行判断的前提条件,而把是否伤血由属性Hurt来判定。这样,子弹在击中障碍的时候,也会消失,但障碍物不会伤血(因为障碍物可能不具备Hurt方法)
到此,碰撞检测和基本的美化就已经做完了。不过,我的程序的运行界面是这样的:
实际运行swf
main.swf (20.05 KB)
可能你的和我的不太一样吧。呵呵。可以从下面的源码中找到不同。相信经过前面4篇的学习,可以很轻松的看懂现在的源码的:
Teach.rar (408.24 KB)
在下一篇教程中,我们将研究如何更简单的实现地图,同时做一些必要的限制(比如现在可以像冲锋枪一样不停的发射子弹,如果对于一款坦克游戏来讲,这显然不太符合逻辑)。
最后,在这里提醒各位在看本教程的朋友。教程只为引导大家快速写出可以运行的东西,而非进行项目实战。因此一些处理方法并不是最好的,而是比较容易理解和操作的。例如本篇教程中的碰撞检测。对于场景中对象不多的游戏可以胜任,如果游戏对象多起来,效率就会大大降低。选择合适的算法、处理方式,是一个漫长的路程,需要经验的积累和沉淀:)
转载请注名来源于天地会。
第五篇 告别方块,添加碰撞
在上一篇教程中。我们新增了基地的概念,并让敌人可以向基地开火。但是,敌人和自己还都是四四方方一大块,分不清哪是脸哪是屁股。另外在游戏界面里,各个对象依然可以重叠在一起。这显然不太合理。在本次的教程中,我们将一一修正这些问题。
首先,换个脸。在FLASH里对原有的组件进行编辑,我们随便画一个坦克的样子,大概像下面这样:
这样,就有了比较像样(至少不是方块)的素材了。不过,新的问题出现了。这个时候测试影片,我们可以发现,当坦克向上开的时候,是没问题的,但是向其他方向移动,素材并没有发生变化,而是横着走,或者倒退了。我们需要根据坦克的方向来调整素材的旋转角度。于是,我们重写了FaceObject的direction方法:
override public function set direction(dir:uint):void
{
super.direction = dir;
var angle:Number;
var tx:Number;
var ty:Number;
switch(dir)
{
case ActionObject.UP:
angle = 0;
tx = 0;
ty = 0;
break;
case ActionObject.RIGHT:
angle = Math.PI * 0.5;
tx = _face.width;
ty = 0;
break;
case ActionObject.DOWN:
angle = Math.PI;
tx = _face.width;
ty = _face.height;
break;
case ActionObject.LEFT:
angle = Math.PI * 1.5;
tx = 0;
ty = _face.height;
break;
}
_face.transform.matrix = new Matrix(Math.cos(angle), Math.sin(angle),Math.sin(angle)*-1,Math.cos(angle),tx,ty);
}
复制代码
从代码中我们可以看出,是通过设置的方向值的不同,获取了一个特定的角度(向上0度,向右90度,向下180度,向左270度。注意这里的angle是用弧度来表示角的。)最后,我们定义了一个矩阵,并通过_face的transform来进行了形状的变化。
有兄弟可能会问为什么需要tx,ty两个属性呢?你可以把最后一行里的tx和ty去掉测试一下。可以发现,当素材旋转的时候,产生了位移。这是由于我们使用的素材的注册点是在左上角(可以看到图片上左上角那个十字么)。而旋转是围绕注册点进行的,也就是说,坦克的旋转是按照以下方式进行的:
可以看到,在旋转的过程中,坦克由于环绕左上的注册点旋转,实际上在4个方位各产生了与本身的宽度和高度相关的位移,因此,我们需要把他们移动相应的位置,使他们看起来还在原来的位置上。因此使用了tx,ty。
矩阵(Matrix)是一个非常有用的类。在我们的教程中也是第一次用到。矩阵的构造函数:
new Matrix(a,b,c,d,tx,ty)
其中各参数的说明如下:
在Adobe官方提供的文档中有详细的说明。这里不再过多描述,你可以看这里查看详细的说明:http://help.adobe.com/zh_CN/AS3L ... sh/geom/Matrix.html
现在,坦克的方向可以很清楚的看到了,下面,我们来看一下如何放置游戏场景里的物品与其他的物品撞到一起。我们来进行碰撞检测。
首先,随着游戏的扩展,并不是所有的游戏物体都能碰到(比如草丛可以踩过去等等),因此,游戏对象需要增加一个开关,来控制他是否参与碰撞检测.我们修改gameObject类,增加这个属性:
/**
* 是否参与碰撞检测
*/
protected var _hitTest:Boolean = false;
/**
* 是否参与碰撞检测
*/
public function get hitTest():Boolean
{
return _hitTest;
}
复制代码
为什么设置为protected?因为我们不需要从外部来更改它的碰撞属性,而只需要读取是否可以碰撞就可以了。
gameObject是继承自Sprite对象的。而Sprite提供了两种检测碰撞的方法,一是hitTestObject,另一个则是hitTestPoint。从API(http://help.adobe.com/zh_CN/AS3L ... /DisplayObject.html)中我们可以很清楚的看到,hitTestObject只是进行了外框的检测,也就是说,如果我们的图形不是正方形,而是其他不规则图形,哪怕图形上没有发生碰撞,只要图形的范围发生了交叠,FLASH就认为他们碰撞了。这显然不符合我们的要求(虽然我们的坦克基本上是个方块)。因此,我们还是和判断子弹的碰撞一样,选择hitTestPoint。但hitTestPoint需要一个指定的点。如何处理呢?
我们定义了8个检测目标,分别位于图形的四周(如下图所示),如果这8个目标点发生了碰撞,就认为物体撞在了一起。
由于只有ActionObject才需要检测碰撞,所以,我们根据上图给ActionObject增加检测点数组:
/**
* 碰撞检测点
*/
protected var _hitPoint:Array = [[0,0],[22,0],[45,0],[45,22],[45,45],[22,37],[0,45],[0,22]];
复制代码
进而修改nextCanMove方法:
/**
* 下一目标点是否可以移动
*/
public function get nextCanMove():Boolean
{
...
// 如果下一目标点超出屏幕范围,则不能移动
if (nx > Global.stage.stageWidth - width || nx < 0) return false;
if (ny > Global.stage.stageHeight - height || ny < 0) return false;
// 计算下一目标点的碰撞测试(本部分为新增代码)
for each(var obj:gameObject in Global.scene.AllObject)
{
if (obj == this || !obj.hitTest) continue;
for each(var p:Array in _hitPoint)
{
if (obj.hitTestPoint(nx + p[0], ny + p[1], true)) return false;
}
}
...
}
复制代码
我们循环了游戏场景中的所有游戏对象,如果发现游戏对象是自己或者对象并不参与碰撞检测,跳过检测,接下来,循环数组中的8个位置点,逐个判断是否发生了碰撞。如果发生,则返回false。
ActionObject是肯定参与检测的,因此,我们修改了一下ActionObject的构造函数:
public function ActionObject(ctrl:basicController)
{
super();
controller = ctrl;
controller.target = this; // 将控制器的控制目标设置为自己
_hitTest = true;// 打开碰撞检测开关
}
复制代码
在加入碰撞检测后,我们原来的子弹飞行也可以用碰撞检测开关来判断了,因此,我们修改了BulletObject的Do方法:
for each(var obj:gameObject in Global.scene.AllObject)
{
if (obj.hitTest && obj.part!=_shooter.part && obj!=this && obj.hitTestPoint(x, y, true))
{
// 击中目标
if(obj.hasOwnProperty('Hurt')) (obj as FaceObject).Hurt(20);
die();
break;
}
}
复制代码
我们改成了用碰撞开关来控制是否进行判断的前提条件,而把是否伤血由属性Hurt来判定。这样,子弹在击中障碍的时候,也会消失,但障碍物不会伤血(因为障碍物可能不具备Hurt方法)
到此,碰撞检测和基本的美化就已经做完了。不过,我的程序的运行界面是这样的:
实际运行swf
main.swf (20.05 KB)
可能你的和我的不太一样吧。呵呵。可以从下面的源码中找到不同。相信经过前面4篇的学习,可以很轻松的看懂现在的源码的:
Teach.rar (408.24 KB)
在下一篇教程中,我们将研究如何更简单的实现地图,同时做一些必要的限制(比如现在可以像冲锋枪一样不停的发射子弹,如果对于一款坦克游戏来讲,这显然不太符合逻辑)。
最后,在这里提醒各位在看本教程的朋友。教程只为引导大家快速写出可以运行的东西,而非进行项目实战。因此一些处理方法并不是最好的,而是比较容易理解和操作的。例如本篇教程中的碰撞检测。对于场景中对象不多的游戏可以胜任,如果游戏对象多起来,效率就会大大降低。选择合适的算法、处理方式,是一个漫长的路程,需要经验的积累和沉淀:)
相关文章推荐
- 从零开始学AS3游戏开发【一】 响应键盘移动的方块
- 从零开始学AS3游戏开发【二】 随机移动的敌人
- 从零开始学AS3游戏开发【三】 向敌人开火!
- 状态添加Android游戏开发十日通(4)-行走,跳跃,碰撞检测
- 从零开始学AS3游戏开发【四】 敌人来袭!保护基地!
- 从零开始学AS3游戏开发【六】 设置地图
- 从零开始学AS3游戏开发【七】永无终结,不断完善的游戏
- AS3多人游戏开发—同步人物移动1
- 游戏开发之UE4添加角色到场景中
- [java游戏开发快速入门]俄罗斯方块游戏开发开篇
- 添加cocos2dX场景类模板。可以更快捷的开发游戏。。。
- 用Quick3.3简单开发微信打飞机 (三)----------------------------- 添加爆炸动画和子弹与敌机的碰撞
- html5游戏开发-愤怒的小鸟-开源讲座(三)-碰撞产生的冲力
- 碰撞检测碰撞Java简单游戏开发之碰撞检测
- 利用cocos2dx 3.2开发消灭星星(九)为游戏添加一些特效
- 【Android游戏开发之八】游戏中添加音频-详解MediaPlayer与SoundPoo!并讲解两者的区别和游戏中的用途!
- 关于游戏开发的一些思想碰撞
- 游戏开发基础--碰撞检测
- 从零开始丨使用Unity3D进行VIVE VR游戏开发
- 【Android游戏开发之六】在SurfaceView中添加组件!!!!并且相互交互数据!!!!