Cocos2d-android是Cocos2dx家族中的一员,优点是使用Java语言进行游戏代码的编写,不像Cocos2dx需要使用C++ 、Lua,方便安卓程序员上手。缺点也显而易见,Cocos2dx本身使用C++开发的,Cocos2dx-android相当于做了一次Java到C的本地调用封装,因此执行效率上肯定会比较差。
作为快速上手文章(get start),使用一个小案例来演示一下Cocos2d-android的基本用法。

开发环境:Eclipse + SDK17
需要导入Cocos2d-android的相关jar文件。CSDN上有一个联接可以下载:点击下载
案例的资源文件涉及几张图片和音乐与音效文件,可以通过下载案例的源代码去使用。
案例的效果如图所示:

屏幕左侧会有一个“忍者”,从屏幕右侧会跑出许多“敌人”向屏幕左侧移动。忍者发射飞镖射击敌人。如果忍者击毙了30个敌人则游戏成功结束,如果有敌人一直跑到屏幕左侧都没有被飞镖打死,则游戏结束。
接下来我们就使用Cocos2d-android来开发这个小游戏。
使用Cocos2d-android开发游戏,主要分为以下几个步骤:
1. Cocos2d-android的一些全局初始化
2. 场景的搭建
3. 事件的处理
4. 音乐、音效
5. 场景的切换

step1 创建安卓项目
step2 在MainActivity的onCreate方法中完成Cocos2d-android的初始化。

protected CCGLSurfaceView _glSurfaceView;
public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestwindowFeature(Window.FEATURE_NO_TITLE);
        getwindow().setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getwindow().setFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        _glSurfaceView = new CCGLSurfaceView(this);
        setContentView(_glSurfaceView);
    }

这段代码中绝大部分都是使用的android原生代码。设定MainActivity界面不显示TitleBar,完全全屏且保持亮度。比较不一样的代码是声明了一个属性_glSurfaceView,属性类型为CCGLSurfaceView,CC前缀代表这是一个Cocos2d-android中的类型,该类继承自安卓的GLSurfaceView。通过调用构造器创建了_glSurfaceView将其传入了setContentView方法中。因此MainActivity连布局文件都不需要了。
step3 在MainActivity的相关生命周期方法中调用Cocos2d-android的相关方法

@Override
    public void onPause()
    {
        super.onPause();

        CCDirector.sharedDirector().pause();
    }

    @Override
    public void onResume()
    {
        super.onResume();

        CCDirector.sharedDirector().resume();
    }

    @Override
    public void onStop()
    {
        super.onStop();

        CCDirector.sharedDirector().end();
    }

这里反复出现了一个CCDirector类,通过sharedDirector方法获取CCDirector的单例对象,并执行相关方法。
CCDirector顾名思义就像一个导演,而它导演的大片就是我们的游戏项目。一部大片都会有很多幕(Scene),我们的游戏项目同样也是由很多幕组成的,每一幕都用一个CCScene对象表示。你也可以将CCScene视为Android中的Activity。Android中,Activity上呈现的是一个一个按一定顺序摆放的视图(View),而在幕中呈现的是一个一个精灵(Sprite)。
Android的普通Activity里,视图要放在一个视图容器(DecoView)中,视图容器再放入Activity里进行呈现。Cocos2d-andriod中,精灵需要放到一个层(Layer)中,再将层放到幕(Scene)中显示。

public void onStart()
    {
        super.onStart();

        CCDirector.sharedDirector().attachInView(_glSurfaceView);

        CCDirector.sharedDirector().setDeviceOrientation(CCDirector.kCCDeviceOrientationLandscapeLeft);

        CCDirector.sharedDirector().setdisplayFPS(true);

        CCDirector.sharedDirector().setAnimationInterval(1.0f / 60.0f);

        CCScene scene = GameLayer.scene();
        CCDirector.sharedDirector().runWithScene(scene);
    }

在Activity的onStart生命周期方法中,CCDirector类继续进行一些常规性的设置,这些都是常规性的代码,包括添加_glSurfaceView,屏幕横屏显示,显示FPS信息,设置刷新率为每秒60次。
下面的两行代码就是涉及到幕(Scene)和层(Layer)了。GameLayer是我们自己写的一个类,在scene方法中完成Layer的创建,Scene的创建,以及把Layer添加到Scene中。然后CCDirector将scene方法的返回值作为游戏的第一个界面显示在屏幕上。
接下来看一下GameLayer类:

