abi选择 cocos
2018-09-14 14:20:00 weixin_34004750 阅读数 65

 

APP ABI 选项对应的是设备的 CPU 架构。勾选不同的值,编译出来的 apk 可以适用于不同的设备。勾选的越多,适配的机器越多。但是相应的 apk 包体越大。

需要根据自己的项目实际情况决定要编译哪些 APP ABI。如果都不勾选的话,那么默认与 proj.android/jni/Application.mk 中 APP_ABI 的值一致(Android Studio 项目的话,是 proj.android-studio/app/jni/Applicaition.mk 文件)

2018-09-14 14:20:00 weixin_34326179 阅读数 18

 

APP ABI 选项对应的是设备的 CPU 架构。勾选不同的值,编译出来的 apk 可以适用于不同的设备。勾选的越多,适配的机器越多。但是相应的 apk 包体越大。

需要根据自己的项目实际情况决定要编译哪些 APP ABI。如果都不勾选的话,那么默认与 proj.android/jni/Application.mk 中 APP_ABI 的值一致(Android Studio 项目的话,是 proj.android-studio/app/jni/Applicaition.mk 文件)

转载于:https://www.cnblogs.com/luorende/p/9646324.html

2019-03-30 09:58:00 weixin_30399055 阅读数 8

  我们在使用cocos在windows平台下,运行速度很快很流畅,很强大,可是当我们打包成apk文件,在手机上运行的时候,流畅度很可能降低,甚至还有间歇性内存彪高。

游戏内存优化我们一般可以从这么3个方面入手:引擎自身提供的优化选项,引擎底层框架,语言上层(内存泄漏)。事实上,代码运行占用的内存是很低的,图片等资源的加载和使用占80%你所使用的的内存资源。在这里我们着重分析一下如何由图片减少内存的使用。

  •   首先,图片的格式!各个类型(png8,png32,jpg......)我们区分一下。jpg最大的缺点是不透明,所以只能作为一些不动的背景,在最底层使用。与jpg很像的png8格式都是减少包体的好选择,因为他们的压缩比都是最好的,当然要适用,否则适得其反。
  •   其次,图片是有颜色深度RGBA4444和RGBA8888,即使是采用同样的色深(24bit or 32bit)保存,RGBA4444比RGBA8888的图像质量会差一些,而且在cocos中,最终都会使用RGBA8888,RGBA4444尽量使用颜色深度为16bit的图片,在TexturePacker中开启抖动算法,cc.Texture2D.setDefaultAlphaPixelFormat(cc.Texture2D.PIXEL_FORMAT_RGBA4444)改变默认像素格式,如何单个加载可以在加载需要将颜色深度设为RGBA4444的文件的前后,分别设置PixelFormat;图片保存格式: 8bit 、 24bit 和 24bit(with alpha channel)=32bit 三种格式;
setFormat(RGBA4444);
loadTexture("SpriteSheet.png");
setFormat(RGBA8888);

  •   接下来,看一下纹理加载过程中的内存变化, 先以一张1024*1024 本身大小500k的jpg/png图片为例:

  1. 读取图片文件(500k)
  2. 把jpg/png数据最终都是按RGBA8888(默认)格式解析(4mb)
  3. 释放500k的图片内存
  4. 上传给OpenGL纹理数据(4mb)
  5. 释放4mb内存

  计算图片纹理大小:

  1. 图片的像素点个数(分辨率)

  2. 单位像素占用的字节数(像素格式)。

即纹理内存大小 = 纹理长度 * 纹理宽度 * 单位像素占用的字节数,如:一张1136x640的RGBA8888的png图片占用的内存为 1136x640x4 = 2.8M左右

 

  • 知道了以上信息,我们可以选择对不同的设备优化:

 iOS用什么?当然是用PVR格式。
pvr是iOS设备的图形芯片 PowerVR 图形 支持的专用压缩纹理格式。它在PowerVR图形芯片中效率极高,占用显存也小。

Android设备上,因为硬件不统一,每个厂商GPU使用的不同的纹理压缩,目前可以采用ETC1或者PNG/JPEG格式。

 

  • 如何使用将图片打包压缩,较少包体,较少内存花销呢?

1.首先使用TexturePacker打包,如果颜色深度不是很高,可以选择抖动算法,打包成大图

2.将压缩后的图片使用https://tinypng.com/这个网站再压缩一次,显著减少包体

 

