• cocos2d-x 3.0游戏实例学习笔记 《跑酷》第四步--地图循环&主角加入动作


    说明:这里是借鉴:晓风残月 前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记

    这一步其中,我们主要完毕下面功能:

    1.地图的无限滚动---让主角看起来真的是在跑动

    2.给主角加入Jump跳跃和crouch下蹲动作

    那么首先来让背景滚动起来,在PlayScene.h中加入:

    //初始化背景
    void initBG();
    //用update函数让地图滚动
    virtual void update(float dt);
    
    //背景精灵
    cocos2d::Sprite* bgSprite1;
    cocos2d::Sprite* bgSprite2;
    cocos2d::Sprite* groundSprite1;
    cocos2d::Sprite* groundSprite2;
    然后.Cpp文件里:

    void PlayScene::initBG(){
    	auto visibleSize = Director::getInstance()->getVisibleSize();
    	//背景1
    	bgSprite1 = Sprite::create("Map00.png");
    	bgSprite1->setPosition(visibleSize.width/2,visibleSize.height/2);
    	this->addChild(bgSprite1);
    
    	//地面1
    	groundSprite1 = Sprite::create("Ground00.png");
    	groundSprite1->setPosition(visibleSize.width/2,groundSprite1->getContentSize().height/2);
    	this->addChild(groundSprite1);
    
    	//背景2
    	bgSprite2 = Sprite::create("Map01.png");
    	bgSprite2->setPosition(bgSprite1->getContentSize().width+visibleSize.width/2,visibleSize.height/2);
    	this->addChild(bgSprite2);
    	
    	//地面2
    	groundSprite2 = Sprite::create("Ground01.png");
    	groundSprite2->setPosition(bgSprite1->getContentSize().width+visibleSize.width/2,groundSprite2->getContentSize().height/2);
    	this->addChild(groundSprite2);
    }
    
    void PlayScene::update(float dt){
    	int posX1 = bgSprite1->getPositionX();
    	int posX2 = bgSprite2->getPositionX();
    
    	posX1 -= 2;
    	posX2 -= 2;
    
    	auto mapSize = bgSprite1->getContentSize();
    
    	if(posX1 < -mapSize.width/2){
    		posX1 = mapSize.width + mapSize.width/2;
    		posX2 = mapSize.width/2;
    	}
    	if(posX2 < -mapSize.width/2){
    		posX2 = mapSize.width + mapSize.width/2;
    		posX1 = mapSize.width/2;
    	}
    
    	bgSprite1->setPositionX(posX1);
    	bgSprite2->setPositionX(posX2);
    	groundSprite1->setPositionX(posX1);
    	groundSprite2->setPositionX(posX2);
    }
    
    完毕这些,我们就在PlayScene中的init函数:

    bool PlayScene::init(){
    	if(!Layer::init()){
    		return false;
    	}
    
    	SimpleAudioEngine::getInstance()->playBackgroundMusic("background.mp3",true);
    	
    	initPhysicWorld();
    
    	initBG();
    
    	//开启update
    	this->scheduleUpdate();
    
    	m_runner = Runner::create();
    	m_runner->setPosition(runner_posX,ground_hight+m_runner->getRunJumpSize().height/2);
    	m_runner->Run();
    
    	this->addChild(m_runner);
    
    	return true;
    }
    
    这里要注意:我们应该把背景的初始化放置在主角创建的前面,由于先创建主角,就等于在屏幕上先画出主角,然后再画背景,那么主角就会被挡住。当然,这里也能够设置绘画的层次,那么执行例如以下图:



    这里任然不是 动态的截图,所以看不出地图滚动的效果,求指导。。。


    以下来为主角加入除开跑动的其它动作:

    在Runner的 initActionSet函数中,我们先加入其它的帧动画:

    void Runer::initActionSet(SpriteFrameCache* frameCache){
    	SpriteFrame* frame = NULL;
    	//3.0中改用vector 而不是用Array
    	Vector<SpriteFrame*>frameVector;
    	
    	/* 1.----------------载入跑动的Animation-----------------*/
    	for(int i = 0; i <= 7; i ++) {
    		//从缓存池中载入精灵到Vector
    		frame = frameCache->spriteFrameByName(String::createWithFormat("runner%d.png",i)->getCString());
    		frameVector.pushBack(frame);
    	}
    
    	//用vector里面的SpriteFrame列表创建Animation  以及设置一些參数
    	auto run_animation = Animation::createWithSpriteFrames(frameVector,0.1f,-1);
    	//将跑动的 Animation 取名为 running 
    	AnimationCache::getInstance()->addAnimation(run_animation,"running");
    	
    	/*4------------------载入跳跃过程中上升的动画---------------------------*/
    	frameVector.clear();
    	for(int i = 0; i <= 3; i ++){
    		frame = frameCache->spriteFrameByName(String::createWithFormat("runnerJumpUp%d.png",i)->getCString());
    		frameVector.pushBack(frame);
    	}
    	auto jumpUp_animation = Animation::createWithSpriteFrames(frameVector,0.2);//不设置无限循环
    	AnimationCache::getInstance()->addAnimation(jumpUp_animation,"jumpUp");
    
    	/*------------------载入跳跃过程中下落的动画----------------------------*/
    	frameVector.clear();
    	for(int i = 0; i <= 1; i ++){
    		frame = frameCache->spriteFrameByName(String::createWithFormat("runnerJumpDown%d.png",i)->getCString());
    		frameVector.pushBack(frame);
    	}
    	auto jumpDown_animation = Animation::createWithSpriteFrames(frameVector,0.3);
    	AnimationCache::getInstance()->addAnimation(jumpDown_animation,"jumpDown");
    
    	/*------------------载入下蹲-------------------------------------------*/
    	frameVector.clear();
    	frame = frameCache->spriteFrameByName("runnerCrouch0.png");
    	frameVector.pushBack(frame);
    	auto crouch_animation = Animation::createWithSpriteFrames(frameVector,0.3);//不设置无限循环
    	AnimationCache::getInstance()->addAnimation(crouch_animation,"crouch");
    
    }
    加入Jump,Crouch函数,以及update函数:

    void Jump();
    
    void Crouch();
    
    virtual void update(float dt);
    实现:

    void Runner::Jump(){
    	//仅仅有在跑动时才干起跳
    	if(m_state == running){
    		m_state = jumpUp;
    		
    		auto mass = this->getPhysicsBody()->getMass()*150;// 力大小
    
    		this->getPhysicsBody()->applyImpulse(Vect(0,mass));
    
    	    m_runner->stopAllActions();
    
    	    doAction("jumpUp");
    	}
    }
    
    void Runner::update(float dt){
    	auto vel = this->getPhysicsBody()->getVelocity();
    	if(m_state == jumpUp){
    		if(vel.y < 0.1){
    			m_state = jumpDown;
    			m_runner->stopAllActions();
    			doAction("jumpDown");
    		}
    	}
    
    	if(m_state == jumpDown){
    		CCLOG("%f",vel.y);
    		//不应该是 等于 0
    		if(vel.y > 0){
    			m_state = running;
    			m_runner->stopAllActions();
    			doAction("running");
    		}
    	}
    }
    
    void Runner::Crouch(){
    	//仅仅能在跑动的时候蹲下
    	if(m_state == running){
    		m_state = crouch;
    		m_runner->stopAllActions();
    		initBody();
    		doAction("crouch");
    	}
    }

    这里的Jump 我们就给主角一个向上的力,而且这个力是瞬时力,这样主角就会上升,可是加速度向下,慢慢到达最高点然后 因为重力而下落;

    这里的update函数用来做这个事: 当主角向上跳到最高点的时候,就应该下落,切换下落状态,运行下落帧动画,这里是借鉴了前辈的,首先在JumpUp状态下,假设y速度小于 0.1 那么我们觉得它到了最高点,切换下落。在JumpDown状态下,y速度大于0,我们就觉得它到达了地面,切换跑动状态。 前辈的推断中是 vel.y == 0 过程中我调试了,由于速度是float,== 0这样的推断非常不精确,然后我的主角就一直处于下落的那个动作状态啦。。。。。

    Ok到这里,我们主角的动作都准备好了,以下就開始加入 button,来控制主角运行这些动作啦!!


    个人愚昧观点,欢迎指正与讨论大笑(好像也没人会和我讨论,,哎睡觉)

  • 相关阅读:
    docker 删除所有的 docker ps -a 记录
    使用ES6的Promise完美解决回调地狱
    linux查看历史命令history
    linux命令补全 忘记命令只记得开头
    linux更改shell
    java信号量PV操作 解决生产者-消费者问题
    eclipse代码自动提示功能设置
    linux下mysql修改数据库账户root密码
    IntelliJ Idea12 破解码与中文乱码配置
    linux usermod修改用户所在组方法
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4265306.html
Copyright © 2020-2023  润新知