文章目录

  • 一、技能碰撞检测方式分类讲解
    • 1)AABB
    • 2)OBB
    • 3)像素检测碰撞
    • 4)矩阵变换检测碰撞(打住,略)
    • 5)Tile地形检测碰撞(其实就是九方格遍历查找攻击对象)
  • 二、武林风云录
    • 1)老一:陈斩槐(只有四个机制,dps压力不大,留爆发打影子就行)
      • (1)点名红色扇形区域
      • (2)点名红色长条,注意最后还有一段大劈
      • (3)BOSS在百分之80 、50、20血量时会击退玩家,会刷新三个输出位置
      • (4)BOSS在百分之35血时会吸玩家到其周围,释放旋风斩,得交解控技能。但是不要着急回去,还有一个圆圈的下坠伤害
    • 2)老二:醉仙
      • (1)红圈和点名略过
      • (2)输出记得喝酒(龙吟内功,铁衣外功等)
      • (3)每一个奉茶小厮都有名字,得按照诗词来按照顺序击杀小二
    • 3)老三:楚相玉
      • (1)boss有狂暴机制,冰火玄功达到极致,倒数360s,将直接团灭(人均得有1.2Wdps)
      • (2)地上出现红圈,0.5s后将冒出冰柱,击飞造成一段伤害,落地造成二段伤害(估计代码是设计成击飞后掉落下来还在圆圈内)
      • (3)点名T红色长条,多段伤害
      • (4)烈焰焚身,需要交减伤或无敌规避伤害
      • (5)冰风火凤融合产生圆形爆炸区域
      • (6)赤炎寒光破
      • (7)暴风雪
    • 4)老四:刀狂
      • (1)略过半圆斩、三段长条大劈、落地红圈、黑水机制不在赘述
      • (2)达到百分之90血时,地上出现追忆碎片,分内外场地(血河上马溜boss,需要奶妈往返内网场用追忆碎片奶安抚boss并奶白剑)
      • (3)刀狂有怒气机制,到百分之100时增加移速和攻击力
      • (4)内场讲解
  • 三、舞阳城

一、技能碰撞检测方式分类讲解

1)AABB

  • 定义
    采用一个长方体将物体包裹起来,进行两个物体的相交性检测时仅检测物体对应包围盒(包裹物体的长方体)的相交性。长方体每一个面都是与某个坐标轴平面平行的,因此,AABB 包围盒又称了 轴对齐包围盒 。

  • 备注
    确定 AABB 包围盒就简单多了,仅需要记录 6 个值即可,这 6 个值分别代表包围盒在每个坐标轴上的最小值与最大值,即 xmin、xmax、ymin、ymax、zmin、zmax。也就是说,实际物体上所有的点都必须满足以下条件:

  • 代码计算
    1)C++版本检测AABB碰撞

法一:(1)包围盒
struct stBoundingBox
{stBoundingBox () { min[0] = min[1] = min[2] =max[0] = max[1] = max[2] = 0; }float min[3];float max[3];
};
//检测点是否在包围盒内
// Point inside box.
bool OnCollision(stBoundingBox bb, float x, float y, float z)
{if(bb.max[0] <= x) return false;if(bb.min[0] >= x) return false;if(bb.max[1] <= y) return false;if(bb.min[1] >= y) return false;if(bb.max[2] <= z) return false;if(bb.min[2] >= z) return false;// Return true then we have collision.return true;
}
//检测包围盒相撞
// Box on box.
bool OnCollision(stBoundingBox &bb1, stBoundingBox &bb2)
{if((bb1.min[0] > bb2.max[0]) || (bb2.min[0] > bb1.max[0]))return false;if((bb1.min[1] > bb2.max[1]) || (bb2.min[1] > bb1.max[1]))return false;if((bb1.min[2] > bb2.max[2]) || (bb2.min[2] > bb1.max[2]))return false;return true;
}
法二:立方体检测
(一)优点:对结构而言,对边界框使用4个浮点数需要的空间较少,而这是较合理的空间坐标。
(二)缺点:盒子变成了立方体。这样在尝试封装物体时会浪费更多的空间,因为需要为深度、宽度和高度使用最
大的尺寸值,而不是使用每个方向上所必须的扩展值
(这里给出了一个使用4个浮点数以及一个最大、最小数值对来定义和创建边框的方法)
struct stBoundingBox
{CVector3 min, max;
};struct stBoundingBox
{CVector3 center;float size;
};
法三:边界求检测
(一)定义:边界球完全围绕在一些几何图形周围,它除了不用方
框之外,和边界框结构非常相似。边界球结构可以使用4个浮点值
确定。前3个浮点值代表了边界球的中心位置,第四个浮点数代表
了边界球的半径
(二)优点:边界框相比较而言,边界球在处理碰撞检测和可见度时速度更快
(三)缺点:环绕造成的空间浪费要比边界框多
struct stBoundingSphere
{CVector3 center;double radius;
};stBoundingSphere CalculateBoundingSphere(CVector3 *vList, int totalVerts)
{float d, maxDistance = 0.0f;stBoundingSphere sphere;for(int i = 0; i < totalVerts; i++){if(vList[i].x < min[0]) min[0] = vList[i].x;if(vList[i].x > max[0]) max[0] = vList[i].x;if(vList[i].y < min[1]) min[1] = vList[i].y;if(vList[i].y > max[1]) max[1] = vList[i].y;if(vList[i].z < min[2]) min[2] = vList[i].z;if(vList[i].z > max[2]) max[2] = vList[i].z;}CVector3 center = (max + min) * 0.5f;for(i = 0; i < totalVerts; i++){d = ((vList[i].x - center.x) * (vList[i].x - center.x)) +((vList[i].y - center.y) * (vList[i].y - center.y)) +((vList[i].z - center.z) * (vList[i].z - center.z));if(d > maxDistance)maxDistance = d;}sphere.radius = sqrt(maxDistance);sphere.center = center;return sphere;
}
  • 球体检测综合评价
    如前所述,边界球要比边界框更容易处理(碰撞、能见度等),因为对球所做的操作都是比较便宜的CPU相关的。这样在想要快速确定一个物体是否和其他物体发生碰撞或是那个物体是否可见的情况下,就最有可能选择使用边界球。某些混合法包括先使用边界球快速拒绝几何图形,然后使用边界框进行更准确的测试。如果这两个测试都通过了,那么接下来的操作要么是接受物体测试成功,要么是将物体分解成更小的块,然后分别对围绕这些块的边界框进行测试。当然,使用的方法很大程度上取决于程序的要求。取代使用大的球,然后是大的边界框,可以先使用大的边界球,然后再直接使用小一些的边界框。无论如何,最初使用边界球进行测试经过证明十分有用,因为进行碰撞和可见度测试使用的大量时间对包含大量物体的场景而言都是不够的

