好贷网好贷款

【cocos2d-x 3.0】入门样例《SimpleGame》源码解读【2】

发布时间:2016-12-4 18:33:42 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"【cocos2d-x 3.0】入门样例《SimpleGame》源码解读【2】",主要涉及到【cocos2d-x 3.0】入门样例《SimpleGame》源码解读【2】方面的内容,对于【cocos2d-x 3.0】入门样例《SimpleGame》源码解读【2】感兴趣的同学可以参考一下。

上一篇我们以这个游戏的win32\main.cpp为出发点,分析了引擎的启动入口和基本运作机制,回顾最后的一个重点语句 auto scene = HelloWorld::scene();从这里开始,后面的工作真正交给了我们,不用太关心引擎底层运行机制的问题了! 让我们进入HelloWorldScene类吧,先来看一下上面调用的这个方法 Scene* HelloWorld::scene() { Scene * scene = NULL; do { // 'scene' is an autorelease object // [RN] 创建一个场景实例(一个空白的场景) scene = Scene::create(); CC_BREAK_IF(! scene); // 'layer' is an autorelease object // [RN] 创建一个HelloWorld场景层(即本类所表现的层) HelloWorld *layer = HelloWorld::create(); // [RN] *注意* 正是这句调用了下面的init()方法来初始化! CC_BREAK_IF(! layer); // [RN] 把上面的层放入场景 // add layer as a child to scene scene->addChild(layer); } while (0); // return the scene // [RN] 返回这个场景指针(返回到AppDelegate::applicationDidFinishLaunching(),然后由导演director来执行这个场景) return scene; } 这里涉及到了scene和layer的概念 根据UP主个人的理解,scene就像是一个空白的舞台,无论你想表现什么东西首先需要一个舞台 然后layer就像是舞台中的一层布景(因为布景可能有前景、背景或者更多层) 我们的HelloWorldScene类正是继承自cocos2d::LayerColor 所以这个游戏中的HelloWorldScene场景类对象,也就是一个自身包含了舞台scene和layer的东西 接下来注意到HelloWorld::create()实际上就是通过一个宏调用了HelloWorld::init()方法,我们看看它又做了什么 // on "init" you need to initialize your instance bool HelloWorld::init() { bool bRet = false; do { ////////////////////////////////////////////////////////////////////////// // super init first ////////////////////////////////////////////////////////////////////////// // [RN] 预处理白色背景 CC_BREAK_IF(! LayerColor::initWithColor( Color4B(255,255,255,255) ) ); ////////////////////////////////////////////////////////////////////////// // add your codes below... ////////////////////////////////////////////////////////////////////////// // 1. Add a menu item with "X" image, which is clicked to quit the program. // Create a "close" menu item with close icon, it's an auto release object. // [RN] 创建关闭按钮的图片对象,并传入关闭功能的回调函数 auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback,this)); CC_BREAK_IF(! closeItem); // Place the menu item bottom-right conner. // [RN] 将关闭按钮置位右下角 auto visibleSize = Director::getInstance()->getVisibleSize(); auto origin = Director::getInstance()->getVisibleOrigin(); closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2, origin.y + closeItem->getContentSize().height/2)); // Create a menu with the "close" menu item, it's an auto release object. // [RN] 创建菜单对象,并将关闭按钮放置其中 auto menu = Menu::create(closeItem, NULL); menu->setPosition(Point::ZERO); CC_BREAK_IF(! menu); // Add the menu to HelloWorld layer as a child layer. // [RN] 将菜单对象置入画面,并且定位于更高的层 this->addChild(menu, 1); ///////////////////////////// // 2. add your codes below... // [RN] 创建玩家的精灵 auto player = Sprite::create("Player.png", Rect(0, 0, 27, 40) ); player->setPosition( Point(origin.x + player->getContentSize().width/2, origin.y + visibleSize.height/2) ); this->addChild(player); // [RN] 定时器,每隔1.0秒执行gameLogic添加一个敌人 this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0 ); // [RN] 获得事件Dispatcher auto dispatcher = Director::getInstance()->getEventDispatcher(); // [RN] 创建多点触控事件Listener auto listener = EventListenerTouchAllAtOnce::create(); // [RN] 指定触摸之后回调的函数 listener->onTouchesEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this); // [RN] 注册(启用)触控事件Listener dispatcher->addEventListenerWithSceneGraphPriority(listener, this); // [RN] 创建敌人数组、子弹数组并初始化 _targets = new Array(); _targets->init(); _projectiles = new Array(); _projectiles->init(); // use updateGame instead of update, otherwise it will conflit with SelectorProtocol::update // see http://www.cocos2d-x.org/boards/6/topics/1478 // [RN] 未指定间隔的定时器,表示每帧都会执行updateGame(在本例就是做中弹判定用) this->schedule( schedule_selector(HelloWorld::updateGame) ); // [RN] 播放背景音乐的简单方法 CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("background-music-aac.wav", true); bRet = true; } while (0); return bRet; } 上面的一系列工作,就好比演出之前,我们需要准备好即将登台的演员和道具 值得一提的是两个 定时器,还有触摸事件的回调函数,它们是使这个游戏运作起来的关键 第一个定时器调用了HelloWorld::gameLogic方法,就是每隔1秒增加一个敌人 void HelloWorld::gameLogic(float dt) { this->addTarget(); }具体是这样增加的 // cpp with cocos2d-x void HelloWorld::addTarget() { // [RN] 创建敌人精灵 Sprite *target = Sprite::create("Target.png", Rect(0,0,27,40) ); // Determine where to spawn the target along the Y axis // [RN] 获取可视区域尺寸(理论创建尺寸,并非放缩后的显示尺寸) Size winSize = Director::getInstance()->getVisibleSize(); float minY = target->getContentSize().height/2; float maxY = winSize.height - target->getContentSize().height/2; int rangeY = (int)(maxY - minY); // srand( TimGetTicks() ); int actualY = ( rand() % rangeY ) + (int)minY; // Create the target slightly off-screen along the right edge, // and along a random position along the Y axis as calculated // [RN] 设置敌人初始位置从屏幕最右侧开始,随机一个高度 target->setPosition( Point(winSize.width + (target->getContentSize().width/2), Director::getInstance()->getVisibleOrigin().y + actualY) ); this->addChild(target); // Determine speed of the target // [RN] 随机一个敌人速度 int minDuration = (int)2.0; int maxDuration = (int)4.0; int rangeDuration = maxDuration - minDuration; // srand( TimGetTicks() ); int actualDuration = ( rand() % rangeDuration ) + minDuration; // Create the actions // [RN] 创建一个动作:移动到屏幕最左方 FiniteTimeAction* actionMove = MoveTo::create( (float)actualDuration, Point(0 - target->getContentSize().width/2, actualY) ); // [RN] 指定动作结束后回调的函数 FiniteTimeAction* actionMoveDone = CallFuncN::create( CC_CALLBACK_1(HelloWorld::spriteMoveFinished, this)); // [RN] 在target身上实施上面定义的动作与回调 target->runAction( Sequence::create(actionMove, actionMoveDone, NULL) ); // Add to targets array // [RN] 设定敌人的TAG为1 target->setTag(1); // [RN] 最后将本次生成的敌人target加入敌人列表 _targets->addObject(target); }基本上都是很容易懂的,不过其中有个关键之处,就是在敌人动作结束之后(飞到屏幕最左方之后)回调了HelloWorld::spriteMoveFinished方法 void HelloWorld::spriteMoveFinished(Node* sender) { Sprite *sprite = (Sprite *)sender; // [RN] 从场景上移除这个对象 this->removeChild(sprite, true); // [RN] 如果这个对象是敌人对象,则在敌人数组中移除这个敌人 if (sprite->getTag() == 1) // target { _targets->removeObject(sprite); // [RN] 敌人逃脱,你输了!创建GameOver场景并切换过去 auto gameOverScene = GameOverScene::create(); gameOverScene->getLayer()->getLabel()->setString("You Lose :["); Director::getInstance()->replaceScene(gameOverScene); } else if (sprite->getTag() == 2) // projectile { // [RN] 如果是一个子弹对象,则在子弹数组中移除这个子弹,不触发别的事件 _projectiles->removeObject(sprite); } } 这个方法处理了所有sprite精灵对象运动结束后的事件,其中包含了游戏结束的逻辑,建立GameOver场景并显示 细心的同学可能发现了,GameOverScene创建场景实例的方式好像和HelloWorldScene并不太一样 没错,通过对比HelloWorldScene.h和GameOverScene.h可以发现: 前者本身继承于Layer,类中包含了一个static的scene()方法里create了一个scene对象、一个layer层,最终通过调用scene()方法返回场景指针; 后者本身继承于Scene,类中包含了一个_layer对象,最终直接通过调用类的create方法(其中创建了_layer层)并返回场景指针 两种途径都可以实现场景类的管理,总之最后交给导演director的都是scene,然而scene里包含了layer。 至此关于第一个定时器:增加敌人、以及判定GameOver的过程我们已经有所了解。 下一篇将会讨论init()方法中的第二个定时器处理中弹判定,以及触摸发射子弹的机制

上一篇:乐蜂网今日卖身唯品会
下一篇:group by语句

相关文章

相关评论