public class GameLayer extends CCColorLayer {
    ......
    public static CCScene scene()
    {
        //获取幕(CCScene)对象
        CCScene scene = CCScene.node();
        //创建GameLayer对象
        CCColorLayer layer = new GameLayer(ccColor4B.ccc4(255,255,255));
        //将Layer放到Scene中
        scene.addChild(layer);
        //返回Scene
        return scene;
    }
    //构造器
    protected GameLayer(ccColor4B color)
    {
        super(color);
        //打开触屏事件
        this.setIsTouchEnabled(true);
        //视口大小
        CGSize winSize =
        CCDirector.sharedDirector().displaySize();
        //精灵(忍者)
        CCSprite player = 
        CCSprite.sprite("Player.png");

        //设定忍者精灵在视口中的位置
        player.setPosition(
        CGPoint.ccp(
            player.getContentSize().width / 2.0f,winSize.height / 2.0f));
        //将忍者精灵添加到Layer上
        addChild(player);
        ......
    }
......
}

我们的GameLayer通过继承CCColorLayer而成为一个Layer,可以添加各种的精灵。但Layer不能单独的显示,最终要把Layer放到一个Scene中才可以。
首先看构造方法,构造器需要提供一个颜色作为整个Layer的背景,这是父类CCColorLayer所要求的。

super(color);

然后允许Layer可触摸。这样一旦手指在Layer上产生触摸,会触发Layer的相应回调方法。

this.setIsTouchEnabled(true);

接下来获取显示区域的大小:

CGSize winSize = CCDirector.sharedDirector().displaySize();

创建一个精灵:

CCSprite player = CCSprite.sprite("Player.png");

该精灵的样子就是Player.png,而Player.png需要放在我们安卓项目的assets文件夹下:

这些图片都将是精灵的形象。Player是忍者,Target是敌人,Projectile是忍者发射的飞镖,fps_images是用来显示帧数(FPS)信息的。需要注意的是,根据下载或导入的Cocos2d-android的来源不同,有的Cocos2d-android中已经包含了fps_images图片了,就不需要额外导入了。
有了精灵后接下来就需要设置精灵的位置:

player.setPosition(
    CGPoint.ccp(
        player.getContentSize().width / 2.0f,winSize.height / 2.0f));

这里需要注意两点:
1. Cocos2d中有自己一套坐标系,该坐标系的原点为左下角,这与安卓中默认的坐标系不一样,安卓中的坐标系原点为左上角。Cocos2d-android利用CGPoint工具类进行Cocos2d坐标系下坐标的生成。
2. 调用精灵的setPosition方法时指定的坐标点位置所对应的是精灵的中心位置。

所以,如果要让精灵恰好贴在屏幕的左边缘时,横坐标不能指定为0,而是要指定为精灵宽度的一半。为了让精灵在屏幕上垂直居中显示,将纵坐标指定为整个可显示区域的一半。

最后将已经生成好的精灵添加到Layer中

addChild(player);

这样Layer的构造器就算完成了,在创建Layer对象的时候我们还设置了Layer的背景并添加了一个精灵。
接下来再看静态的scene方法:

public static CCScene scene()
    {
        CCScene scene = CCScene.node();
        CCColorLayer layer = 
            new GameLayer(ccColor4B.ccc4(
                255,255));

        scene.addChild(layer);

        return scene;
    }

因为Layer不可以单独显示,所以scene方法就是创建Scene对象,通过调用GameLayer的构造器创建Layer对象后放到Scene中,并将该Scene对象作为方法的返回值返回。
现在运行程序后,应该在手机屏幕上显示如下内容:

屏幕强制以横屏方式显示,白色背景,左下角显示的是FPS帧数,忍者精灵靠屏幕左侧居中显示。
接下来就用已经掌握的知识来添加更多的精灵,这一次添加敌人精灵。
在GameLayer的构造器已有代码的最后添加这样一行代码:

