追逐算法之--牛鞭的子弹是怎样练成的(5)--牛鞭终养成
2013-04-10 01:41
495 查看
从3号开博到现在已经整整一个星期了,偶博客的访问量只有600多人,这得到什么时候才能达到100w啊。。。。我在这里郑重起誓,等我的博客访问量达到100w的时候,我就现场直播,剖腹,挖眼,割耳,掏心,想看杀人的朋友,走过路过千万不要错过,速度来顶吧!
看到没,这就是传说中的牛鞭子弹,我第一眼看到这张图就知道,要实现这个效果绝非易事,果然。在我仔细观察了3秒钟之后,我揭开了其中的秘密,现在请各位观众和我一起来到今天的《走进科学》,我将一一为大家揭开谜底。
别急,现在我们的敌机射出来的子弹不管任何时候都是垂直向下的,这样看起来非常的傻,敌机的子弹应该朝着我的飞机打来才对,因此我们首先来实现一下,敌机将子弹射向我们的效果。
原理很简单,我们先要在子弹类中加入targetV向量,代表子弹运动的目标方向,如图,我们将子弹的targetV设成(X2-X1,Y2-Y1)即可。
为此我们在TypeConst中加入一种新的子弹类型: //敌方跟踪子弹 int ENEMY_BULLET_TRACK_1 =4; 然后我们在Bullet中添加一个targetV属性
//目标向量
public PVector targetV = new PVector(0,0); 接着我们就可以实现这种子弹类型的逻辑函数和绘图函数了
然后我们将enemy的fire函数做如下修改
这样我们再运行一下就可以看见,敌人的子弹是向着我们飞来了。运行一下试试吧!
下面我们就要来实现牛鞭子弹了,它的原理是怎样的呢,其实很简单,它的那条长长的鞭子其实是由一个一个的小方块组成的,就如同我们这里的小长方形,通过粒子特效,与图片效果,将子弹的射速加快之后,看起来就是一条长长的鞭子了,那么它是如何弯曲的呢?其实就是让这些小长方形每一帧都做上面追踪子弹追踪过程,这样看起来就如果一根长长的鞭子了,我们让每一颗小子弹用初始速度向量,加上目标向量,以达到逐渐改变方向的目的。
如图,根据向量的加法,子弹的initV向量加上子弹的targetV向量应该等于子弹的实际运动方向moveV,我们再对moveV归一化,然后将归一化后的向量的各自分量乘以子弹的速度speed,就可以得到实际移动的距离了,如果每一帧都做这样的移动,那么就会实现类似跟踪导弹的效果了,这在追逐算法里的专业术语叫做视线追逐。接下来我们就来尝试实现以下
首先我们为我方飞机加入一种新的子弹类型TypeConst.MY_BULLET_VECTOR_TRACK ,然后我们照例实现它的逻辑与绘图函数
这时候我们产生了问题,如果屏幕上的敌机有很多架,那么我们的子弹追逐哪一架呢?这里我们寻找到离我们最近的敌机进行追逐,我们在Bullet类中加入一个寻找离自己最近敌机的函数
有了上面的函数,我们就可以很轻松的找到离我们最近敌机的位置向量了。
我们将这个函数加入到TypeConst.MY_BULLET_VECTOR_TRACK 的逻辑更新函数中
现在 ,我们在TypeConst中为我方飞机,加入一种新的射击方式
//发射多颗向量追踪子弹(牛鞭子弹)
int MY_SHOT_VECTOR_TRACK_1=3;
然后我们在MyPlanet类里的fire函数中,添加这个射击方式的功能如下,我们同时发出9颗子弹,并设置他们的初始方向向量为垂直向上,这里我们就不设置飞机的开火CD了,即为每帧发出下面这一批子弹。
好各位注意了,下面就是见证奇迹的时刻,如果你现在运行这个程序,发现子弹已经变成了牛鞭,我要的不多,每人十个回帖!
ok!!大功告成,只是还有些不爽的地方,就是子弹的打击感好像不咋的,我们给击中敌机的子弹按照Enemy的方式,做一个小的死亡爆炸效果,具体做法请参照前文,时间实在是太晚了,不能多写了!
我们尝试修改一下跟踪子弹的初始方向向量,试试效果会如何。在MyPlanet中增加一个新的射击类型
我们在这个基础上增加散射效果试试!
源码地址 :http://download.csdn.net/detail/azhangzhengtong/5240817
看到没,这就是传说中的牛鞭子弹,我第一眼看到这张图就知道,要实现这个效果绝非易事,果然。在我仔细观察了3秒钟之后,我揭开了其中的秘密,现在请各位观众和我一起来到今天的《走进科学》,我将一一为大家揭开谜底。
别急,现在我们的敌机射出来的子弹不管任何时候都是垂直向下的,这样看起来非常的傻,敌机的子弹应该朝着我的飞机打来才对,因此我们首先来实现一下,敌机将子弹射向我们的效果。
原理很简单,我们先要在子弹类中加入targetV向量,代表子弹运动的目标方向,如图,我们将子弹的targetV设成(X2-X1,Y2-Y1)即可。
为此我们在TypeConst中加入一种新的子弹类型: //敌方跟踪子弹 int ENEMY_BULLET_TRACK_1 =4; 然后我们在Bullet中添加一个targetV属性
//目标向量
public PVector targetV = new PVector(0,0); 接着我们就可以实现这种子弹类型的逻辑函数和绘图函数了
case TypeConst.ENEMY_BULLET_TRACK_1: this.setSpeed(3); initV=targetV; break;
case TypeConst.ENEMY_BULLET_TRACK_1: g.setColor(Color.YELLOW); g2d.rotate(this.rotateAngle,this.x, this.y); g.fillOval((int)this.x,(int)this.y, rdiusW, rdiusH); g2d.rotate(-this.rotateAngle,this.x, this.y); break;
然后我们将enemy的fire函数做如下修改
public void fire(){ //产生一颗子弹,位置就在敌人飞机的正前方 if(this.fireTimer.act()) { //这里的+20和+55用来调整子弹的初始位置,让它从飞机的正前方打出来 Bullet temp=new Bullet(this.x+20,this.y+55,true,TypeConst.ENEMY_BULLET_TRACK_1); temp.setTargetV(new PVector(GameHandler.myPlane.getX()-temp.x,GameHandler.myPlane.getY()-temp.y).normalize()); } }
这样我们再运行一下就可以看见,敌人的子弹是向着我们飞来了。运行一下试试吧!
下面我们就要来实现牛鞭子弹了,它的原理是怎样的呢,其实很简单,它的那条长长的鞭子其实是由一个一个的小方块组成的,就如同我们这里的小长方形,通过粒子特效,与图片效果,将子弹的射速加快之后,看起来就是一条长长的鞭子了,那么它是如何弯曲的呢?其实就是让这些小长方形每一帧都做上面追踪子弹追踪过程,这样看起来就如果一根长长的鞭子了,我们让每一颗小子弹用初始速度向量,加上目标向量,以达到逐渐改变方向的目的。
如图,根据向量的加法,子弹的initV向量加上子弹的targetV向量应该等于子弹的实际运动方向moveV,我们再对moveV归一化,然后将归一化后的向量的各自分量乘以子弹的速度speed,就可以得到实际移动的距离了,如果每一帧都做这样的移动,那么就会实现类似跟踪导弹的效果了,这在追逐算法里的专业术语叫做视线追逐。接下来我们就来尝试实现以下
首先我们为我方飞机加入一种新的子弹类型TypeConst.MY_BULLET_VECTOR_TRACK ,然后我们照例实现它的逻辑与绘图函数
case TypeConst.MY_BULLET_VECTOR_TRACK: this.setSpeed(25); //取得当前子弹指向敌机的向量 即目标向量 PVector tp = new PVector((targetV.x-this.x),(targetV.y-this.y)); //让初始向量的模向量,加上目标向量的模向量(此处我们同化初始向量和目标向量的比例差异) initV=initV.normalize().add(tp.normalize()); break;
case TypeConst.MY_BULLET_VECTOR_TRACK: g.setColor(Color.blue); g2d.rotate(this.rotateAngle,this.x, this.y); this.setRdius(3, 15); g2d.drawRect((int)this.x,(int)this.y, rdiusW, rdiusH); g2d.rotate(-this.rotateAngle,this.x, this.y); break;
这时候我们产生了问题,如果屏幕上的敌机有很多架,那么我们的子弹追逐哪一架呢?这里我们寻找到离我们最近的敌机进行追逐,我们在Bullet类中加入一个寻找离自己最近敌机的函数
//得到离自己最近的敌机的坐标,并返回为向量 public PVector getNestEnemy(){ int result =0; int index =-1; //循环遍历敌人类,寻找y轴坐标最大的飞机 for (int i=0;i<GameHandler.enemyList.size();i++){ int yPos =(int) GameHandler.enemyList.get(i).y; if (yPos>result){ result =yPos; index = i; } } //如果屏幕上没有飞机,就让子弹垂直往上射 if (index ==-1)return new PVector(this.x+20,-1); //如果有最近的敌机,返回最近敌机的中间偏下的坐标 Enemy nestEnemy = GameHandler.enemyList.get(index); return new PVector(nestEnemy.x+nestEnemy.ENEMY_WIDTH/2,nestEnemy.y+nestEnemy.ENEMY_HEIGHT); }
有了上面的函数,我们就可以很轻松的找到离我们最近敌机的位置向量了。
我们将这个函数加入到TypeConst.MY_BULLET_VECTOR_TRACK 的逻辑更新函数中
case TypeConst.MY_BULLET_VECTOR_TRACK: this.setSpeed(25); //得到离自己最近的敌机的向量位置 this.targetV=this.getNestEnemy(); //取得当前子弹指向敌机的向量 即目标向量 PVector tp = new PVector((targetV.x-this.x),(targetV.y-this.y)); //让初始向量加上目标向量 initV=initV.add(tp).normalize(); break;
现在 ,我们在TypeConst中为我方飞机,加入一种新的射击方式
//发射多颗向量追踪子弹(牛鞭子弹)
int MY_SHOT_VECTOR_TRACK_1=3;
然后我们在MyPlanet类里的fire函数中,添加这个射击方式的功能如下,我们同时发出9颗子弹,并设置他们的初始方向向量为垂直向上,这里我们就不设置飞机的开火CD了,即为每帧发出下面这一批子弹。
//产生牛鞭子弹 case TypeConst.MY_SHOT_VECTOR_TRACK_1: new Bullet(this.x+5,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+10,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+15,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+20,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+25,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+30,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+35,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+40,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+45,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); break;
好各位注意了,下面就是见证奇迹的时刻,如果你现在运行这个程序,发现子弹已经变成了牛鞭,我要的不多,每人十个回帖!
ok!!大功告成,只是还有些不爽的地方,就是子弹的打击感好像不咋的,我们给击中敌机的子弹按照Enemy的方式,做一个小的死亡爆炸效果,具体做法请参照前文,时间实在是太晚了,不能多写了!
public void draw(Graphics g){ //将Graphics 转成Graphics2D,这样就有旋转的功能了 g2d = (Graphics2D)g; if(this.isExplode){ g.setColor(Color.pink); //画一个圆圈表示爆炸效果 g.drawOval((int)x-10,(int)y-10, explodeRadius, explodeRadius); //每一帧让圆的半径增大15 this.explodeRadius+=10; if(this.explodeRadius>this.explodeMaxRadius)this.isExplodeDead=true; return; }else{ this.drawBulletType(g); } } public void update(){ this.checkDead(); this.checkEnemyCollision(); this.updateBulletType(); //将x,y坐标,分别加上初始方向模向量的x,y分量*速度值 this.x = this.x+initV.x*speed; this.y = this.y+initV.y*speed; //区分左偏垂直线,还是右偏 if (initV.x<0) this.rotateAngle=-new PVector(0,-1).checkVectorAngle(initV); else this.rotateAngle=new PVector(0,-1).checkVectorAngle(initV); }
我们尝试修改一下跟踪子弹的初始方向向量,试试效果会如何。在MyPlanet中增加一个新的射击类型
//产生牛鞭子弹2号 case TypeConst.MY_SHOT_VECTOR_TRACK_2: new Bullet(this.x+10,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(-5,1)); new Bullet(this.x+20,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+30,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(5,1)); break;
我们在这个基础上增加散射效果试试!
//散射加牛鞭1号 case TypeConst.MY_SHOT_VECTOR_PLUS_MULITI_TRACK_1: new Bullet(this.x+10,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(-5,1)); new Bullet(this.x+20,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(0,-1)); new Bullet(this.x+30,this.y-5,false,TypeConst.MY_BULLET_VECTOR_TRACK).setInitV(new PVector(5,1)); if(this.fireCDTimer.act()) this.makeMulitiBullet(6, 10); break;
源码地址 :http://download.csdn.net/detail/azhangzhengtong/5240817
相关文章推荐
- 追逐算法之--牛鞭的子弹是怎样练成的(2)--简单追逐
- 追逐算法之--牛鞭的子弹是怎样练成的(3)--简单碰撞检测
- 追逐算法之--牛鞭的子弹是怎样练成的(6)--贝塞尔强化
- 追逐算法之--牛鞭的子弹是怎样练成的(1)--游戏主框架
- 追逐算法之--牛鞭的子弹是怎样练成的(4)--散射子弹
- 怎样学习算法
- 算法问题征解:怎样生成随机数而不借助任何工具?
- html修炼养成--怎样使用Swiper
- Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?
- 给出一个单链表,不知道节点N的值,怎样只遍历一次就可以求出中间节点,写出算法!
- 子弹跟踪算法
- 怎样学算法
- 水仙花数的算法(怎样怎样将数字拆分为个位,十位,百位)
- 怎样的中奖算法能让人信服(转)
- 比特币地址的生成算法是怎样的?
- 怎样学习算法
- 怎样编写一个程序,把一个有序整数数组放到二叉树中? 编写实现链表排序的一种算法。说明为什么你会选择用这样的方法?
- 怎样的 Hash 算法能对抗硬件破解
- 微软等数据结构+算法面试100题(3)--怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
- 【算法】5 传说中的快排是怎样的