2)java版本

(1)3D结构体定义
public class Vector3f {float x;//三维变量中的x值float y;//三维变量中的y值float z;//三维变量中的z值public Vector3f(float x,float y,float z){this.x=x;this.y=y;this.z=z;}public void add(Vector3f temp){this.x+=temp.x;this.y+=temp.y;this.z+=temp.z;}
}
(2)包围盒定义
public class AABBBox {float minX;//x轴最小位置float maxX;//x轴最大位置float minY;//y轴最小位置float maxY;//y轴最大位置float minZ;//z轴最小位置float maxZ;//z轴最大位置public AABBBox(float[] vertices){init();findMinAndMax(vertices);}public AABBBox(float minX,float maxX,float minY,float maxY,float minZ,float maxZ){this.minX=minX;this.maxX=maxX;this.minY=minY;this.maxY=maxY;this.minZ=minZ;this.maxZ=maxZ;}//初始化包围盒的最小以及最大顶点坐标public void init(){minX=Float.POSITIVE_INFINITY; // 正无穷maxX=Float.NEGATIVE_INFINITY; // 负无穷minY=Float.POSITIVE_INFINITY;maxY=Float.NEGATIVE_INFINITY;minZ=Float.POSITIVE_INFINITY;maxZ=Float.NEGATIVE_INFINITY;}//获取包围盒的实际最小以及最大顶点坐标public void findMinAndMax(float[] vertices){for(int i=0;i<vertices.length/3;i++){//判断X轴的最小和最大位置if(vertices[i*3]<minX){minX=vertices[i*3];}if(vertices[i*3]>maxX){maxX=vertices[i*3];}//判断Y轴的最小和最大位置if(vertices[i*3+1]<minY){minY=vertices[i*3+1];}if(vertices[i*3+1]>maxY){maxY=vertices[i*3+1];}//判断Z轴的最小和最大位置if(vertices[i*3+2]<minZ){minZ=vertices[i*3+2];}if(vertices[i*3+2]>maxZ){maxZ=vertices[i*3+2];}}}//获得物体平移后的AABB包围盒public AABBBox getCurrAABBBox(Vector3f currPosition){AABBBox result=new AABBBox(this.minX+currPosition.x,this.maxX+currPosition.x,this.minY+currPosition.y,this.maxY+currPosition.y,this.minZ+currPosition.z,this.maxZ+currPosition.z);return result;}
}(3)碰撞检测函数public boolean check(RigidBody ra, RigidBody rb)//true为撞上{float[] over = calOverTotal(// 两个物体的 AABB 包围盒ra.collObject.getCurrAABBBox(ra.currLocation),rb.collObject.getCurrAABBBox(rb.currLocation));// 三个方向的交叠值与设定的阈值进行比较return over[0] > V_UNIT && over[1] > V_UNIT && over[2] > V_UNIT;}// 传入两个物体的 AABB 包围盒public float[] calOverTotal(AABBBox a, AABBBox b) {float xOver = calOverOne(a.maxX, a.minX, b.maxX, b.minX);float yOver = calOverOne(a.maxY, a.minY, b.maxY, b.minY);float zOver = calOverOne(a.maxZ, a.minZ, b.maxZ, b.minZ);return new float[]{xOver, yOver, zOver};}// 计算每个轴方向的交叠值public float calOverOne(float amax, float amin, float bmax, float bmin) {float minMax = 0;float maxMin = 0;if (amax < bmax)//a物体在b物体左侧{minMax = amax;maxMin = bmin;} else //a物体在b物体右侧{minMax = bmax;maxMin = amin;}if (minMax > maxMin) {return minMax - maxMin;} else {return 0;}}

