Cocos2d-android游戏引擎

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/axi295309066/article/details/53169104

什么是游戏引擎

游戏引擎是指一些已编写好的可编辑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始。

Cocos2d家族

cocos2d是一个开源的游戏开发框架,利用它可以非常容易的开发2D游戏。 包括以下成员

  • Cocos2d-x
  • Cocos2d-iphone
  • Cocos2d-android

本质区别:开发的语言不一样:Cocos2d-x使用c++、Cocos2d-iphone使用Object-C;共同点:api名字基本一致

我们为什么要使用cocos2d

  • 一款开源的,跨平台,轻量级的2D游戏引擎。
  • 性能良好
  • 广泛的社区支持
  • 拥护很多成功案例。比如捕鱼达人,三国塔防等
  • 使用MIT授权协议。可以自由使用,修改源码,不需要像GPL一样公开源码,可以商用

架构

cocos

  • 图形引擎Cocos2D Graphic
  • 声音引擎CocosDenshion
  • 物理引擎:Box2d、Chipmunk

cocos

架构说明

  • Cocos2D Graphic图形引擎
  • CocosDenshion Audio声音引擎
  • 物理引擎
    • Box2d
    • Chipmunk
  • Lua脚本库

Box2D是一个用于模拟2D刚体物体的C++引擎。作者为Erin Catto。
chipmunk本是一个独立的开源项目,用纯c编写

Lua 是一个小巧的脚本语言。是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。

图形引擎Cocos2D Graphic

CCDirector界面的统一管理者

cocos

图形引擎说明

cocos

  • CCDirector(导演):引擎的控制者,控制场景的切换,游戏引擎属性的设置
  • CCScene (场景):场景类,例如游戏的闪屏,主菜单,游戏主界面等。
  • CCLayer(布景):图层类,每个图层都有自己的触发事件,该事件只能对其拥有的元素有效,而图层之上的元素所包含的元素,是不受其事件管理的
  • CCSprite(人物):精灵类,界面上显示的最小单元
  • CCNode:引擎中最重要的元素,所有可以被绘制的东西都是派生于此。它可以包含其它CCNode,可以执行定时器操作,可以执行CCAction。
  • CCAction(动作):动作类,如平移、缩放、旋转等动作

CCDirector

CCGLSurfaceView

引擎中SurfaceView的子类,实现了SurfaceHolder.Callback接口,但并未实现Runnable接口。
存在问题:
1、绘制界面的线程是谁?
2、该线程是如何启动的?

CCDirector的作用

界面的绘制工作是由GLThread来完成,而GLThread的开启是在CCDirector的attachInView方法中完成的。
管理场景CCScene

CCDirector,导演类,负责管理和切换场景。还负责初始化openGL各项参数。
CCDirector引擎的控制者,控制场景的切换,游戏引擎属性的设置

单例模式,sharedDirector()取得对象

方法 功能描述
sharedDirector() 获取CCDirector对象,单例模式
attachInView() 连接OpenGL的SurfaceView
runWithScene() 运行场景
replaceScene() 替换场景
setDeviceOrientation() 设置横屏竖屏
setDisplayFPS(true) 显示fps帧率
setAnimationInterval(1.0f / 60) 设置帧率,每秒刷新60次
setScreenSize(480, 320) 设置屏幕分辨率,高于设置的分辨率时,引擎会自动适配
resume() 进入运行状态
pause() 暂停
end() 结束


public class MainActivity extends Activity {

    private CCDirector director;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        CCGLSurfaceView surfaceView=new CCGLSurfaceView(this);

        setContentView(surfaceView);
        //  程序只能有一个导演
        director = CCDirector.sharedDirector();
        director.attachInView(surfaceView);// 开启线程

        director.setDeviceOrientation(CCDirector.kCCDeviceOrientationLandscapeLeft);// 设置游戏方向 水平
        director.setDisplayFPS(true);//是否展示帧率
    //  director.setAnimationInterval(1.0f/30);// 锁定帧率  指定一个帧率  向下锁定 
        director.setScreenSize(480, 320);//设置屏幕的大小   可以自动屏幕适配 

        CCScene ccScene=CCScene.node();// 为了api 和cocos-iphone 一致 
        ccScene.addChild(new ActionLayer());//场景添加了图层 
        director.runWithScene(ccScene);//  运行场景

    }
    @Override
    protected void onResume() {
        super.onResume();
        director.resume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        director.onPause();
        //director.pause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        director.end();// 游戏结束了
    }

}

