用 cocos2d-x 3.0rc1版本做一个贪吃蛇,顺便写一个教程,碰到问题就试着解决。第一次写,写的丑了莫怪,实用为主
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
环境:
cocos2d-x-3.0rc1
Xcode5
OS X 10.9.2
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1.创建一个新的项目!具体方法见:http://www.cocos2d-x.org/docs/manual/framework/native/getting-started/v3.0/how-to-start-a-new-game/en
(E文不好的朋友请自带翻译妹子或翻译软件)
项目就叫个snake!真是霸气。顺带一提cocos console真是赞!
机器叫了一会 给我了个文件夹叫snake。居然有194.5m!
,我和我的晚饭都觉得项目”自由“了,好饿阿 中饭没次
。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
2.双击snake/pro.ios_mac/snake.xcodeproj 打开项目,按照国际惯例 我们先编译以下看看这货能不能跑!
跑的异常欢快!!
然后我们找到class 和resources 这两个文件夹很重要。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
3.接下来 先准备好素材把!打开ps画一个 妥妥的,就是这个像饭团一样的东西,要的自己拿吧 一块钱一个。
把这个饭团导入resources,直接拖!就是那个bo.png,这个贪吃蛇要用到的素材就这个饭团。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
4.选个场景,就用这个项目自带的场景, 一个场景足够了,把除了那个按钮之外的node都注释掉吧,没用了。删了也没事。关闭按钮留着,好看又好用。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
5.首先 我们先把控制实现,无非是上下左右3.0与以前的触摸机制不一样了,采用设置监听器的方式,让我想起了j2se里图形化界面的监听方式。
控制的实现思想:用两个一次函数 把屏幕分为4个三角型,上下左右分别一块,用来控制蛇的移动方向。看代码就明白!
auto listener1 = EventListenerTouchOneByOne::create();//创建一个监听
listener1->setSwallowTouches(true);//设置是否想下传递触摸
listener1->onTouchBegan = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());//获取的当前触摸的目标
Point p = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
auto winsize = Director::getInstance()->getVisibleSize();
if (rect.containsPoint(p))//判断触摸点是否在目标的范围内
{
if(winsize.height/winsize.width * p.x+p.y>winsize.height)
{
if(winsize.height/winsize.width * p.x<p.y)
{
log("up");
}else
{
log("left");
}
}else
{
if(winsize.height/winsize.width * p.x<p.y)
{
log("right");
}
else
{
log("down");
}
}
return true;
}else
return false;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
这样就完成了控制!方向键都省了。
顺带一提 在3.0里面声明变量可以不用说明类型 用auto代替,当然你也可以声明类型。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
6.好了接下来我们把蛇实现了,蛇是一节节的,要一个vector来存储每一节,每节都用我们的上面的饭团图片来表示。贪吃蛇吃的苹果 也用这个图片来表示,为了区别 我们用setColor上点颜色。蛇上绿色吧,苹果是红色。然后我们在init里面创建蛇头和苹果。
this->apple = Sprite::create("bo.png");
apple->setAnchorPoint(Point(0,0));
apple->setPosition(Point(22*20,12*20));
apple->setColor(Color3B(255,0,0));
this->addChild(this->apple);
auto head = Sprite::create("bo.png");
head->setAnchorPoint(Point(0,0));
head->setPosition(Point(2*20,12*20));
head->setColor(Color3B(0,255,0));
this->snake.pushBack(head);
this->addChild(this->snake.at(0));
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
7.用一个schedule来控制蛇持续移动
void HelloWorld::up_date(float dt){
move(this->direction, this->snake.size()-1);
}
this->direction = 2;
this->speed = 100;
schedule(schedule_selector(HelloWorld::up_date), 60/this->speed);
整型direction控制方向 1:上,2:右,3:下,4:左
整型speed 控制蛇的速度。
move方法来控制每一节身体的移动,具体见源码吧 比较多 不帖出来了。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
8.关联控制器和direction ,刚才写好的控制现在可以用了,改变方向并调用一次move,为了操作的手感好一点 我在这里写了一个函数用来重置了控制移动的schedule,如果要改变速度的话也要调用这个函数,不过这边我们还不考虑变速。
很好!现在我们小蛇已经可以动了 ,不过只有一节。。。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
9.接下来我们让我们的蛇可以吃苹果,写了一个函数testEat用来检测有没有吃到苹果!
void HelloWorld::testEat(){
auto head_size = this->snake.at(0)->getContentSize();
auto head_point = this->snake.at(0)->getPosition();
auto head_rect = Rect(head_point.x,head_point.y,20 ,20);
auto apple_point = this->apple->getPosition();
auto ap = Point(apple_point.x+10,apple_point.y+10);
if(head_rect.containsPoint(ap)){
log("Good eat!!");
auto body = Sprite::create("bo.png");
body->setAnchorPoint(Point(0,0));
body->setColor(Color3B(0,255,0));
this->snake.pushBack(body);
this->addChild(this->snake.at(this->snake.size()-1));
body->setPosition(this->snake.at(this->snake.size()-2)->getPosition());
//random set apple
auto winsize = Director::getInstance()->getVisibleSize();
auto x_l = winsize.width/20-1;
auto y_l = winsize.height/20-1;
while (true) {
srand((int)time(NULL)+(int)time(0));
this->apple->setPosition(Point( (rand() % ((int)x_l+1)) *20,(rand() % ((int)y_l+1))*20));
bool b = true;
for (auto i=0; i<this->snake.size(); i++) {
auto body_size = this->snake.at(i)->getContentSize();
auto body_point = this->snake.at(i)->getPosition();
auto body_rect = Rect(body_point.x,body_point.y,20 ,20);
auto apple_ppoint = this->apple->getPosition();
auto app = Point(apple_ppoint.x+10,apple_ppoint.y+10);
if(body_rect.containsPoint(app)){
b=false;
}
}
if (b)
break;
}
testGameisOver(false);
}
}
吃到苹果,加一节 应该很好理解。后面的代码用来改变苹果的位置,让蛇可以再吃一次。。所以本质上苹果没有被吃掉。。。只是跑了,不管,最后的函数用来测试游戏的胜负,吃到40节就赢啦!
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
10.接下来是怎么检测蛇挂了。。。真是不吉利,好吧,吃到自己或者碰到墙壁就结束游戏!具体见testGameisOver函数,每次move后要调用检测一下。
//失败情况 1.撞墙 2.吃到自己 (移动后检测)
bool b = false;
if (snake.size()>2) {
for (auto i=1; i<this->snake.size(); i++) {
auto body_size = this->snake.at(i)->getContentSize();
auto body_point = this->snake.at(i)->getPosition();
auto body_rect = Rect(body_point.x,body_point.y,20 ,20);
auto head_point = this->snake.at(0)->getPosition();
auto app = Point(head_point.x+10,head_point.y+10);
if(body_rect.containsPoint(app)){
b=true;
}
}
}
if (this->snake.at(0)->getPositionX() >= winsize.width || this->snake.at(0)->getPositionX() < 0 ||
this->snake.at(0)->getPositionY() >= winsize.height || this->snake.at(0)->getPositionY() < 0 || b)
{
//game over
unschedule(schedule_selector(HelloWorld::up_date));
_eventDispatcher->removeEventListenersForType(EventListener::Type::TOUCH_ONE_BY_ONE);
auto label = LabelTTF::create("GAME OVER", "Arial", 50);
label->setPosition(Point(winsize.width/2,winsize.height/2));
this->addChild(label, 1);
label->setScale(0);
label->runAction(ScaleTo::create(3, 1.5));
label->setOpacity(0);
label->runAction(FadeTo::create(1.5, 255));
this->runAction(Sequence::create(DelayTime::create(5),CallFunc::create([]{Director::getInstance()->replaceScene(HelloWorld::createScene());}), NULL));
}
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
11.胜负!
其实上面的代码已经显示出来!有一个label弹出来,我加了点动画,然后等个几秒 重新载入场景 ,test里面都是这么干的。。。。
截个输的图吧,赢得画面要花点时间才看得到。
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
12.其实到这里游戏已经基本上完成了,虽然有点简陋,而且在电脑上操作也不太方便,可以考虑加入上下左右的键盘控制,绘制两条对角直线等,这篇就这样吧,下一篇我会稍微完善一下,然后在win32 android 和mac iOS四个平台上运行。!真是赞!请大家支持Dz.Harry.Yang 谢谢大家!跟我一起来学 cocos2d-x 3.0吧!
声明:今天是第一天接触2dx3.0,有些地方写的不太好,希望高手不要喷阿!善意的提醒万分欢迎,我只是个学生。。。还在学习阿!!