2)OBB

  • 定义
    两个凸包多边形,当且仅当存在一条线,这两个多边形在这条线上的投影不相交,则这两个多边形也不相交.
  • 举例
    这里不能取2因为投影会相交,可以取1为投影轴

  • 链接传送门

3)像素检测碰撞

  • 使用背景
    1)使用像素碰撞检测法算是最精确的算法
    2)效率上的低下。除非是在极为特殊的情况下,要求使用非常精确的碰撞,否则,一般情况下在游戏中是不建议使用这种算法,特别是在运行效率不太高的HTML5游戏中。

  • 使用顺序
    一般来说在使用像素碰撞检测之前会使用AABB矩形包围盒先检测两个精灵是否有碰撞,如果AABB包围盒检测没有碰撞,那一定是没有碰撞到,反之,则不一定,需要进一步进行像素检测。如下图所示,很明显,虽然两个精灵的包围盒发生了碰撞,但两个精灵本身没有发生碰撞,所以在这种精灵的形状极为不规则的情况下,除非使用多边形包围盒,并且需要多边形和精灵的形状极为接近,才能够获取好的效果,而且,别忘了,多边形只适合凸多边形的情况。

  • 定义
    这样,我们就只能采用像素检测算法达到精确检测的目的。接下来,先来看看像素碰撞的原理,首先,我们知道所有的精灵都是由像素点组成,而在canvas的像素数据中每个点都是由RGBA四个数据组成。如果某个点的A(alpha值,透明度)为0则表示该点是透明的,比如在图6-19中两个精灵的空白部分的点的A值为0。如果两个精灵发生碰撞,则表示两个精灵有像素点发生了重叠,即两个精灵的像素点坐标相同,如下图所示。

    根据这个原理,基本上我们可以采取以下步骤来进行检测。

(1)选择需要检测的两个精灵。
(2)先检测两个精灵是否发生包围盒碰撞,如果没有则退出,否则获取两个矩形的相交区域,并继续。
(3)把一个精灵绘制到和游戏屏幕等大的空白的后台缓冲区中,获取缓冲区中在相交区域的像素数据。
(4)清除后台缓冲区。
(5)对另一个精灵进行步骤3的操作。
(6)得到两个精灵在同一个相交矩形的像素数据后,循环比较每一个像素点,如果两个精灵在同一位置的透明度不都是0,则表示两个精灵有相交,退出循环,返回真。
  • 备注点
    需要注意的一点是,在第3步获取相交区域的像素数据中,需要在后台另外的一个和游戏屏幕等大的空白区域中绘制,而不能直接获取游戏画面中的相交区域,因为两个精灵在相交区域中的像素已经发生了重叠【包围盒】。
  • 注意点
    由以上的算法可以看出,在进行像素检测的时候,需要另外一个缓冲区,把需要检测的精灵绘制一次,需要清空缓冲区,最后还要使用一个for循环检测像素。如果相交区域为100×100个像素点,则最坏的情况需要循环10 000 次,由此看来,这真不是一个省时的工作。
  • 代码