FirstLayer

public class FirstLayer extends CCLayer {
    private CCSprite ccSprite;


    public  FirstLayer() {
        setIsTouchEnabled(true);// 打开触摸事件开关
        init();
    }
    // 按下的事件 
    @Override
    public boolean ccTouchesBegan(MotionEvent event) {
        //  先把android坐标系中的点 转换成 cocos2d坐标系中的点
        CGPoint convertTouchToNodeSpace = this.convertTouchToNodeSpace(event);
        System.out.println("我被按下了");
        CGRect boundingBox = ccSprite.getBoundingBox(); // 获取精灵的矩形
        // 判断点是否在矩形之中 
        //  参数1  矩形  参数2 点 
        boolean containsPoint = CGRect.containsPoint(boundingBox, convertTouchToNodeSpace);
        if(containsPoint){
            ccSprite.setScale(ccSprite.getScale()+0.2);
        }else{
            ccSprite.setScale(ccSprite.getScale()-0.2);
        }
        //this.getChildByTag(10); 根据Tag标签 找对应的孩子
        return super.ccTouchesBegan(event);
    }


    private void init() {
        CCSprite bg = CCSprite.sprite("bbg_arena.jpg");
        bg.setAnchorPoint(0, 0);
        this.addChild(bg,0);  // 如果第二个参数越大  默认显示的越靠上面, 如果一样大  谁先添加谁显示在下面


        ccSprite = CCSprite.sprite("z_1_attack_01.png");
        ccSprite.setAnchorPoint(0,0);// 设置锚点
        ccSprite.setPosition(100, 100);//设置坐标
        ccSprite.setScale(1); // 设置缩放
        //ccSprite.setFlipY(true);// X水平翻转  Y垂直翻转
        //ccSprite.setOpacity(0);//设置不透明度 值越大 越不透明  0-255
        ccSprite.setVisible(true);// 设置不可显示
        //ccSprite.
        // 把精灵添加到图层上 
        this.addChild(ccSprite);
    //  this.addChild(ccSprite, z);  // 优先级 
        this.addChild(ccSprite, 1, 10);//  参数3 标签 
    }
}

ActionLayer

public class ActionLayer extends CCLayer {
    public ActionLayer(){
        init();
    }

    private void init() {
    //  moveTo();
    //  moveBy();
    JumpBy();
        //scaleBy();
        //rotateBy();
        //rotateTo();
        //bezierBy();
        //fadeIn();
        //ease();  //和加速度有关系的动作
        //tint();
        //blink();
    }

    private void blink() {
        // 三秒钟闪烁3次
        CCBlink blink=CCBlink.action(3, 3);
        getSprite().runAction(blink);
    }

    private void tint() {
        // 专门显示文字的精灵 
        //  参数1  显示的内容 参数2 字体的样式  3 字体的大小
        CCLabel label=CCLabel.labelWithString("那些年,我们在黑马的苦逼日子", "hkbd.ttf", 24);
        label.setColor(ccc3(50, 0, 255));
        label.setPosition(200,200);
        this.addChild(label);

        ccColor3B c=ccc3(100, 255, -100);
        // 参数1 时间 参数2 变化后的颜色 
        CCTintBy by=CCTintBy.action(1, c);
        CCTintBy reverse = by.reverse();
        CCSequence actions = CCSequence.actions(by, reverse);
        CCRepeatForever forever=CCRepeatForever.action(actions);
        label.runAction(forever);
    }

    private void ease() {
        CCMoveTo ccMoveTo=CCMoveTo.action(10, CCNode.ccp(200, 0));
        CCEaseIn easeOut=CCEaseIn.action(ccMoveTo,9); // 让移动按照有一定加速度去移动
        getSprite().runAction(easeOut);

    }

    private void fadeIn() {
        CCFadeIn fadeIn=CCFadeIn.action(10);
        getSprite().runAction(fadeIn);


    }

    private void bezierBy() {
        CCBezierConfig c=new CCBezierConfig();
        c.controlPoint_1=ccp(0, 0);
        c.controlPoint_2=ccp(100, 100);
        c.endPosition=ccp(200, 0);

        CCBezierBy bezierBy=CCBezierBy.action(2, c);
        getSprite().runAction(bezierBy);
    }