this.schedule("gameLogic",1.0f);

该代码的作用就是利用计时器(Timer),每间隔1秒钟执行一次gameLogic方法。
接下来在GameLayer中添加gameLogic方法:

public void gameLogic(float dt)
    {
        addTarget();
    }

gameLogic回调方法必须有一个float类型的参数,该参数的值为本次回调距离上一次该方法被回调时的时间间隔是多少。所以对于gameLogic方法来说,每一次被调用时dt参数的值应该都是在1左右。
接下来看一下addTarget方法:

protected void addTarget()
{
        Random rand = new Random();
        //添加精灵
        CCSprite target =
        CCSprite.sprite("Target.png");
        CGSize winSize = 
        CCDirector.sharedDirector().displaySize();
        int minY = (int)(target.getContentSize().height / 2.0f);
        int maxY = (int)(winSize.height - target.getContentSize().height / 2.0f);
        int rangeY = maxY - minY;
        int actualY = rand.nextInt(rangeY) + minY;
        target.setPosition(winSize.width + (target.getContentSize().width / 2.0f),actualY);

        addChild(target);
        target.setTag(1);
        ......

        int minDuration = 2;
        int maxDuration = 4;
        int rangeDuration = maxDuration - minDuration;
        int actualDuration = 
        rand.nextInt(rangeDuration) + minDuration;

        CCMoveto actionMove = 
        CCMoveto.action(
        actualDuration,CGPoint.ccp(
        -target.getContentSize().width / 2.0f,actualY));
        CCCallFuncN actionMoveDone =
        CCCallFuncN.action(this,"spriteMoveFinished");
        CCSequence actions = 
        CCSequence.actions(actionMove,actionMoveDone);

        target.runAction(actions);
}

addTarget方法中完成了两件事情:
1. 添加敌人精灵到屏幕上的随机位置
2. 让精灵动起来
创建并添加敌人精灵到相应位置的代码与之前添加忍者精灵的代码非常类似。首先利用Target.png创建精灵,然后调用精灵的setPosition方法设定精灵在屏幕上的位置。这次的位置相对灵活一些,纵坐标方面先计算一个minY,minY的位置为敌人精灵恰好踩在屏幕的最底边时的纵坐标,而maxY的位置为敌人精灵恰好顶在屏幕的最上边时的纵坐标。然后利用Random在minY和maxY之间生成一个随机的值作为最终敌人精灵所在位置的纵坐标。横坐标方面利用屏幕的最大宽度加上敌人精灵宽度的一半,这样让敌人精灵的最左侧恰好贴在屏幕最右侧位置,刚好看不见。

另外在创建了敌人精灵后比之前多了一行代码:

target.setTag(1);

这里为创建的敌人精灵设置一个tag属性,以后可以通过该tag值判定一个精灵的类型是什么。如果取到一个精灵的tag值为1,则可以知道该精灵为敌人精灵。
接下来要让精灵动起来。这里要使用Cocos2d-android中提供的一Action类型对象。这里用到了3中Action对象:
1. CCMoveto:它的作用是在规定的时间内,让精灵从当前位置移动到参数指定位置。

CCMoveto actionMove = 
        CCMoveto.action(
            actualDuration,CGPoint.ccp(
            -target.getContentSize().width / 2.0f,actualY));

actualDuration为利用Random生成的完成移动的时间,第二个参数是移动结束时希望敌人精灵所处的位置。终止位置的纵坐标与敌人精灵初始位置的纵坐标一致,横坐标为敌人精灵移出屏幕最左侧一半身位的位置,也就是敌人精灵的最右侧恰好贴在屏幕的最左侧边缘,刚好看不见。
2. CCCallFuncN:也是Action类型,它的作用是用来回调指定的方法,例子中被回调的方法名称是spriteMoveFinished方法,且spriteMoveFinished方法会有一个Object类型的参数传入。
3. CCSequence:Action类型,它的作用顾名思义就是将参数中传入的若干个Action组成一个序列按顺序执行。
代码中,我们的敌人精灵实际最终运行的Action是CCSequence类型的actions,而创建actions的时候我们传入了两个action对象,一个是CCMoveto类型的actionMove对象,另一个是CCCallFuncN类型的actionMoveDone对象。这样最终的执行内容就是先执行actionMove,在随机时间内将敌人精灵从屏幕的右侧移动到左侧,当移动完毕后执行actionMoveDone,回调spriteMoveFinished方法。