<!DOCTYPE html>
<html lang="en">
<head><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"><meta charset="UTF-8"><title>盒包围碰撞算法-像素检测算法</title><style>#stage {border: 1px solid lightgray;}</style>
</head>
<body>
<h1>包围盒是否碰撞:<span class="hitTestBox">否</span></h1>
<h1>像素检测是否碰撞:<span class="hitTestPixel">否</span></h1>
<canvas id="stage"></canvas>
<img src="./images/penguin.png" alt="penguinImg" id="penguinImg" style="display:none" />
<img src="./images/giraffe.png" alt="giraffeImg" id="giraffeImg" style="display:none" />
</body>
<script>window.onload = function () {var stage = document.querySelector('#stage'),ctx = stage.getContext('2d');stage.width = 600;stage.height = 600;//创建后台canvasvar bC = document.createElement("canvas");bC.width = stage.width;bC.height = stage.height;var backBuf = bC.getContext("2d");var penguin = document.querySelector('#penguinImg'),giraffe = document.querySelector('#giraffeImg');var penguinImg = {x:stage.width/2,y:stage.height/2,r:128,data:null},giraffeImg = {x:100,y:100,r:128,data:null};function drawImageBox(img,x,y,width,height){ctx.beginPath();ctx.rect(x,y,width,height);ctx.stroke();ctx.drawImage(img,x,y,width,height);}//缓存画布绘制方法function drawImageBC(img,x,y,width,height){backBuf.clearRect(0,0,stage.width,stage.height);backBuf.save();backBuf.drawImage(img,x,y,width,height);backBuf.restore();}//获取两个矩形相交区域function getInRect(x1,y1,x2,y2,x3,y3,x4,y4) {return [Math.max(x1,x3),Math.max(y1,y3),Math.min(x2,x4),Math.min(y2,y4)];}document.onkeydown = function (event) {var e = event || window.event || arguments.callee.caller.arguments[0];//根据地图数组碰撞将测switch (e.keyCode) {case 37:console.log("Left");if (penguinImg.x > 0) {penguinImg.x -= 2;}break;case 38:console.log("Top");if (penguinImg.y > 0) {penguinImg.y -= 2;}break;case 39:console.log("Right");if (penguinImg.x < stage.width) {penguinImg.x += 2;}break;case 40:console.log("Bottom");if (penguinImg.y < stage.height) {penguinImg.y += 2;}break;default:return false;}};stage.addEventListener('click', function (event) {var x = event.clientX - stage.getBoundingClientRect().left;var y = event.clientY - stage.getBoundingClientRect().top;penguinImg.x = x;penguinImg.y = y;});function update() {ctx.clearRect(0, 0, 600, 600);drawImageBox(giraffe,giraffeImg.x,giraffeImg.y,giraffeImg.r,giraffeImg.r);drawImageBox(penguin,penguinImg.x,penguinImg.y,penguinImg.r,penguinImg.r);document.querySelector('.hitTestBox').innerHTML = "否";document.querySelector('.hitTestPixel').innerHTML = "否";var rect = getInRect(giraffeImg.x,giraffeImg.y,giraffeImg.x+giraffeImg.r,giraffeImg.y+giraffeImg.r,penguinImg.x,penguinImg.y,penguinImg.x+penguinImg.r,penguinImg.y+penguinImg.r)//如果没有相交则退出if(rect[0]>=rect[2]||rect[1]>=rect[3]) {} else{document.querySelector('.hitTestBox').innerHTML = "是";giraffeImg.data = null;penguinImg.data = null;//获取精灵在相交矩形像素数据drawImageBC(giraffe,giraffeImg.x,giraffeImg.y,giraffeImg.r,giraffeImg.r);giraffeImg.data = backBuf.getImageData(rect[0],rect[1],rect[2],rect[3]).data;drawImageBC(penguin,penguinImg.x,penguinImg.y,penguinImg.r,penguinImg.r);penguinImg.data = backBuf.getImageData(rect[0],rect[1],rect[2],rect[3]).data;for(var i=3;i<giraffeImg.data.length;i+=4){if(giraffeImg.data[i]>0&&penguinImg.data[i]>0){document.querySelector('.hitTestPixel').innerHTML = "是";}}}requestAnimationFrame(update);}update();};
</script>
</html>
  • 在线预览地址

4)矩阵变换检测碰撞(打住,略)

5)Tile地形检测碰撞(其实就是九方格遍历查找攻击对象)

