zoukankan      html  css  js  c++  java
  • cocos2d-x 3.0来做一个简单的游戏教程 win32平台 vs2012 详解献给刚開始学习的人们!

    原代码来自于网络,因为cocos2d-x 3.0的资料,的确不多,与曾经版本号的接口非常难对上,


    所以网上非常多样例都无法调试,对于新学习cocos2d-x 的同学,难度添加了,所以出一个超具体的样例给大家。


    源代码地址:http://download.csdn.net/detail/adady/7293629

    #include "HelloWorldScene.h"
    #include "SimpleAudioEngine.h"
    USING_NS_CC;
    
    Scene* HelloWorld::createScene()
    {
        // 1.创建场景
        auto scene = Scene::create();
        
        // 2.创建图层,把当本类创建出来,至layer
        auto layer = HelloWorld::create();
    
        // 3.把layer放到 场景其中
        scene->addChild(layer);
    
        // 4.返回此场景
        return scene;
    }
    
    void HelloWorld::onEnter()	//init() 之后就到这个函数
    {
    	LayerColor::onEnter();		//执行 LayerColor 的 onEnter();
        
    	auto listener = EventListenerTouchOneByOne::create();	//创建监听事件
    	listener->setSwallowTouches(true);			//时间是否向下传递,true 就不会向下传递
    
        listener->onTouchBegan = [=](cocos2d::Touch* touch,cocos2d::Event* event)		//****这还没懂,是什么意思,弄清楚了,告诉大家,或则大家能够与我分享
        {
            return true;
        };
    	listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);			//弹起后,调用onTouchEnded函数
    
    	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);		//导演加入 listener 事件
    }
    
    void HelloWorld::update(float t)					
    {
    	Vector<Sprite*> targetsToDelete;				//列表targetsToDelete
    	Vector<Sprite*> projectilesToDelete;			//列表projectilesToDelete
        
    	for (int i = 0; i < _projectiles.size(); i++)		//从0至全部进入列表的子弹(所以还没有消失的子弹,包含屏幕外面的还没有结束的)
    	{
    		auto projectile = _projectiles.at(i);			//当前第i 个子弹 保存至 projectile
    
    		//获取当前子弹的坐标及大小  得到一个矩形    这里减一个projectile->getContentSize().width / 2,是由于他的锚点在中心,所以要减掉
    		auto projectileRect = Rect(
                                       projectile->getPositionX() - projectile->getContentSize().width / 2,
                                       projectile->getPositionY() - projectile->getContentSize().height / 2,
                                       projectile->getContentSize().width,
                                       projectile->getContentSize().height );
            
    		for (int j = 0; j < _targets.size(); j++)
    		{
    			auto target = _targets.at(j);     //当前第j 个目标 保存至 target
    			//获取当前目标的坐标及大小  得到一个矩形
    			auto targetRect = Rect(
                                       target->getPositionX() - target->getContentSize().width / 2,
                                       target->getPositionY() - target->getContentSize().height / 2,
                                       target->getContentSize().width,
                                       target->getContentSize().height);
                
    			if (projectileRect.intersectsRect(targetRect))       //一一比对,有没有子弹与目标碰撞了
    			{
    				targetsToDelete.pushBack(target);				//碰撞后,把要删除的目标,加入队列
    			}
    		}
            
    		//C++11 的 range-based for循环
    		for (Sprite* target : targetsToDelete)		//遍历  targetsToDelete 里全部元素  一一保存至 target
    		{
    			_targets.eraseObject(target);			//移除  _target表里的  target,并非  targetsToDelete
    			this->removeChild(target);				//当前 layer 移掉 target
                
                _projectilesDestroyed++;				//每打中一个 加一分
                if (_projectilesDestroyed >3) {			//大于3分 转换至 成功场景
                    auto gameOverScene = GameOverScene::create();
                    gameOverScene->getLayer()->getLabel()->setString("You Win!");
                    Director::getInstance()->replaceScene(gameOverScene);
                }
    		}
            
    		if (targetsToDelete.size() >0)				//当第i个子弹 有碰撞,就意味着 size 大于0
    		{
    			projectilesToDelete.pushBack(projectile);    //把当前子弹加入入 子弹删除列表
    		}
    		targetsToDelete.clear();					// 清空 目标删除 列表
    	}
    	
    	for (const auto& p : projectilesToDelete)		//遍历  targetsToDelete 里全部元素  一一保存至 p
    	{
    		_projectiles.eraseObject(p);				//移除  _projectiles表里的  target,并非  projectilesToDelete
    		this->removeChild(p);						//当前 layer 移掉 projectiles
    		//p->removeFromParentAndCleanup(true);
    	}
    	projectilesToDelete.clear();					// 清空 目标删除 列表
    	
    }
    
    // on "init" you need to initialize your instance
    bool HelloWorld::init()
    {
        if ( !LayerColor::initWithColor(Color4B(255,255,255,255)) )	//5. 把本图层的背景设置成白色
        {
            return false;			//假设图层没有被创建就false
        }
        
        Size visibleSize = Director::getInstance()->getVisibleSize();	//getInstance()应该是得到导演的句柄,取得屏幕的尺寸
        
    
        auto player = Sprite::create("Player.png", Rect(0, 0, 27, 40));     //创建一个玩家的精灵,他的大小改动为27 hight:40
    	player->setPosition(Point(player->getContentSize().width/2, visibleSize.height / 2));    //设置精灵出现的位子,程序选择放在(27/2,屏幕中间)的位子,就是在左中,全然的能够显示图片
    	this->addChild(player, 0);	//加入玩家精灵,进入图层
        
        //更新函数
        this->schedule(schedule_selector(HelloWorld::gameLogic), 1.0f);   //schedule是按时调用一个函数的方法,定义这个以后就会隔一段时间调用一次该方法,每一秒调用一次gameLogic函数   //schedule_selector 应该是注冊HelloWorld::gameLogic 这个函数
    
    	this->scheduleUpdate();			//这表示大概每0.01秒 调用一次 Update()函数
        
        CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("background-music-aac.caf");     //载入声音文件
        
        return true;
    }
    
    void HelloWorld::gameLogic(float dt)			//每1秒调用一次
    {
    	addTarget();//每1秒调用一次
    }
    
    void HelloWorld::addTarget()
    {
    	Size visibleSize = Director::getInstance()->getVisibleSize();		//得到屏幕尺寸
        
    	auto target = Sprite::create("Target.png", Rect(0, 0, 27, 40));		//创建一个 目标精灵
        
        // Determine where to spawn the target along the Y axis
    	int minY = target->getContentSize().height / 2;						  // 得到Target 能够显示的最小位置   (相当于图片的height 的中点)
    	int maxY = visibleSize.height - target->getContentSize().height / 2;  // 得到Target 能够显示的最大位置    
    	int rangeY = maxY - minY;											  // 得到可显示区域的大小
    	int actualY = (CCRANDOM_0_1() * rangeY) + minY;					      //(随机产生一个数(0,1) * rangeY) + minY   得到(0-1)的小数	
    	target->setPosition(Point(visibleSize.width + target->getContentSize().width / 2, actualY));  //设置Target 出现的位子
    	this->addChild(target,0);											//加入到本图层内
        
        target->setTag(1);													//设置这个Targer 的标签为1
        _targets.pushBack(target);											//把Target 存于 _targets的列表
        
    
    	//以下4句,随即产生一个速度
    	int minDuration = 2.0;
    	int maxDuration = 4.0;
    	int rangeDuration = maxDuration - minDuration;
    	int actualDuration = (CCRANDOM_0_1() * rangeDuration) + minDuration;
        
        
    	
    	auto actionMove = MoveTo::create(actualDuration, Point(-target->getContentSize().width, actualY));  //创建一个速度移动, actualDuration速度, Point(-target->getContentSize().width, actualY)是起始点
    	auto actionMoveDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::spriteMoveFinished, this));	//这里是创建一个回调函数,就是调用spriteMoveFinished函数 并把自己传出去this。
        
    	target->runAction(Sequence::create(actionMove, actionMoveDone, NULL));		//执行一个动画  actionMove 移动方法   actionMoveDone回调的函数
    
    	//从上面看来,这个函数,每1秒创建一个Target 精灵,从屏幕的最右边,随机高度,至左移动
    
    }
    
    void HelloWorld::onTouchEnded(Touch* touch, Event* event)				//按下事件
    {
    	Size visibleSize = Director::getInstance()->getVisibleSize();		//获得屏幕尺寸
        
    	auto touchPoint = touch->getLocation();								//获得点击坐标
        
    	auto projectile = Sprite::create("Projectile.png", Rect(0, 0, 20, 20));    //创建一个子弹
    	projectile->setPosition(Point(20, visibleSize.height / 2));					//设置子弹位子
        
    	// Determine offset of location to projectile
    	int offX = touchPoint.x - projectile->getPosition().x;				//点击位置与子弹X位置的差值
    	int offY = touchPoint.y - projectile->getPosition().y;				//点击位置与子弹Y位置的差值
        
    
    	if (offX <= 0) return;												//假设 子弹 超出范围 return
        
    
    	this->addChild(projectile);											//把 子弹 加入进图层
        
        projectile->setTag(2);					// 把子弹的标签设置为2
        _projectiles.pushBack(projectile);		// 把子弹加入进子弹列表
        
    	// Determine where we wish to shoot the projectile to
    	int realX = visibleSize.width + (projectile->getContentSize().width / 2);     //求出屏幕最大 + 子弹的一半, (求出子弹消失的最大x)
    	float ratio = (float)offY / (float)offX;					//斜率
    	int realY = (realX * ratio) + projectile->getPosition().y;					//求出真实的y值,同样的斜率
    	auto realDest = Point(realX, realY);				//子弹要去位置
        
    	// 理解上面的话,以下5句就非常好理解了
    	int offRealX = realX - projectile->getPosition().x;		//真实X值
    	int offRealY = realY - projectile->getPosition().y;		//真实Y值
    	float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));	//求出 直线距离
    	float velocity = 960 / 1; // 960pixels/1sec				//960 像素/ 1秒
    	float realMoveDuration = length / velocity;				//速度
        
    	// 创建一个动作,移动动作,realMoveDuration速度,至realDest,并进入回调函数
    	projectile->runAction(Sequence::create(MoveTo::create(realMoveDuration, realDest),CallFuncN::create(CC_CALLBACK_1(HelloWorld::spriteMoveFinished, this)), NULL));
    
        CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("pew-pew-lei.caf");   //载入声音文件
    }
    
    
    void HelloWorld::spriteMoveFinished(Ref* pSender)
    {
    	Sprite *sprite = (Sprite *)pSender;				//获得的Target  转成 sprite 类型
        
        if (sprite->getTag() == 1) {					//假设 标签 等于 1 
    		_targets.eraseObject(sprite);				//从_target列表里删掉Target      仅仅是从列表里删掉
            
            auto gameOverScene = GameOverScene::create();        //创建一个GameOver的场景
            gameOverScene->getLayer()->getLabel()->setString("You Lose :[");    //显示youLose
            Director::getInstance()->replaceScene(gameOverScene);				//替换成刚生成的GameOver场景
    	} else if(sprite->getTag() == 2) {				//假设 标签 等于 2
    		_projectiles.eraseObject(sprite);			//从_projectiles列表里删掉 Projectiles     仅仅是从列表里删掉
    	}
        
        this->removeChild(sprite);						//删掉sprite 这个图层
        
    }
    
    void HelloWorld::menuCloseCallback(Ref* pSender)
    {
        Director::getInstance()->end();
    
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        exit(0);
    #endif
    }
    



    
    

  • 相关阅读:
    轻松处理高于平常10倍的视频需求,还能节省60%的IT成本,蓝墨做对了什么?
    支付宝研究员王益的建议:“学好语文,才能写好代码”
    Flutter+FaaS一体化任务编排的思考与设计
    开放下载!《大促背后的前端核心业务实践》
    揭秘!信息检索技术高端玩法
    秒懂云通信:如何用阿里云语音通知服务(小白指南)
    卡顿人生,如何拯救?
    阿里云荣获可信云容器安全能力先进级认证, ACK/ACR为企业级安全护航
    飞天大数据产品价值解读— SaaS模式云数据仓库MaxCompute
    阿里产品专家:高情商的技术人,如何做沟通?
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4275803.html
Copyright © 2011-2022 走看看