    private void rotateTo() {
        CCSprite heart = getHeart();
        heart.setPosition(200, 100);
        CCRotateTo rotateTo=CCRotateTo.action(3, 240);  //偷懒的做法
        heart.runAction(rotateTo);
    }

    private void rotateBy() {
        // 参数2  旋转的角度
        CCRotateBy by=CCRotateBy.action(3, 240);
        getHeart().runAction(by);
    }

    private void scaleBy() {
        // 参数1 时间 参数2 缩放的比例
        CCScaleBy ccScaleBy=CCScaleBy.action(1f, 0.65f);   //基于锚点进行缩放
        CCScaleBy reverse = ccScaleBy.reverse();
        CCSequence sequence=CCSequence.actions(ccScaleBy, reverse);
        CCRepeatForever forever=CCRepeatForever.action(sequence);
        getHeart().runAction(forever);
    }

    private void JumpBy() {
        // 1 时间  单位秒 2 目的地   3 高出的高度  4 跳跃的次数
        CCJumpBy ccJumpBy=CCJumpBy.action(4, ccp(200, 100), 100, 2);
        CCRotateBy ccRotateBy=CCRotateBy.action(2, 360);
        // 并行动作
        CCSpawn ccSpawn=CCSpawn.actions(ccJumpBy, ccRotateBy);//并行起来了   跳跃的过程中伴随着旋转

        //CCJumpBy reverse = ccJumpBy.reverse();
        CCSequence sequence=CCSequence.actions(ccSpawn, ccSpawn.reverse());// 跳上去 跳回来(伴随着旋转) 
        CCRepeatForever forever=CCRepeatForever.action(sequence);// 让串行动作 永不停止循环了
        CCSprite sprite = getSprite();
        sprite.setAnchorPoint(0.5f, 0.5f);  
        sprite.setPosition(50, 50);
        sprite.runAction(forever);
    }

    private void moveBy() {
        CCSprite sprite = getSprite();
        sprite.setPosition(0, 100);
        // 参数1  移动的时间 单位秒  参数2  坐标的改变  
        CCMoveBy ccMoveBy=CCMoveBy.action(2, CCNode.ccp(200, 0)); // 
        CCMoveBy reverse = ccMoveBy.reverse();
        CCSequence sequence=CCSequence.actions(ccMoveBy, reverse);//CCSequence 串行动作  

        sprite.runAction(sequence);
    }

    public void moveTo() {
        CCSprite sprite = getSprite();

        // 参数1  移动的时间 单位秒  参数2  移动的目的地
        CCMoveTo ccMoveTo=CCMoveTo.action(2, CCNode.ccp(200, 0));
        CCIntervalAction reverse = ccMoveTo.reverse();
        CCSequence sequence=CCSequence.actions(ccMoveTo, reverse);//CCSequence 串行动作  
        sprite.runAction(sequence);
    }

    public CCSprite getSprite() {
        CCSprite sprite=CCSprite.sprite("z_1_attack_01.png");
        sprite.setAnchorPoint(0,0);

        this.addChild(sprite);
        return sprite;
    }

    public CCSprite getHeart() {
        CCSprite sprite=CCSprite.sprite("heart.png");
        sprite.setPosition(100, 100);
        this.addChild(sprite);
        return sprite;
    }
}

CCAction

对于一个游戏来说,动作是非常重要的,好的动作可以使游戏的可玩性大大提高,在cocos2d引擎中有一个动作类,CCAction是动作类的基类,动作是定义在节点(CCNode)上的,以节点为目标,主要分为两类瞬时动作和延时动作

CCAction

基本动作
Cocos2d提供的基本动作:瞬时动作、延时动作、运作速度。

1、瞬时动作:就是不需要时间,马上就完成的动作。瞬时动作的共同基类是 InstantAction。
Cocos2d提供以下瞬时动作:

放置 – Place
效果类似于 node.Position = ccp(x, y)。之所以作为一个动作来实现是为了可以与其他动作形成一个连续动作。

隐藏 – Hide
效果类似于 [node setVisible:NO]. 之所以作为一个劢作来实现是为了可以与其他动作形成一个连续动作。