(1)头文件中#include <iostream>#include "cocos2d.h"using namespace cocos2d;class AA:public CCLayer{public:virtual bool init();static CCScene *scene();CREATE_FUNC(AA);CCSprite *_player;int count;bool mode;CCArray *bulletArray;CCArray *enemyArray;CCTMXTiledMap *_tileMap;CCTMXTiledMap *_titleMap;CCTMXLayer *wall,*foreground;CCPoint mapPoint,heroPoint,beginPoint;CCLabelTTF *label;//碰撞检测void detection();bool iscallision(CCSprite *mysprite,CCSprite *testsprite);CCRect getRect(CCSprite *sprite);//触摸事件virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);void goon(CCNode *pSender);void toggleGame(CCObject *pSender);void targetFinish(CCNode *pSender);};(2)实现文件中
////  AA.cpp//  date10////  Created by Student on 14-9-22.////#include "AA.h"CCScene *AA::scene(){CCScene *s=CCScene::create();AA *layer=AA::create();s->addChild(layer);return s;}bool AA::init(){if(!CCLayer::init()){return false;}mode=true;//初始化数组bulletArray = CCArray::create();bulletArray->retain();enemyArray = CCArray::create();enemyArray->retain();//加载瓦片地图_tileMap=CCTMXTiledMap::create("ThefirstTiled1.tmx");_tileMap->setPosition(mapPoint);addChild(_tileMap);//读取瓦片地图中的层和对象wall=_tileMap->layerNamed("wall");foreground=_tileMap->layerNamed("water");CCTMXObjectGroup *objects=_tileMap->objectGroupNamed("hero");CCDictionary  *spawnPoint=objects->objectNamed("pa");heroPoint.x=spawnPoint->valueForKey("x")->floatValue();heroPoint.y=spawnPoint->valueForKey("y")->floatValue();CCLog("x=%f,y=%f",heroPoint.x,heroPoint.y);//加载英雄到界面_player=CCSprite::create("www.png");_player->setAnchorPoint(CCPoint(0,0));_player->setPosition(heroPoint);_tileMap->addChild(_player,0);//加载敌人到界面for(int i=0;i<int(objects->getObjects()->count());i++) //得到敌人的数量{CCDictionary *enemy=(CCDictionary *)objects->getObjects()->objectAtIndex(i);if(enemy->valueForKey("n")->intValue()==1){CCSprite *s=CCSprite::create("enemy1.png");float x=enemy->valueForKey("x")->floatValue();float y=enemy->valueForKey("y")->floatValue();s->setPosition(ccp(x,y));s->setAnchorPoint(CCPoint(0,0));_tileMap->addChild(s,4);enemyArray->addObject(s);CCActionInterval *move=CCMoveBy::create(0.5,CCPoint(_player->getPosition().x-s->getPosition().x>0?10:-10,_player->getPosition().y-s->getPosition().y>0?10:-10));//goon 表示不断的移动CCFiniteTimeAction *func=CCCallFuncN::create(this,callfuncN_selector(AA::goon));s->runAction(CCSequence::create(move,func,NULL));}}//加载开关选项CCMenuItem *oon,*ooff;oon=CCMenuItemImage::create("projectile-button-on.png","projectile-button-on.png");ooff=CCMenuItemImage::create("projectile-button-off.png","projectile-button-off.png");CCMenuItemToggle *toggle=CCMenuItemToggle::createWithTarget(this,menu_selector(AA::toggleGame),ooff,oon,NULL);CCMenu *menu=CCMenu::create(toggle,NULL);menu->setPosition(ccp(oon->getContentSize().width/2,oon->getContentSize().height/2));addChild(menu);//加入触摸的单例CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);//碰撞检测的调用this->schedule(schedule_selector(AA::detection), 0.2);label=CCLabelTTF::create("0","Arial",20);label->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width-label->getContentSize().width/2,label->getContentSize().height/2));addChild(label,10);return true;}//表示敌人不断移动的距离void AA::goon(CCNode *pSender){CCLOG("goon");CCSprite *s=(CCSprite *)pSender;CCActionInterval *move=CCMoveBy::create(0.5,CCPoint(_player->getPosition().x-s->getPosition().x>0?10:-10,_player->getPosition().y-s->getPosition().y>0?10:-10));CCFiniteTimeAction *func=CCCallFuncN::create(this,callfuncN_selector(AA::goon));s->runAction(CCSequence::create(move,func,NULL));}void AA::toggleGame(CCObject *pSender){mode=mode?false:true;}bool AA::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){beginPoint=pTouch->getLocation();return true;}void AA::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent){/*if(mode){//得到先前的坐标(0,0)CCPoint PP=pTouch->getPreviousLocation();//得到当前的坐标CCPoint np=pTouch->getLocation();//两坐标相减CCPoint dp=ccpSub(np, PP);//向左为负 右侧为正if(_titleMap->getPosition().x+dp.x>-480 &&  _titleMap->getPosition().x+dp.x<0){mapPoint=ccp(_titleMap->getPosition().x+dp.x,0);_titleMap->setPosition(mapPoint);}}*/if(mode){CCPoint pp=pTouch->getPreviousLocation();CCPoint np=pTouch->getLocation();CCPoint dp=ccpSub(np,pp);if(_tileMap->getPosition().x+dp.x>-480&&_tileMap->getPosition().x+dp.x<0){mapPoint=ccp(_tileMap->getPosition().x+dp.x,0);_tileMap->setPosition(mapPoint);}}}void AA::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent){/*//地图里的坐标(0,0)是从左上角开始的步骤:1、判断是否点击2、判断点击的位置与英雄的位置的X,Y的差值     比较DX与DY的大小3、判断英雄的X做标要大于点击的X坐标  才能向左4、判断移动时是否撞击墙和移出地图外*///获得点击的位置/*CCPoint pp=pTouch->getLocation();if(mode){//是点击不是滑动  在原地点击下又点击离开if(beginPoint.x==pp.x && beginPoint.y==pp.y)//beginPoint是开始触摸的位置{//—player的位置CCPoint pt=_player->getPosition();//判断是否 x>yif(fabs(pt.x-(pp.x-mapPoint.x))>=fabs( pt.y-(pp.y-mapPoint.y))    ){点击点向左移动   英雄的X做标要大于点击的X坐标  才能向左if(pt.x>=pp.x-mapPoint.x){if(9-_player->getPosition().y/32<10 && 9-_player->getPosition().y/32>=0&&_player->getPosition().x/32-1<50&&_player->getPosition().x/32-1>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32-1,9-_player->getPosition().y/32))))//判断是否是地图外面,或者是不是墙{_player->setPosition(ccp(_player->getPosition().x-32,_player->getPosition().y));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}else{if(9-_player->getPosition().y/32<10&&9-_player->getPosition().y/32>=0&&_player->getPosition().x/32+1<50&&_player->getPosition().x/32+1>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32+1,9-_player->getPosition().y/32)))){_player->setPosition(ccp(_player->getPosition().x+32,_player->getPosition().y));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}}else{if(pt.y>=pp.y-mapPoint.y){if(9-_player->getPosition().y/32+1<10&&9-_player->getPosition().y/32+1>=0&&_player->getPosition().x/32<50&&_player->getPosition().x/32>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32+1)))){_player->setPosition(ccp(_player->getPosition().x,_player->getPosition().y-32));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}else{if(9-_player->getPosition().y/32-1<10&&9-_player->getPosition().y/32-1>=0&&_player->getPosition().x/32<50&&_player->getPosition().x/32>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32-1)))){_player->setPosition(ccp(_player->getPosition().x,_player->getPosition().y+32));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}}}}else{CCSprite *s=CCSprite::create("Projectile.png");s->setPosition(_player->getPosition());_tileMap->addChild(s,4);bulletArray->addObject(s);float dx=pp.x-_player->getPosition().x;float dy=pp.y-_player->getPosition().y;if(dx>0){float lx=32*30-_player->getPosition().x;float ly=dy/dx*lx;CCActionInterval *move=CCMoveBy::create(3,ccp(lx+s->getContentSize().width,ly));CCFiniteTimeAction *ff=CCCallFuncN::create(this,callfuncN_selector(AA::targetFinish));s->runAction(CCSequence::create(move,ff,NULL));}else{float lx=0-_player->getPosition().x;float ly=dy/dx*lx;CCActionInterval *move=CCMoveBy::create(3,ccp(lx-s->getContentSize().width,ly));CCFiniteTimeAction *ff=CCCallFuncN::create(this,callfuncN_selector(AA::targetFinish));s->runAction(CCSequence::create(move,ff,NULL));}}*/CCPoint pp=pTouch->getLocation();if(mode)//移动{if(beginPoint.x==pp.x&&beginPoint.y==pp.y){cocos2d::CCPoint pt=_player->getPosition();//dx>dyif(fabs(pt.x-(pp.x-mapPoint.x))>=fabs(pt.y-(pp.y-mapPoint.y))){//左移if(pt.x>=pp.x-mapPoint.x){if(9-_player->getPosition().y/32<10&&9-_player->getPosition().y/32>=0&&_player->getPosition().x/32-1<50&&_player->getPosition().x/32-1>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32-1,9-_player->getPosition().y/32))))//判断是否是地图外面,或者是不是墙  //tileGIDAt表示有没有的意思{//32表示32个像素  表示向左挪动了1个单位_player->setPosition(ccp(_player->getPosition().x-32,_player->getPosition().y));//判断西瓜的和_player相撞if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){//西瓜的位置消失foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}//右移else{if(9-_player->getPosition().y/32<10&&9-_player->getPosition().y/32>=0&&_player->getPosition().x/32+1<50&&_player->getPosition().x/32+1>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32+1,9-_player->getPosition().y/32)))){_player->setPosition(ccp(_player->getPosition().x+32,_player->getPosition().y));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}}//dx<dyelse{//下移if(pt.y>=pp.y-mapPoint.y){if(9-_player->getPosition().y/32+1<10&&9-_player->getPosition().y/32+1>=0&&_player->getPosition().x/32<50&&_player->getPosition().x/32>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32+1)))){_player->setPosition(ccp(_player->getPosition().x,_player->getPosition().y-32));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}//上移else{if(9-_player->getPosition().y/32-1<10&&9-_player->getPosition().y/32-1>=0&&_player->getPosition().x/32<50&&_player->getPosition().x/32>=0&&!(wall->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32-1)))){_player->setPosition(ccp(_player->getPosition().x,_player->getPosition().y+32));if(foreground->tileGIDAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32))){foreground->removeTileAt(ccp(_player->getPosition().x/32,9-_player->getPosition().y/32));count++;CCString *temp=CCString::createWithFormat("%d",count);label->setString(temp->getCString());}}}}}}//英雄发射子弹else{CCSprite *s=CCSprite::create("Projectile.png");s->setPosition(_player->getPosition());_tileMap->addChild(s,4);bulletArray->addObject(s);float dx=pp.x-_player->getPosition().x;float dy=pp.y-_player->getPosition().y;if(dx>0){float lx=32*30-_player->getPosition().x;float ly=dy/dx*lx;CCActionInterval *move=CCMoveBy::create(3,ccp(lx+s->getContentSize().width,ly));CCFiniteTimeAction *ff=CCCallFuncN::create(this,callfuncN_selector(AA::targetFinish));s->runAction(CCSequence::create(move,ff,NULL));}else{float lx=0-_player->getPosition().x;float ly=dy/dx*lx;CCActionInterval *move=CCMoveBy::create(3,ccp(lx-s->getContentSize().width,ly));CCFiniteTimeAction *ff=CCCallFuncN::create(this,callfuncN_selector(AA::targetFinish));s->runAction(CCSequence::create(move,ff,NULL));}}}void AA::targetFinish(CCNode *pSender){pSender->removeFromParent();}void AA::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent){}//碰撞检测void AA::detection(){/*1、英雄与敌人碰撞2、子弹与敌人碰撞*///遍历敌人for(int i=0;i<enemyArray->count();i++){CCSprite *s=(CCSprite *)enemyArray->objectAtIndex(i);//判断英雄是否和敌人碰撞if(iscallision(_player, s)){CCLog("--------aaaaaaaa-------------");}}//创建临时的数组CCArray *bulletA=CCArray::create();CCArray *enemyA=CCArray::create();//遍历子弹for(int i=0;i<bulletArray->count();i++){CCSprite *bullet=(CCSprite *)bulletArray->objectAtIndex(i);//遍历敌人for(int j=0;j<enemyArray->count();j++){CCSprite *enemy=(CCSprite *)enemyArray->objectAtIndex(i);//判断子弹是否和敌人相撞if(iscallision(bullet, enemy)){//这里移除后应该加入数组  否则会崩溃enemy->removeFromParent();bullet->removeFromParent();bulletA->addObject(bullet);enemyA->addObject(enemy);}}}//从数组中移除子弹for(int i=0;i<bulletA->count();i++){CCSprite *bullet = (CCSprite *) bulletA->objectAtIndex(i);bulletArray->removeObject(bullet);}//从数组中移除敌人for(int i=0;i<enemyA->count();i++){CCSprite *enemy = (CCSprite *) enemyA->objectAtIndex(i);enemyArray->removeObject(enemy);}}//碰撞检测bool AA::iscallision(CCSprite *mysprite,CCSprite *testsprite){CCRect myrect=mysprite->boundingBox();CCRect testrect=testsprite->boundingBox();return myrect.intersectsRect(testrect);}-----------------------------------
©著作权归作者所有:来自51CTO博客作者春蕾夏荷的原创作品,请联系作者获取转载授权,否则将追究法律责任
Cocos2d-X 瓦片地图使用的实例项目(包含碰撞检测,移动)
https://blog.51cto.com/u_10486491/3217098

