今天介绍两个比较简单的类
GameBegin.h
LandLayer.h
需要注意的有两点,一个是草地的滚动,还有一个是物理模型,都在LandLayer.h中实现,分析都在代码注释中。
先上GameBegin场景的效果图
这张图可以解析为
背景图的添加
游戏名字
小鸟以及小鸟飞行动画
按钮
草地(草地是会滚动的)
//GameBegin.h
#pragma once
#include "cocos2d.h"
class GameBegin:public cocos2d::Layer
{
public:
GameBegin();
~GameBegin();
static cocos2d::Scene * createScene();
bool init();
void landMove(float);
void startGame();
CREATE_FUNC(GameBegin);
private:
cocos2d::Sprite * land1;
cocos2d::Sprite * land2;
};
//GameBegin.cpp
#include "GameBegin.h"
#include "define.h"
#include "GameLayer.h"
USING_NS_CC;
GameBegin::GameBegin()
{
}
GameBegin::~GameBegin()
{
}
cocos2d::Scene * GameBegin::createScene()
{
auto scene=Scene::create();
auto gameLayer=GameBegin::create();
scene->addChild(gameLayer);
return scene;
}
bool GameBegin::init()
{
if (!Layer::init())
{
return false;
}
//获取 OpenGL 视图的初始化时的可见大小
auto origin=Director::getInstance()->getVisibleOrigin();
auto visibleSize=Director::getInstance()->getVisibleSize();
//背景图片,根据时间加载晚上和白天的图片,这个功能是来自原作者
time_t t=time(NULL);
tm * lt=localtime(&t);
int hour=lt->tm_hour;
Sprite * bg;
if (hour>=6&&hour<=17)
{
bg=Sprite::createWithSpriteFrameName("bg_day.png");
}
else
{
bg=Sprite::createWithSpriteFrameName("bg_night.png");
}
bg->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2));
this->addChild(bg);
//游戏草坪的移动,这边的草地移动是没有物理模型的
//所有的草地移动都在LandLayer类中介绍,这里不介绍了
//这个类和LandLayer类是没有任何联系的,这里的草地移动和那边的草地移动也是不一样的
//至于为什么不直接调用那个类,只能怪我刚开始写的时候没有策划好
//那个LandLayer类是后面补上去给,别的类使用的,所以这边没有改
land1=Sprite::createWithSpriteFrameName("land.png");
land1->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
land1->setPosition(Point::ZERO);
land1->getTexture()->setAliasTexParameters();
this->addChild(land1);
land2=Sprite::createWithSpriteFrameName("land.png");
land2->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
land2->setPosition(Point(origin.x+land1->getPositionX()+land1->getContentSize().width-2,origin.y));
land2->getTexture()->setAliasTexParameters();
this->addChild(land2);
this->schedule(schedule_selector(GameBegin::landMove),LAND_VELOCITY);
//游戏名字
auto title=Sprite::createWithSpriteFrameName("title.png");
title->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height*0.8));
this->addChild(title);
//小鸟
auto bird=Sprite::createWithSpriteFrameName("bird0_0.png");
bird->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height*0.65));
<span style="white-space:pre"> </span>//小鸟的动画就是我们存在缓存中的,今天拿来用
bird->runAction(RepeatForever::create(Animate::create(AnimationCache::getInstance()->getAnimation(BIRDANIMATION_0))));
this->addChild(bird);
//开始按钮
auto start_sprite=Sprite::createWithSpriteFrameName("button_play.png");
//按钮这里一共有2中状态,一是弹起状态
//二是按下状态,下面的第一个参数和第二个参数就表示这两中状态
//第三个参数就是按钮的回调函数
auto start_button=MenuItemSprite::create(start_sprite,start_sprite,CC_CALLBACK_0(GameBegin::startGame,this));
start_button->setPosition(Point(origin.x+visibleSize.width/2,origin.y+visibleSize.height*0.5));
//这个是按钮菜单
auto menu=Menu::create(start_button,NULL);
menu->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT);
menu->setPosition(Point::ZERO);
this->addChild(menu);
return true;
}
void GameBegin::landMove(float)
{
land1->setPositionX(land1->getPositionX()-2);
land2->setPositionX(land1->getPositionX()+land1->getContentSize().width-2);
if (land2->getPositionX()==0)
{
land1->setPositionX(0);
}
}
//按钮回调
void GameBegin::startGame()
{
//场景切换
Director::getInstance()->replaceScene(TransitionFade::create(CHANGESCENE_TIME,GameLayer::createScene()));
log("replaceScene");
}
//LandLayer.h
#pragma once
#include "cocos2d.h"
class LandLayer:public cocos2d::Layer
{
public:
LandLayer();
~LandLayer();
bool init();
//草地移动
void landMove(float);
//草地停止移动
void stopLand();
CREATE_FUNC(LandLayer);
private:
//草地精灵1
cocos2d::Sprite * land1;
//草地精灵2
cocos2d::Sprite * land2;
};
//LandLayer.cpp
#include "LandLayer.h"
#include "define.h"
USING_NS_CC;
LandLayer::LandLayer()
{
}
LandLayer::~LandLayer()
{
}
bool LandLayer::init()
{
if (!Layer::init())
{
return false;
}
auto origin=Director::getInstance()->getVisibleOrigin();
auto visibleSize=Director::getInstance()->getVisibleSize();
//游戏草坪的移动
land1=Sprite::createWithSpriteFrameName("land.png");
land1->setPosition(Point(origin.x+land1->getContentSize().width/2,origin.y+land1->getContentSize().height/2));
//下面这个接口是防止两个精灵叠加时出现黑边
land1->getTexture()->setAliasTexParameters();
//下面是草地的物理模型
//因为猪脚在飞的过程中会撞到两种东西
//一是管子
//二就是草地
//所以我们要给草地添加物理模型,刚开始写的时候我是没有接触过物理模型
//所以翻了很多资料,包括原作者的,百度的,研究了好长时间
//现在也就懂了点皮毛
//创造一个物理body,是不是应该叫刚体
auto body1=PhysicsBody::create();
//给body一个框架(外壳???),这里我们就是草地的对应的长方形
auto shape_1=PhysicsShapeBox::create(land1->getContentSize());
//把这个外壳给那个物理body
body1->addShape(shape_1);
//把刚体设为静态的
//如果是动态刚体,它会受到力的作用
//如果用另个刚体碰撞它的话,这个动态刚体就会运动或者旋转什么的
//做为草地,它只能是一个安静的美男子......所以我们设为静态的
body1->setDynamic(false);
//这个是把重力取消掉,草地时没有重力的
body1->setGravityEnable(false);
//下面三个函数很复杂,我也是不怎么懂,网上的资料也不多
//就是说要添加上去,貌似是碰撞检测要用到的
body1->setCategoryBitmask(1);
body1->setCollisionBitmask(-1);
body1->setContactTestBitmask(-1);
//下面的叫线性阻尼,我把它理解成摩擦力吧
body1->setLinearDamping(0.7f);
//把刚体付给草地
land1->setPhysicsBody(body1);
this->addChild(land1,2);
land2=Sprite::createWithSpriteFrameName("land.png");
//把草地2接在草地1的后面,这边减去2个像素,是为了防止移动过程出现黑边
//因为,我们每移动一次的像素就是2
land2->setPosition(Point(origin.x+land1->getPositionX()+land1->getContentSize().width-2,land1->getPositionY()));
land2->getTexture()->setAliasTexParameters();
auto body2=PhysicsBody::create();
auto shape_2=PhysicsShapeBox::create(land1->getContentSize());
body2->addShape(shape_2);
body2->setDynamic(false);
body2->setGravityEnable(false);
body2->setCategoryBitmask(1);
body2->setCollisionBitmask(-1);
body2->setContactTestBitmask(-1);
body2->setLinearDamping(0.7f);
land2->setPhysicsBody(body2);
this->addChild(land2,2);
this->schedule(schedule_selector(LandLayer::landMove),LAND_VELOCITY);
return true;
}
//草地滚动的实现
//如何实现草地滚动,在上面我们实例了两个草地精灵
//并且这两个草地的首尾接在了一起(具体看他们坐标X,草地2是接在草地1后面的)
//在定时器运行过程中,每执行一次函数,草地1和草地2的X坐标就减去2
//并且检测草地2的坐标有没有超过限定值(这里就是草地1起始的坐标值)
//如果超过,就重置两个草地的坐标
void LandLayer::landMove( float )
{
land1->setPositionX(land1->getPositionX()-2);
land2->setPositionX(land1->getPositionX()+land1->getContentSize().width-2);
if (land2->getPositionX()==land2->getContentSize().width/2)
{
land1->setPositionX(land2->getContentSize().width/2);
}
}
//草地停止移动,以后要用到
void LandLayer::stopLand()
{
this->unschedule(schedule_selector(LandLayer::landMove));
}