显示 – Show
效果类似于 [node setVisible:YES]. 之所以作为一个动作来实现是为了可以与其他动作形成一个连续动作。

可见切换 – ToggleVisibility

2.延时动作

延时动作就是指动作的完成需要一定时间。因此actionWithDuration 是延时动作执行时的第一个参数,延时动作的共同基类是 CCIntervalAction(包含了组合动作类)。

Cocos2d提供以下瞬时动作(函数命名规则是:XxxxTo: 意味着运动到指定的位置, XxxxBy:意味着运动到按照指定的 x、y 增量的位置。[x、y 可以是负值]):

移动到 – CCMoveTo
移动– CCMoveBy
跳跃到 – CCJumpTo 设置终点位置和跳跃的高度和次数。
跳跃 – CCJumpBy 设置终点位置和跳跃的高度和次数。
贝塞尔 – CCBezierBy 支持 3 次贝塞尔曲线:P0-起点,P1-起点切线方向,P2-终点切线方向,P3-终点。
放大到 – CCScaleTo 设置放大倍数,是浮点型。
放大 – CCScaleBy
旋转到 – CCRotateTo
旋转 – CCRotateBy
闪烁 – CCBlink 设定闪烁次数
色调变化到 – CCTintTo
色调变换 – CCTintBy
变暗到 – CCFadeTo
由无变亮 – CCFadeIn
由亮变无 – CCFadeOut

3.组合动作

按照一定的次序将上述基本动作组合起来,形成连贯的一套组合动作。组合动作包括以下几类:
序列 – CCSequence
Sequence 的使用非常简单,该类也从 CCIntervalAction 派生,本身就可以被 CocosNode 对象执行。该类的作用就是线序排列若干个动作,然后按先后次序逐个执行。
同步 – Spawn
Spawn 的使用非常简单,该类也从 IntervalAction 派生,本身就可以被CocosNode 对象执行。该类的作用就是同时并列执行若干个动作,但要求动作都必须是可以同时执行的。比如:移动式翻转、变色、变大小等。
需要特别注意的是,同步执行最后的完成时间由基本动作中用时最大者决定。
重复有线次数 – Repeate
重复有限次数的动作,该类也从 IntervalAction 派生,可以被 CocosNode 对象执行。
反动作 – Reverse
反动作就是反向(逆向)执行某个动作,支持针对动作序列的反动作序列。反动作不是一个专门的类,而是 CCFiniteAction 引入的一个接口。不是所有的类都支持反动作,XxxxTo 类通常不支持反动作,XxxxBy 类通常支持。
动画 – Animation
动画就是让精灵自身连续执行一段影像,形成模拟运动的效果:行走时的精灵状态、打斗时的状态等。
无限重复 – RepeatForever
RepeatForever 是从 Action 类直接派生的,因此无法参与序列和同步;自身也无法反向执行。该类的作用就是无限期执行某个动作或动作序列,直到被停止。

4.速度变化

基本动作和组合动作实现了针对精灵的各种运动、动画效果的改变,但这样的改变的速度是不变的,通过 CCEaseAction 为基类的类系和 CCSpped 类我们可以很方便的修改精灵执行劢作的速度:由快至慢还是由慢至快。
EaseIn 由慢至快。
EaseOut 由快至慢
EaseInOut 由慢至快再由快至慢。
EaseSineIn
由慢至快。
EaseSineOut 由快至慢
EaseSineInOut 由慢至快再由快至慢。
EaseExponentialIn 由慢至极快。
EaseExponentialOut 由极快至慢。
EaseExponentialInOut 由慢至极快再由极快至慢。
Speed 人工设定速度,还可通过 SetSpeed 不断调整。
5.扩展动作
延时动作 – Delay ,比如在动作序列中增加一个时间间歇
函数调用
函数在动作序列中间或者结束调用某个函数,执行任何需要执行的任务:动作、状态修改等。id acf = [CCCallFunc actionWithTarget:self selector:@selector(CallBack1)];对应的函数为:- (void) CallBack1 {
[sprite runAction:[CCTintBy actionWithDuration:0.5 red:255 green:0 blue:255]]; }
带对象参数–调用自定义函数时,传递当前对象。id acf = [CallFuncN actionWithTarget:self selector:@selector(CallBack2:)];对应的自定义函数:(这里,我们直接使用了该对象)

  • (void) CallBack2:(id)sender {
    [sender runAction:[CCTintBy actionWithDuration:1 red:255 green:0 blue:255]]; }
    带 对象、数据参数–用自定义函数时,传递当前对象和一个常量(也可以是指针)。id acf = [CCCallFuncND actionWithTarget:self selector:@selector(CallBack3:data:) data:(void*)2];对应的自定义函数,我们使用了传递的对象和数据:
    -(void) CallBack3:(id)sender data:(void*)data {
    [sender runAction:[CCTintBy actionWithDuration:(NSInteger)data red:255 green:0 blue:255]]; }