二、武林风云录

1)老一:陈斩槐(只有四个机制,dps压力不大,留爆发打影子就行)

(1)点名红色扇形区域

(2)点名红色长条,注意最后还有一段大劈


(3)BOSS在百分之80 、50、20血量时会击退玩家,会刷新三个输出位置

  • 应对策略
    需要三个输出职业进入篮圈击杀影子
  • 注意点
    ①每个篮圈只能进一个人,
    ②如果没在30s内击杀影子,影子会爆炸,BOSS将释放地图炮导致团灭
    ③进去打影子的队友,奶妈是奶不了的,需要躲好红圈,躲不了平A

(4)BOSS在百分之35血时会吸玩家到其周围,释放旋风斩,得交解控技能。但是不要着急回去,还有一个圆圈的下坠伤害


  • 额外注意
    boss释放完技能后原地会生成一个龙卷风,靠近会暴毙,需要T尽可能的往副本初始位置拉boss

2)老二:醉仙

  • 机制讲解
    boss是软狂暴boss,每一次喝酒都会叠加后劲不足buff,叠加到12层后会一直放技能而不会平A,解茶小厮也不会出现
  • 备注
    ①奶妈一定要切天问,打好飘絮给boss百分之25增伤

    ②四个输出位置平均喝酒后需要3w的秒伤,T是第二轮供酒可以喝,不然吸引不了仇恨

    ③奶妈不要喝酒
    ④喝酒叠加的buff不要满了,否则点名必死

    ⑤小二都刷新在周边,需要把boss往中心拉否则容易误伤小二