public void spriteMoveFinished(Object sender)
    {
        CCSprite sprite = (CCSprite)sender;

        if (sprite.getTag() == 1)
        {
            ......
        }
        ......

        this.removeChild(sprite,true);
    }

之前说过spriteMoveFinished有一个Object类型的参数,该参数就是触发该回调的精灵。我们通过调用该精灵的getTag方法来判定该精灵究竟是什么精灵,如果tag为1则该精灵是敌人精灵,我们可以针对敌人精灵在做更多的操作。最后将该精灵从Layer上去掉。

this.removeChild(sprite,true);

此时再运行我们的代码,就会看到从屏幕右侧每隔一秒钟会产生一个水平移动的敌人精灵,因为移动的时长是随机数,因此敌人精灵从屏幕右侧向左侧移动时的速度是不一样的。
OK,接下来来处理用户的手指触摸。一旦用户在屏幕上进行了点击,则会触发Layer中的响应回调方法,我们只需要在GameLayer中重写这些方法即可。这些方法包括cctouchesBegan、cctouchesMoved、cctouchesEnded、cctouchesCancelled方法,从名字就可以知道哪些方法会在触摸发生的什么阶段被回调。
在游戏中当触摸屏幕时,希望忍者精灵向触摸位置方向发射一枚飞镖。根据设计可以重写cctouchesBegan刚按下时就发送飞镖,也可以重写cctouchesEnded手指抬起时发送飞镖。

public boolean cctouchesEnded(MotionEvent event)
{
        // 将坐标点从安卓坐标系转为Cocos2d坐标系
        CGPoint location = 
        CCDirector.sharedDirector().
        convertToGL(CGPoint.ccp(
        event.getX(),event.getY()));

        CGSize winSize = 
        CCDirector.sharedDirector().displaySize();
        CCSprite projectile = 
        CSprite.sprite("Projectile.png");

        projectile.setPosition(20,winSize.height / 2.0f);

        //计算飞镖的终点坐标
        int offX = 
        (int)(location.x - projectile.getPosition().x);
        int offY = 
        (int)(location.y - projectile.getPosition().y);
        if (offX <= 0)
            return true;
        addChild(projectile);
        projectile.setTag(2);

        ......

        int realX = (int)(winSize.width + (projectile.getContentSize().width / 2.0f));
        float ratio = (float)offY / (float)offX;
        int realY = (int)((realX * ratio) + projectile.getPosition().y);
        //飞镖的终点坐标
        CGPoint realDest = CGPoint.ccp(realX,realY);

        int offRealX = 
        (int)(realX - projectile.getPosition().x);
        int offRealY = 
        (int)(realY - projectile.getPosition().y);
        float length = 
        (float)Math.sqrt(
          (offRealX * offRealX) +
          (offRealY * offRealY));
        float veLocity = 
            480.0f / 1.0f; // 480 pixels / 1 sec
        float realMoveDuration = length / veLocity;

        //移动飞镖
        projectile.runAction(CCSequence.actions(
                CCMoveto.action(
                realMoveDuration,realDest),CCCallFuncN.action(
                this,"spriteMoveFinished")));

        ......

        return true;
}

当手指抬起后,会从初始位置飞镖精灵的初始位置(20,屏幕高度一半)向手指抬起的方向进行移动,但是移动时需要注意的是飞镖移动的终点并不是手指抬起的点,而是应该顺着手指抬起的点一直延伸到屏幕之外:

这里的计算只需用到一点简单的比值关系就可以计算出飞镖的终点坐标。在得到终点坐标后利用勾股定理得到飞镖飞行的距离。然后利用飞行距离除以一个人为设定的飞行速度(480)计算出来完成这段移动所需要的时长。有了时长和终点坐标就可以构建CCMoveto来移动飞镖了。同样我们也通过构建CCSequence在飞镖移动完毕后回调spriteMoveFinished方法,这样我们就需要在spriteMoveFinished增加一些针对飞镖精灵的处理逻辑了:

