hello,一连好几天的雨。
《占星起源》星星的创建和游戏检测
回顾:
上次把《占星起源》的“线段”弄好了,现在就要开始弄“星星”了。对了《占星起源》本身有很多关卡,这里只是开发其中一个,可能有人看了之后觉得挺奇怪的,可以说这里本身不算是一个游戏,在下一期,将会解释怎么实现其他关卡:
现在开始开发“星星”:
当玩家移动线段跟星星有接触的时候,星星应该有所反应,提示玩家成功连接一颗星星:
效果:(这里没有其他美术资源,所以。。。。)
现在就来开发这个类:
class Star :public Sprite{
public:
CREATE_FUNC(Star);
virtual bool init();
void SMove();//动作
Sprite*ball;//底图(用来执行动画的东西)
void Setop();//动作停止
};
实现:
bool Star::init(){
this->initWithFile("ch.png");//初始化纹理
this->setScale(0.5);//缩放
ball=Sprite::create("io.png");
ball->setPosition(this->getContentSize().width/2,this->getContentSize().height/2);
this->addChild(ball,-1);//加入到渲染
//下一期这里会有变动
return true;
}
void Star::SMove(){
auto ac1=ScaleTo::create(0.5, 3);//动作1
auto ac2=ScaleTo::create(0.5, 1);//动作2
auto seq=Sequence::create(ac1,ac2, NULL);//动作组合
auto rep=RepeatForever::create(EaseInOut::create(seq,0.5));
//重复执行
ball->runAction(rep);//执行动作
}
(这里就是视频中动作的主要代码了,是不是很简单的说)
void Star::Setop(){
ball->stopAllActions();
//下一期这里会有变动
}
(就这样就写好了星星这个类,往后可能会增加一些功能)
然后布局你的星星:(这里布局如下:)
布局(创建)星星的时候,还要考虑接下来对星星的检测。所以这里使用一个 vector容器来存放星星,方便以后遍历:(这里没有使用地图来布局)
头文件中:
Star*p1,*p2,*p3,*p4,*p5,*p6;
Vector<Sprite*> *pol;
实现文件中:
pol=new Vector<Sprite*>(0);// 初始化容器
void GameScene::CreateP(){
p1=Star::create();
p2=Star::create();
p3=Star::create();
p4=Star::create();
p5=Star::create();
p1->setPosition(Point(117,388));
p2->setPosition(Point(181,288));
p3->setPosition(Point(241,183));
p4->setPosition(Point(367,200));
p5->setPosition(Point(600,302));
this->addChild(p1);
this->addChild(p2);
this->addChild(p3);
this->addChild(p4);
this->addChild(p5);
pol->pushBack(p1);//把创建好的星星加入到容器里
pol->pushBack(p2);
pol->pushBack(p3);
pol->pushBack(p4);
pol->pushBack(p5);
}
如何检测线“线段”是否穿过星星呢?
这里得写一个比较全面的方法:
这里我推荐几个方法(不一定最高效,但足够可靠):
[1]
A 到 B 线段中有许多点组成,如果该线段经过星星,必有一点在星星内部,检测星星内部是否包含该点即可。
计算时是这样的:
求出角 A ,计算A 到 B 在 X ,Y 轴方向的步进,用 A 的坐标不断 增加即可:
(这里并不是每一个点又要检测,不然性能不好)
比如:
这里的步进为红色箭头距离
[2]
求出绿色线段距离(星星和一个转折点的距离),求出 角 c(a-b) ,由三角函数算出s,判断是否大于星星的半径。
等等。。。。。
这里采用第2种方法:
首先为了能检测全部的星星,所以这里写一个函数方便检测:
void GameScene::check(Star*sp){// 星星类型的变量
auto d1=sp1->getPosition();//a 点位置
auto d2=sp2->getPosition();// b
auto len=d1-d2;
auto rod=len.getAngle();//a b 距离
auto ang=CC_RADIANS_TO_DEGREES(-rod);
//log("%f",ang);
if(ang>90){
ang=180-ang;//保持在 0-90度之间
}
auto d3=sp->getPosition();//星星位置
auto Len=d3-d2;
auto Rod=Len.getAngle();
auto Ang=CC_RADIANS_TO_DEGREES(-Rod);
// log("%f",Ang);
if(Ang>90){
Ang=180-Ang;
}
auto nexangle=fabsf(Ang-ang);/得到角c
log("%f",nexangle);
if(Len.getLength()*sin(CC_DEGREES_TO_RADIANS(nexangle))<=sp->getContentSize().width/2){
//判断是否大于星星半径
sp->SMove();//执行星星的动作
log("cccc");
}else{
sp->Setop();//否则不执行
}
}
检测的时候只需要把容器里的星星一个一个的取出来,检测即可:
for(auto c=pol->begin();c!=pol->end();c++){
check(*c);
}
这个函数还是不够的。
还需要对星星的位置进行判断:
时间有点晚了,下一次在补全吧。
以下这几种情况不能正常检测:
等等。。。。
网友评论