游戏地图制作

工具: Tiled绘图工具
图层:展示整体效果
块层:依据块划分图片后,整张图片会变成一个块层
块:块层中的一个单元
对象层:单独一层,放置一些指定的对象

地图制作,使用Tiled 制作地图。地图大小的宽度表示地图的一行有14 块组成,地图大小的高度表示地图一列有6 块组成,块大小的宽度表示每块的宽度为46px,块大小的高度表示每块的高度为53px。

新建地图文件,如下图1,生成的地图如下图2

游戏地图

游戏地图

接着将下图3中标红的图片拖入Tiled 的图层中。在下图4中直接点击确定

这里写图片描述

这里写图片描述

在图2.5 中选择一块草地点击,将鼠标移动到新建的地图中点击鼠标左键安放草块,如图2.6。

这里写图片描述

这里写图片描述

在图层中选择一块道路点击,如图2.7,将鼠标移动到新建的地图中点击鼠标左键安放道路,做出一条九曲十八弯的小路,如图2.8。

这里写图片描述

这里写图片描述

设置拐点。先添加一个对象层,如图2.9。然后在工具栏点击添加对象,如图2.10,最后在地图上的拐点处单击鼠标左键,如图2.11。

这里写图片描述

这里写图片描述

这里写图片描述

步骤:
1、新建地图,设置地图大小(以块为单位),设置块大小(以像素为单位)
2、显示网格需要设置视图中的显示网格选项
3、通过地图—新图块,来导入地图资源,从而利用工具进行地图的编辑
4、对象层,通过在图层里右键添加。

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="14" height="6" tilewidth="46" tileheight="54">
 <tileset firstgid="1" name="bk1" tilewidth="46" tileheight="54">
  <image source="bk1.jpg" width="678" height="320"/>
 </tileset>
 <layer name="block" width="14" height="6">
  <data encoding="base64" compression="zlib">
   eJwTY2BgECMDW6BhQuK4zCDEprY+YtxMyBx8GADLYgpH
  </data>
 </layer>
 <objectgroup name="road" width="14" height="6">
  <object x="22" y="80"/>
  <object x="160" y="82"/>
  <object x="161" y="244"/>
  <object x="299" y="243"/>
  <object x="298" y="82"/>
  <object x="436" y="83"/>
  <object x="436" y="246"/>
  <object x="620" y="246"/>
 </objectgroup>
</map>

生成的tmx文件说明:
1、Image source属性中填写相对路径
2、层和对象命名尽量使用英文
3、关于对象层中信息,封装在objectgroup中
4、objectgroup中信息按照操作顺序进行排列object

游戏地图加载

加载:CCTMXTiledMap.tiledMap(name);
添加到当前显示层,存在问题:
无法进行图片的移动
用户的touch事件处理:
setIsTouchEnabled(true);
CCTMXTiledMap.touchMove(MotionEvent event, CCTMXTiledMap tiledMap);
存在问题:地图移动
获取图片大小,设置图片位置为宽高的一半
设置锚点为0.5,0.5

public class DemoLayer extends CCLayer {
    private CCTMXTiledMap map;
    private List<CGPoint> roadPoits;

    public DemoLayer() {
        this.setIsTouchEnabled(true);//打开触摸事件的开关
        init();
    }

    private void init() {
        // 加载地图
        loadMap();
        parserMap();
        loadParticle();
        loadZombies();
    }

    private void loadParticle() {
        system = CCParticleSnow.node();
        // 设置雪花的样式
        system.setTexture(CCTextureCache.sharedTextureCache().addImage("f.png"));
        this.addChild(system, 1);       
    }

    int position = 0;
    private CCSprite sprite;// 僵尸
    private CCParticleSystem system;