public void spriteMoveFinished(Object sender)
    {
        CCSprite sprite = (CCSprite)sender;

        if (sprite.getTag() == 1)
        {
            //敌人精灵的处理逻辑
            ......
        }
        else if (sprite.getTag() == 2)
            //飞镖精灵的处理逻辑
            .....
        //无论是什么精灵,移动完毕就从Layer上移除
        this.removeChild(sprite,true);
    }

接下来,处理飞镖击中敌人时的逻辑。飞镖击中敌人实际就是飞镖精灵和敌人精灵发生了碰撞,此时应该让敌人精灵从屏幕上消失,当然击中了敌人的飞镖精灵也应该消失掉。
首先我们在构造器的最后再加上一句代码:

this.schedule("update");

这与之前添加的this.schedule(“gameLogic”,1.0f);类似,也是每间隔一段时间就调用一次update方法,只不过这一次的调用间隔与我们在构造器中设置的刷新率是一致的,也就是1/60秒就调用一次update方法。
接下来就是在update方法中处理飞镖精灵和敌人精灵的碰撞:

public void update(float dt)
{
    ......  
    CGRect projectileRect = 
    CGRect.make(projectile.getPosition().x - 
    (projectile.getContentSize().width / 2.0f),projectile.getPosition().y - 
    (projectile.getContentSize().height / 2.0f),projectile.getContentSize().width,projectile.getContentSize().height);
    ......
    CGRect targetRect = 
    CGRect.make(target.getPosition().x -
    (target.getContentSize().width),target.getPosition().y - 
    (target.getContentSize().height),target.getContentSize().width,target.getContentSize().height);
    ......
    if (CGRect.intersects(projectileRect,targetRect))
    {
            ......
            removeChild(target,true);
            removeChild(projectile,true);
            ......
    }
    ......
}

update方法中保留了碰撞检测的核心代码:
首先利用CGRect勾勒出飞镖精灵的外边框,CGRect需要提供四个参数,分别是边框左下角的横坐标和纵坐标,以及边框的宽度和高度。然后如法炮制的勾勒出敌人精灵的外边框。然后利用CGRect提供的静态方法intersects来判定两个边框是否有相交,如果一旦相交就意味着产生了碰撞,于是将碰撞的双方敌人精灵和飞镖精灵从Layer上去除。
注意:update方法中仅仅保留了碰撞检测的核心代码,完整的代码请下载后自行参考。
接下来,我们再为游戏添加上背景音乐和音效。背景音乐和音效的声音文件可以保存到项目res文件夹下的raw文件夹中,读取和加载声音文件时可以使用R.raw.资源文件名来进行。

这里background_music_acc为背景音乐文件,而pew_pew_lei为音效文件。Cocos2d-android提供了响应的工具类非常方便我们来进行音乐或音效的播放。
同样在GameLayer的构造器里面添加如下代码:

// 获取上下文对象
Context context = CCDirector.sharedDirector().getActivity();
SoundEngine.sharedEngine().preloadEffect(context,R.raw.pew_pew_lei);
SoundEngine.sharedEngine().playSound(context,R.raw.background_music_aac,true);

使用SoundEngine的preloadEffect方法来缓冲音效文件,用playSound方法来设定循环播放背景音乐。
注意:这里在实际测试的时候,在执行playSound方法之前应该先preloadSound一下,否则可能因为MediaPlayer的不正确状态导致代码异常。另外再实际测试中,即使设置了第二个参数为循环播放(true),还是因为MediaPlayer的状态问题导致背景音乐只能播放一次。
后面凡是需要播放音效的地方,只要调用SoundEngine.sharedEngine().playEffect即可。
比如,我们在发射飞镖的时候需要音效,就可以在cctouchesEnded方法中添加上一行:

public boolean cctouchesEnded(MotionEvent event)
{
    ......
    // 播放音效
    Context context = 
    CCDirector.sharedDirector().getActivity();
    SoundEngine.sharedEngine().playEffect(
    context,R.raw.pew_pew_lei);
    ......
    return true;
}