(1)红圈和点名略过

(2)输出记得喝酒(龙吟内功,铁衣外功等)

(3)每一个奉茶小厮都有名字,得按照诗词来按照顺序击杀小二

3)老三:楚相玉

  • 备注
    ①老三技能不按照顺序,有时得同时处理多个boss

(1)boss有狂暴机制,冰火玄功达到极致,倒数360s,将直接团灭(人均得有1.2Wdps)

(2)地上出现红圈,0.5s后将冒出冰柱,击飞造成一段伤害,落地造成二段伤害(估计代码是设计成击飞后掉落下来还在圆圈内)

(3)点名T红色长条,多段伤害


  • 备注
    若红条击中冰柱,则冰柱直接消失

(4)烈焰焚身,需要交减伤或无敌规避伤害

(5)冰风火凤融合产生圆形爆炸区域

  • 应对
    铁衣或神像击飞或吹走

(6)赤炎寒光破

全图玩家都被吸附到boss周围,得躲到冰柱后面,注意得站在冰柱后面,否则服务器判断坐标和冰柱重合或稍微飘逸,则会死亡,这很坑爹

(7)暴风雪

得站在地图的火焰点处

4)老四:刀狂

(1)略过半圆斩、三段长条大劈、落地红圈、黑水机制不在赘述

(2)达到百分之90血时,地上出现追忆碎片,分内外场地(血河上马溜boss,需要奶妈往返内网场用追忆碎片奶安抚boss并奶白剑)

(3)刀狂有怒气机制,到百分之100时增加移速和攻击力


内场会出现安抚之力,需要奶妈拾取

对boss使用安抚之力,boss怒气值清零,地上将会掉落追忆草,失去后增加玩家治疗量

(4)内场讲解

内场将会有白剑npc和各种小怪

白剑:场中npc,需要玩家治疗她,奶满后击败boss后通关

小怪:集火秒掉就行

嗔:打死后出现追忆碎片,使用后出现治疗圆圈,可以治疗玩家和白剑
痴:减疗怪
狂:秒人怪
贪:会回血,且会吃掉场上没被使用的追忆碎片