    // 展示僵尸
    private void loadZombies() {
        sprite = CCSprite.sprite("z_1_01.png");
        sprite.setPosition(roadPoits.get(0));
        sprite.setAnchorPoint(0.5f, 0); // 设置锚点在两腿之间
        sprite.setScale(0.65f);
        sprite.setFlipX(true); // 水平翻转

        map.addChild(sprite);// 通过地图去添加僵尸 // 地图随着手指移动,僵尸也会随着手指移动

        // 序列帧的播放
        ArrayList<CCSpriteFrame> frames = new ArrayList<CCSpriteFrame>();
        String format = "z_1_%02d.png";// 02d 占位符 可以表示两位的整数 如果不足两位前面用0补足
        for (int i = 1; i <= 7; i++) {
            CCSpriteFrame displayedFrame = CCSprite.sprite(
                    String.format(format, i)).displayedFrame();
            frames.add(displayedFrame);
        }

        // 配置序列帧的信息 参数1 动作的名字(给程序员看的) 参数2 每一帧播放的时间 单位秒 参数3 所有用到的帧
        CCAnimation anim = CCAnimation.animation("走路", 0.2f, frames);
        CCAnimate animate = CCAnimate.action(anim);
        // 序列帧动作默认是永不停止的循环
        CCRepeatForever forever = CCRepeatForever.action(animate);
        sprite.runAction(forever);

        moveToNext();
    }
    int speed=40;// 僵尸的速度
    public void moveToNext() {
        position++;
        if (position < roadPoits.size()) {
            CGPoint cgPoint = roadPoits.get(position);
            float t=CGPointUtil.distance(roadPoits.get(position-1), cgPoint)/speed;
            CCMoveTo moveTo = CCMoveTo.action(t, cgPoint);
            // 调用一个对象的某一个方法
            CCSequence ccSequence = CCSequence.actions(moveTo,
                    CCCallFunc.action(this, "moveToNext"));
            sprite.runAction(ccSequence);

        } else {
            //雪停下来
            system.stopSystem();// 停止粒子系统
            sprite.stopAllActions();//停止所有动作    
            //  跳舞 
            dance();
            SoundEngine engine=SoundEngine.sharedEngine();
            // 1 上下文 2. 音乐资源的id  3 是否循环播放
            engine.playSound(CCDirector.theApp, R.raw.psy, true);
        }
    }



    private void dance() {
        sprite.setAnchorPoint(0.5f, 0.5f);
        CCJumpBy ccJumpBy=CCJumpBy.action(2, ccp(-20,10), 10, 2);
        CCRotateBy by=CCRotateBy.action(1, 360);
        CCSpawn ccSpawn=CCSpawn.actions(ccJumpBy, by);
        CCSequence sequence=CCSequence.actions(ccSpawn, ccSpawn.reverse());
        CCRepeatForever forever=CCRepeatForever.action(sequence);
        sprite.runAction(forever);
    }

    // 解析地图
    private void parserMap() {
        roadPoits = new ArrayList<CGPoint>();
        // 解析地图
        CCTMXObjectGroup objectGroupNamed = map.objectGroupNamed("road");
        ArrayList<HashMap<String, String>> objects = objectGroupNamed.objects;
        for (HashMap<String, String> hashMap : objects) {
            int x = Integer.parseInt(hashMap.get("x"));
            int y = Integer.parseInt(hashMap.get("y"));
            CGPoint cgPoint = ccp(x, y);
            roadPoits.add(cgPoint);
        }
    }
    @Override
    public boolean ccTouchesMoved(MotionEvent event) {
        map.touchMove(event, map);// 地图会随着手指的移动而移动  如果该方法生效 必须保证地图的锚点在中间位置
        return super.ccTouchesMoved(event);
    }

    // 加载地图
    private void loadMap() {
        map = CCTMXTiledMap.tiledMap("map.tmx");
        map.setAnchorPoint(0.5f,0.5f);
        // 因为修改了锚点 ,所以坐标也是需要修改的
        map.setPosition(map.getContentSize().width/2,map.getContentSize().height/2);
        this.addChild(map);
    }

    @Override
    public boolean ccTouchesBegan(MotionEvent event) {
        this.onExit(); // 暂停
        this.getParent().addChild(new PauseLayer());// 让场景添加新的图层 
        return super.ccTouchesBegan(event);
    }