这样每当发射飞镖时,都会伴随着pew pew的音效声了。
最后,我们再为游戏增添一个结束场景。我们设定,如果敌人在从屏幕右侧向左侧的移动过程中没有被飞镖击中,顺利的从屏幕左侧逃脱则游戏进入结束场景。
上面曾经写过敌人精灵顺利完成移动(从屏幕左侧逃脱)后会回调spriteMoveFinished方法,因此我们将逻辑加入到方法中:

public void spriteMoveFinished(Object sender)
    {
        CCSprite sprite = (CCSprite)sender;

        if (sprite.getTag() == 1)
        {
            _targets.remove(sprite);

            _projectilesDestroyed = 0;
            CCDirector.sharedDirector().replaceScene(GameOverLayer.scene("You Lose :("));
        }
        else if (sprite.getTag() == 2)
            ......

        this.removeChild(sprite,true);
    }

如果是敌人精灵逃脱后触发的spriteMoveFinished方法,则利用CCDirector进行幕的切换,从当前幕切换到由GameOverLayer.scene()方法产生的幕。
看一下GameOverLayer类:

public class GameOverLayer extends CCColorLayer {
    protected cclabel _label;

    public static CCScene scene(String message)
    {
        CCScene scene = CCScene.node();
        GameOverLayer layer = new GameOverLayer(
            ccColor4B.ccc4(255,255));

        layer.getLabel().setString(message);

        scene.addChild(layer);

        return scene;
    }

    public cclabel getLabel()
    {
        return _label;
    }

    protected GameOverLayer(ccColor4B color)
    {
        super(color);

        this.setIsTouchEnabled(true);

        CGSize winSize = 
        CCDirector.sharedDirector().displaySize();
        //参数为:文字内容,字体名称,文字大小
        _label = cclabel.makeLabel(
        "Won't See Me","DroidSans",32);
        _label.setColor(ccColor3B.ccBLACK);
        _label.setPosition(
        winSize.width / 2.0f,winSize.height / 2.0f);
        addChild(_label);

        this.runAction(CCSequence.actions(
            CCDelayTime.action(3.0f),CCCallFunc.action(this,"gameOverDone")));
    }

    public void gameOverDone()
    {
        CCDirector.sharedDirector().
            replaceScene(GameLayer.scene());
    }

    @Override
    public boolean cctouchesEnded(MotionEvent event)
    {
        gameOverDone();

        return true;
    }
}

GameOverLayer的代码与GameLayer的代码有很多类似的地方,首先也是继承自CCColorLayer因此可以设定白色背景,在构造器中也创建了一个精灵,只不过这次的精灵即不是一个图片甚至也不是一个CCSprite类型,而是一个显示文字的cclabel对象。但是前面提到过任何显示在屏幕上的东西都是一个精灵,因此cclabel对象也是一个精灵。
在构造器中,精灵创建完毕后会继续执行Action,这里的Action也是由CCSequence组成的Action序列,序列中先执行CCDelayTime让场景停留三秒,随后执行CCCallFunc中指定的gameOverDone回调方法。需要注意的是,CCCallFunc中的回调方法是不带参数的,而前面用过的CCCallFuncN中的回调方法是携带一个Object参数的。在回调方法gameOverDone中通过CCDirector进行幕的切换,从当前的游戏结束幕再次切换到GameLayer.scene方法返回的幕。而且当用户触摸屏幕时,当用户手指离开会触发重写的cctouchesEnded方法,该方法中会立即触发gameOverDone方法马上完成幕的切换。
GameOverLayer的scene方法与GameLayer的scene方法基本一致,创建scene对象,通过构造器创建layer对象,将layer对象添加到scene中并将scene对象返回。
至此,一个用Cocos2d-android创建的小游戏就算写完了,我们再来回顾一下使用Cocos2d-android开发的整体步骤:
1. Cocos2d-android的一些全局初始化
2. 场景的搭建(scene,layer,sprite)
3. 事件的处理(触摸,碰撞)
4. 音乐、音效(sound,effect)
5. 场景的切换

完整代码下载:源码

如何用Cocos2d-android写一个小游戏的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  9. 早期Swift中Cocos2D初始化代码的重构

    但是遗憾的是Swift2.2中还是不支持Type的class属性关键字,只能用static,我们期待Swift3的改进吧!

  10. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部