三、舞阳城

游戏思考30:技能碰撞检测分类枚举及逆水寒魔兽老兵服副本攻略(英雄武林风云录,后续更新舞阳城、扬州、清明等副本攻略)相关推荐

  1. 遇见逆水寒服务器修复,遇见逆水寒暂时关服修整,改为乙女游戏,下次再见就是氪金之时?...

    原标题:遇见逆水寒暂时关服修整,改为乙女游戏,下次再见就是氪金之时? 作为逆水寒的衍生作,遇见逆水寒虽然写作"NPC攻略小助手",但实际上却是一款"恋爱"手游, ...

  2. 逆水寒服务器维护,逆水寒11月29日更新到几点进游戏 逆水寒更新维护公告

    逆水寒在11月29日进行了一次新版本的更新,新团本风雪铁牢关要上线了,很多奖励接踵而来,一些小伙伴还不知道更新了什么,下面就来为大家分享一下逆水寒的更新维护公告. 各位自在同门: 为了保证服务器的运行 ...

  3. buff系统 游戏中_游戏中的技能如何而来? 为ARPG设计一个好用的BUFF系统

    游戏中有宏大的场景地图,丰富的游戏剧情,逼真的人物角色.但要让角色(职业)炫酷起来,还是要靠各个职业的技能来烘托.技能系统,根据游戏类型不同而会有不同,ARPG.回合类RPG.SLG类各个游戏都有技能 ...

  4. 游戏中的技能如何而来? 为ARPG设计一个好用的BUFF系统

    转自:游戏中的技能如何而来? 为ARPG设计一个好用的BUFF系统 - GameRes游资网 游戏中有宏大的场景地图,丰富的游戏剧情,逼真的人物角色.但要让角色(职业)炫酷起来,还是要靠各个职业的技能 ...

  5. 设计解谜游戏的30堂课

    设计解谜游戏的30堂课 文章目录 1.什么是Eureka Moment? 2.谜题与幽默是同构的 3.最大限度提高Sparkle 4.避免无意义的谜题 5.惊喜是Sparkle的重要源泉 6.有趣的事 ...

  6. 通过「解救人质」小游戏教你学会碰撞检测

    游戏开发中,碰撞检测无处不在,今天就通过一个简单的小游戏教你学会如何在 Cocos Creator 中进行碰撞检测.配合官方文档学习效果更加(官方文档传送门:https://docs.cocos.co ...

  7. 国内外3D游戏开发流程和职位分类

    国内外3D游戏开发流程和职位分类 分类: 网游相关2010-07-04 21:11 851人阅读 评论(0) 收藏 举报 国内3D游戏开发流程 开发团队 n 制作人 n 执行制作人 n 策划团队 n ...

  8. 游戏开发笔记-技能系统

    原文地址:http://blog.csdn.net/mooke/article/details/9771545    技能系统是一个对于游戏来说,非常重要,实现起来又有些复杂的模块了.       在 ...

  9. 软件测试缺陷等级划分_游戏测试中缺陷等级分类

    给大家讲游戏测试中缺陷等级分类,它的等级区分不同于应用软件系统的测试,行业不同,分类标准也不同. 视觉级缺陷:此类缺陷不会对游戏功能造成影响,但是一款好游戏不光要心灵美(技术好)也要外型美,给玩家带来 ...

最新文章

  1. 新手入门:Kaggle NLP比赛总结
  2. Jzoj3931【NOIP2014day1官方数据】联合权值
  3. UA MATH563 概率论的数学基础1 概率空间2 可列状态空间
  4. 如何处理postman Self-signed SSL certificate blocked错误
  5. MongoDB第二天
  6. python字典怎么添加值_python字典中如何添加键值对
  7. RabbitMq(九) SpringBoot整合RabbitMQ消费者示例代码
  8. 谷歌离线地图开发教程
  9. js 动画函数库 GreenSock velocityjs
  10. 山体滑坡动画用什么软件制作_做施工动画是用什么软件来做
  11. Word:公式编辑器亲密接触(转)
  12. C64x+ CPU中断 .
  13. 怎么找网页源文件位置_win7系统查看网页源文件的三种方法
  14. 快点射!(Swift Injection) 不带这样的!
  15. LTE CQI/PMI 上报机制
  16. AQS: CLH 介绍
  17. 易极天成温怀玉:聚焦垂直领域 提供多元化产品和服务|企服三会系列报道
  18. 优秀的海外住宅代理该从哪几个角度判断?
  19. 深入理解JAVA线程池
  20. 人物五官怎么画?怎样才能画好人物五官?

热门文章

  1. Python 中的 astype() 和 .dtype
  2. EOS智能合约开发系列(一)
  3. JAVA的卸载与重新安装
  4. MySQL练习(一)
  5. IntelliJ IDEA的安装及插件下载
  6. Lect2 BFS总结
  7. 浅谈数字证书的今生前世
  8. 如何在前台输出代码<xmp>,标签,并且是内容自动换行
  9. linux启动jar包报Invalid or corrupt jarfile jar错误
  10. 选择适合的Node.js授权认证策略