    // 专门用来暂停的图层
    private class PauseLayer extends CCLayer{
        private CCSprite heart;
        public PauseLayer(){
            this.setIsTouchEnabled(true);// 打开触摸事件的开关
            heart = CCSprite.sprite("heart.png");
            // 获取屏幕的尺寸
            CGSize winSize = CCDirector.sharedDirector().getWinSize();
            heart.setPosition(winSize.width/2, winSize.height/2);// 让图片再屏幕的中间

            this.addChild(heart);
        }
        // 当点击PauseLayer的时候 
        @Override
        public boolean ccTouchesBegan(MotionEvent event) {
            CGRect boundingBox = heart.getBoundingBox();
            //  把Android坐标系中的点 转换成Cocos2d坐标系中的点 
            CGPoint convertTouchToNodeSpace = this.convertTouchToNodeSpace(event);
            if(CGRect.containsPoint(boundingBox, convertTouchToNodeSpace)){// 确实点击了心


                this.removeSelf();// 回收当前图层
                DemoLayer.this.onEnter();//游戏继续
            }

            return super.ccTouchesBegan(event);
        }
    }
}

粒子系统

什么是粒子系统

粒子系统表示三维计算机图形学中模拟一些特定的模糊现象的技术,而这些现象用其它传统的渲染技术难以实现的真实感的 game physics。经常使用粒子系统模拟的现象有火、爆炸、烟、水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉效果等等。

粒子系统

实现方式:

使用代码设置参数
导入属性列表文件的方式来配置所要添加的粒子系统。

实现步骤:

CCParticleSystem system= CCParticleSnow.node();
system.setTexture(CCTextureCache.sharedTextureCache().addImage("f.png"));
this.addChild(system, 1);

自定义效果:

制作工具ParticleDesigner,使用工具将效果导出成.plist文件

CCParticleSystem ps=CCParticleSystemPoint.particleWithFile("f.plist");
ps.setPosition(0,winSize.height);
addChild(ps);

CocosDenshion Audio声音引擎

SoundEngine处理声音,内部封装的是MediaPlayer和SoundPool
声音类型:音乐和音效
可以从长短上来做区分,音乐一般用于游戏的背景声音,音效主要是短小的声音,如植物发射子弹,僵尸吃植物时发出的声音
声音控制,如播放、暂停、声音大小调节、静音
通过缓存音乐和音效文件来提高声音处理的效率

SoundEngine engine=SoundEngine.sharedEngine();
// 1 上下文 2. 音乐资源的id  3 是否循环播放
engine.playSound(CCDirector.theApp, R.raw.psy, true);

游戏暂停处理

处理游戏暂停思路
当前的主CCLayer处于暂停状态,处于暂停状态的CCLayer无法接收到用户的触摸事件
在主CCLayer暂停之前需要启动另外一个CCLayer显示,除提示玩家游戏已经暂停外,如果玩家需要切换到游戏界面需要点击当前的CCLayer中的按钮完成继续游戏的处理。
注意:
1、该暂停用CCLayer必须添加到与主CCLayer相同的parent下,不能再主CCLayer继续添加
2、点击完成时需要清除当前显示的CCLayer
核心方法:onEnter()——游戏继续
onExit——游戏暂停

//处理游戏暂停
//使用到的方法:CCLayer中的onEnter和onExit

@Override
public boolean ccTouchesEnded(MotionEvent event) {
PauseLayer pauseLayer=new PauseLayer();
this.getParent().addChild(pauseLayer);
onExit();
return super.ccTouchesEnded(event);
}

private class PauseLayer extends CCLayer
{
CCSprite sprite ;
public PauseLayer() {
setIsTouchEnabled(true);
sprite = CCSprite.sprite("ZombiesWon.jpg");
sprite.setScale(0.3);
sprite.setPosition(240, 160);
this.addChild(sprite);
}
@Override
public boolean ccTouchesEnded(MotionEvent event) {
if (isClick(event, sprite)) {
MyDemoLayer.this.onEnter();
this.removeSelf();
}
return true;
}
}

protected boolean isClick(MotionEvent event,CCNode sprite)
{
CGPoint clickPoint = this.convertTouchToNodeSpace(event);
return CGRect.containsPoint(sprite.getBoundingBox(), clickPoint);
}

没有更多推荐了,返回首页