此外,在浏览各个大佬博客的时候,看到以下的cocos图片的技巧,(转博客地址http://imgtec.eetrend.com/d6-imgtec/blog/2018-07/16921.html):

1、一帧一帧载入游戏资源
2、减少绘制调用,打包大图
3、载入纹理时按照从大到小的顺序
4、避免高峰内存使用
5、使用载入屏幕预载入游戏资源
6、需要时释放空闲资源
7、收到内存警告后释放缓存资源
8、使用纹理打包器优化纹理大小、格式、颜色深度等
9、使用JPG格式要谨慎!
10、请使用RGB4444颜色深度16位纹理
11、请使用NPOT纹理,不要使用POT纹理
12、避免载入超大纹理
13、推荐1024*1024 NPOT pvr.ccz纹理集,而不要采用RAW PNG纹理

1. 场景、背景、全屏图片
2D手机游戏中,多半都有这样的图片,以作为背景,特别在一些SLG,横版过关游戏中。这种图片对ALPHA没有要求,并且,在同一时间,只会出现一张(如果是多张拼接,也不会超过屏幕尺寸太多),内存不会成为关键点。所以,在这种情况下,我们大胆选择JPG就可以了。

2. 场景的前景,装饰物,可移动对象(npc,moster,…)
这种要看规模,如果规模较小,类型不多。 或者类型虽然多,但同一时间出现在场景中的类型不多,那我们可以选择压缩PNG8的方式,它支持ALPHA通道,文件又小。如果同屏可能出现多种这种,则需要考虑在IOS上使用PVRTC,在ANDROID上使用ETC1+ALPHA_MASK。实际上,为了好维护,一般都是统一用pvr.ccz打包。

3. UI
UI的背景图,可以优先考虑使用压缩PNG8,如果达不到精度要求,则使用PNG32。而对于UI的小元素,可以考虑使用压缩PNG8.

对于UI的图标,一般是不带ALPHA的PVRTC/ETC + 一张公共的ALPHA掩码图,通过双层混合来实现圆边效果。 因为图标同屏出现可能较大。 如果图标能够控制在一定范围内,由于图标是48X48等大小,一张1024x1024的大图,可以放400个图标。 换用JPG,也有4MB的开销,如果这个是可以接受的,也可以使用JPG+ALPHA_MASK的方式。

写到这里才发现,其实只需要下面一句话就可以搞定。

这类图片会不会同时出现多个,同时出现时,内存开销是否无法接受, 如果确实无法接受,则使用GPU纹理,否则,优先考虑JPG,JPG+ALPHA,或者PNG8。就是说,首先要减小安装包大小,如果内存有无法接受的情况,才需要用GPU纹理进行优化。

转载于:https://www.cnblogs.com/zhangthree/p/10575689.html

2018-05-23 11:45:24 qq_27176027 阅读数 1651

功能需求:Cocos Creator 开发斗地主,滑动选取手上的手牌

 

问题:Cocos Creator没有滑动选取节点的组件,于是自己造轮子

 

说明:DragChoose组件用于在多个节点上滑动时,选择鼠标滑动区域内的节点,由于Cocos Creator 支持TypeScript,所以该组件由TypeScript语言编写,需要配合Layout组件使用,可以直接挂在相应的Node节点上

-------------------------------------------------------------------------------------------------------------

 

使用示例1:扑克根节点上需要挂上Layout组件,对子节点下的扑克牌进行排列

使用示例2:选择扑克,被选中的变成灰色

let dragChoose = this.node.addComponent(DragChoose)

dragChoose.OnMoving = (nodes) => {

for (let index = 0; index < nodes.length; index++)

        {

const poker = nodes[index];

// poker 变成灰色

}

}

 

 

 

使用示例3:选择扑克结束,扑克弹起

 

let dragChoose = this.node.addComponent(DragChoose)

dragChoose.OnEnd = (nodes) => {

    for (let index = 0; index < nodes.length; index++) {

        const poker = nodes[index];

        // poker 弹起

    }

}

 

-------------------------------------------------------------------------------------------------------------

 

 

组件代码如下:

 


const { ccclass, property } = cc._decorator;



@ccclass

export default class DragChoose extends cc.Component {

    editor: {

        executeInEditMode: true,

        requireComponent: cc.Layout,

    }



    public OnMoving: Function = null;

    public OnEnd: Function = null;

    private mWidth: number = 0; //item的宽,所有子对象必须等宽

    private mHeight: number = 0; //item的高,所有子对象必须等高

    private offsetX: number = 0; //item之间的排列间距缩进

    private startIndex: number = -1;

    private endIndex: number = -1;

    private isPressDown: false = false;//默认不按下

    private nodes: Array<cc.Node> = new Array<cc.Node>(); //所有子节点的集合

    private validNodes: Array<cc.Node> = new Array<cc.Node>(); //所有非隐藏(有效)的子节点的集合

    private targetNodes: Array<cc.Node> = new Array<cc.Node>() //选择的节点

    private get validNodesCount() { return this.validNodes.length; }



    onLoad() {

        //获取所有子节点

        this.nodes = this.node.children;

        if (!IsValidArray(this.nodes)) {

            cc.error('DragChoose has no children');

            return;

        }

        //初始化状态 与 获取参数

        this.mWidth = this.nodes[0].width;

        this.mHeight = this.nodes[0].height;

        this.node.setContentSize(0, this.mHeight)

        let layout = this.node.getComponent(cc.Layout);

        if (layout != null) {

            this.offsetX = layout.spacingX;

        }

        this.ResetValidNodes()

        this.ListenEvents();

    }



    private ResetValidNodes() {

        this.validNodes = new Array<cc.Node>();

        this.validNodes = this.nodes.filter((node) => {

            return node.activeInHierarchy

        })

    }



    private ListenEvents() {

        this.node.on(cc.Node.EventType.TOUCH_START, function (event) {

            this.isPressDown = true;

            this.OnChooseStart(event);

        }, this);

        this.node.on(cc.Node.EventType.TOUCH_END, function (event) {

            this.OnChooseCancel(event);

        }, this);

        this.node.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {

            this.OnChooseCancel(event);

        }, this);

        this.node.on(cc.Node.EventType.TOUCH_MOVE, function (event) {

            this.OnChooseMoveing(event)

        }, this);

    }



    private OnChooseStart(event) {

        this.startIndex = -1;

        this.endIndex = -1;

        this.ResetValidNodes();

        var mousePos = this.node.convertToNodeSpaceAR(event.getLocation());

        this.startIndex = this.GetNodeIndex(mousePos.x);

    }



    private OnChooseCancel(event) {

        var mousePos = this.node.convertToNodeSpaceAR(event.getLocation());



        //在区域内,将区域内的节点加入

        if (this.CheckValidArea(mousePos.x, mousePos.y)) {

            this.targetNodes = new Array<cc.Node>();

            this.endIndex = this.GetNodeIndex(mousePos.x);

            if ((this.startIndex >= 0 && this.endIndex >= 0)) {

                let tuple = MinMax(this.startIndex, this.endIndex);

                for (let i = 0; i < this.validNodes.length; i++) {

                    const element = this.validNodes[i];

                    if (i <= tuple[1] && i >= tuple[0]) {

                        this.targetNodes.push(element)

                    }

                }

            }

        }



        if (this.OnEnd != null) {

            this.OnEnd(this.targetNodes);

        }

        this.OnReset();

    }



    private OnChooseMoveing(event) {

        if (!this.isPressDown) {

            return;

        }



        //将鼠标坐标转成相对于当前节点的坐标

        var mousePos = this.node.convertToNodeSpaceAR(event.getLocation());

        if (!this.CheckValidArea(mousePos.x, mousePos.y)) {

            return;

        }



        this.endIndex = this.GetNodeIndex(mousePos.x);

        if (this.endIndex == -1) {

            return;

        }



        if ((this.startIndex >= 0 && this.endIndex >= 0) && this.startIndex != this.endIndex) {

            let tuple: [number, number] = MinMax(this.startIndex, this.endIndex);

            this.targetNodes = new Array<cc.Node>();

            for (let i = 0; i < this.validNodes.length; i++) {

                const element = this.validNodes[i];

                if (i <= tuple[1] && i >= tuple[0]) {

                    this.targetNodes.push(element)

                }

            }

            if (this.OnMoving != null) {

                this.OnMoving(this.targetNodes);

            }

        }

    }



    //在有效范围内(高 和 宽)

    private CheckValidArea(x, y) {

        var CheckValidAreaX = (posX) => {

            var areaLeft = this.validNodes[0].getPositionX() - this.mWidth / 2;

            var areaRight = this.validNodes[this.validNodesCount - 1].getPositionX() + this.mWidth / 2;

            return posX <= areaRight && posX >= areaLeft;

        }

        var CheckValidAreaY = (posY) => {

            var areaTop = this.mHeight / 2;

            var areaDown = - (this.mHeight / 2);

            return posY <= areaTop && posY >= areaDown;

        }

        return CheckValidAreaX(x) && CheckValidAreaY(y);

    }



    private OnReset() {

        this.isPressDown = false;

        this.startIndex = -1;

        this.endIndex = -1;

    }



    private GetNodeIndex(x) {

        for (let i = 0; i < this.validNodesCount; i++) {

            var posX = this.validNodes[i].getPositionX();

            if (i == this.validNodesCount - 1) {

                if (x > (posX - this.mWidth / 2) && x < (posX + this.mWidth / 2)) {

                    return i;

                }

            }



            if (x > (posX - this.mWidth / 2) && x < (posX + this.mWidth / 2 + this.offsetX)) {

                return i;

            }

        }

        return -1;

    }

}

 

 

 

2017-05-12 11:05:48 themagickeyjianan 阅读数 616
没有更多推荐了,返回首页