cocos2d-js开发笔记

一.前言

之前有机会接触了cocos2d-js(cocos2d-x的一个分支)相关的技术,这里就做一个回顾和讲解,会从cocos2d-x的历史架构再到cocos2d-js和2d-x的差异开始,同时也介绍下之前cocos项目的整体结构和使用到的核心知识点,也方便自己后续回顾,目前,cocos官方目前大力推荐的是cocos creator,由于之前在做项目时候cocos creator不是非常成熟,加上js语法简洁和跨平台支持等原因,再到项目中的游戏模块不是很复杂择最后了就选择使用cocos2d-js分支来开发。

如果在现阶段要开发一个cocos 游戏,大力推荐使用cocos creator,这个也是cocos官方大力推荐的,cocos2d-x引擎的更新速度已放慢,cocos2d-js已经不再更新了,creator 已经是未来开发cocos游戏的必选的工具和趋势,cocos creator 和cocos2d-x 是完全不同的两个东西,包括引擎架构和开发流程是完全不一样的,creator这里不再多说,我这边还是要介绍下cocos2d-x相关的技术知识。

二.cocos2d-x 介绍

cocos2d-x是什么

Cocos2d-x 是 MIT 许可证下发布的一款功能强大的开源游戏引擎。

允许开发人员使用 C++、Javascript 及 Lua 三种语言来进行游戏开发。

支持所有常见平台,包括 iOS、Android、Windows、macOS、Linux。

引擎特性

  • 现代化的 C++ API
  • 立足于 C++ 同时支持 JavaScript/Lua 作为开发语言
  • 可以跨平台部署, 支持 iOS、Android、Windows、macOS 和 Linux
  • 可以在 PC 端完成游戏的测试,最终发布到移动端
  • 完善的游戏功能支持,包含精灵、动作、动画、粒子特效、场景转换、事件、文件 IO、数据持久化、骨骼动画、3D

市场占有

Cocos2d-x 用户不仅包括个人开发者和游戏开发爱好者,还包括许多知名大公司如 Zynga、Wooga、Gamevil、Glu、GREE、Konami、TinyCo、HandyGames、IGG 及 Disney Mobile 等。

使用 Cocos2d-x 开发的许多游戏占据苹果应用商店和谷歌应用商店排行榜,同时许多公司如触控、谷歌、微软、ARM,英特尔及黑莓的工程师在 Cocos2d-x 领域也非常活跃。

在中国,每一年的手游榜单大作,Cocos2d-x 从未缺席,市场份额占 50% 以上,游戏品类覆盖从轻度休闲,热火棋牌,到横版,SLG,重度 MMO 等市面全品类。一些以 Cocos2d-x 为基础开发出的游戏如下:

POWERED BY COCOS.png

游戏引擎是一种特殊的软件,它提供游戏开发时需要的常见功能;引擎会提供许多组件,使用这些组件能缩短开发时间,让游戏开发变得更简单;专业引擎通常会能比自制引擎表现出更好的性能。游戏引擎通常会包含渲染器,2D/3D 图形元素,碰撞检测,物理引擎,声音,控制器支持,动画等部分。

Cocos2d-x 就是这样的一个游戏引擎,它提供了许多易于使用的组件,有着更好的性能,还同时支持移动端和桌面端。Cocos2d-x 通过封装底层图形接口提供了易用的API,降低了游戏开发的门槛,让使用者可以专注于开发游戏,而不用关注底层的技术细节。更重要的是 Cocos2d-x 是一个完全开源的游戏引擎,这就允许您在游戏开发过程中根据实际需要,定制化引擎的功能,如果您想要一个功能但又不知如何修改,提出这个需求,全世界的开发者可以一起为您完成。

cocos2d-x的几个基本核心概念

导演(Director)).png

导演

Cocos2d-x 使用导演的概念,这个导演和电影制作过程中的导演一样!导演控制电影制作流程,指导团队完成各项任务。在使用 Cocos2d-x 开发游戏的过程中,你可以认为自己是执行制片人,告诉 导演(Director) 该怎么办!一个常见的 Director 任务是控制场景替换和转换。 Director是一个共享的单例对象,可以在代码中的任何地方调用。

如下 Director 就负责场景的转换:

scenes.png

场景(Scene)

在游戏开发过程中,你可能需要一个主菜单,几个关卡和一个结束场景。如何组织所有这些分开的部分?使用 场景(Scene) !当你想到喜欢的电影时,你能观察到它是被分解为不同场景或不同故事线。现在我们对游戏开发应用这个相同的思维过程,你应该很容易就能想出几个场景。

Player 1 00000.png

场景图(Scene Graph)是一种安排场景内对象的数据结构,它把场景内所有的 节点 (Node) 都包含在一个  (tree) 上。(场景图虽然叫做”图”,但实际使用一个树结构来表示)。

Root.jpg

分解这个场景,看一下它有哪些元素,这些最终会被渲染为一个树。

Sceme.png

精灵(Sprite)

所有的游戏都有 精灵(Sprite) 对象,精灵是您在屏幕上移动的对象,它能被控制。你喜欢玩的游戏中主角可能就是一个精灵,我知道你在想是不是每个图形对象都是一个精灵,不是的,为什么? 如果你能控制它,它才是一个精灵,如果无法控制,那就只是一个节点(Node)。

看下面的图片,我们来指出一下,哪个是精灵(Sprite),哪个是节点(Node)。

Super Cocos Aliens.png

动作(Action)

创建一个场景,在场景里面增加精灵只是完成一个游戏的第一步,接下来我们要解决的问题就是,怎么让精灵动起来。动作(Action) 就是用来解决这个问题的,它可以让精灵在场景中移动,如从一个点移动到另外一个点。你还可以创建一个动作 序列(Sequence) ,让精灵按照这个序列做连续的动作,在动作过程中你可以改变精灵的位置,旋转角度,缩放比例等等。

序列(Sequence)

能在屏幕上移动精灵,是制作一个游戏所需的一切,是吗?不是的,至少要考虑一下如何执行多个 Action。Cocos2d-x 通过 序列(Sequence) 来支持这种需求。

顾名思义,序列就是多个动作按照特定顺序的一个排列,当然反向执行这个序列也是可以的,Cocos2d-x 能很方便的完成这项工作。

如下是一个通过序列控制精灵移动的例子:

Move To.png

当然远远不止这些,除此之外还有物理引擎的支持(例如碰撞检查重力等)、音视频模块如(音乐音效支持等模块)具体可以查看官方文档

docs.cocos.com/cocos2d-x/m…

Cocos2d引擎家族介绍

Creator.png

cocos2d架构图

cocos.png
Cocos2d-JS是Cocos2d-x中的JavaScript版本,是Cocos2d-HTML5的延伸,官方对基于Web引擎的H5版本和基于Native的C++版本进行了整合,并在API层提供了统一的JavaScript API,使得Cocos开发更加容易

由于之前选用的是cocos2d-js,以下会侧重讲解js相关内容

二.快速开发一个cocos2d-js项目

项目结构

文件目录介绍

CMakelists.txt.png

  • framework
  • cocos2d-html5 网页端的工程目录
  • cocos2d-x cocos引擎代码目录
  • runtime-src

runtime-src

cocos2d-html5.png

  • Classes 是navtive 的app入口文件

  • proj.xxx 针对 iOS 安卓  Mac 等平台的工程目录

  • Index.html是网页端的启动文件,如果只是发布客户端可以忽略

  • main.js 是 cocos2d-js的启动入口文件,相当于 iOS 中工程的main文件

  • manifest.webapp 是一些描述信息一般用不到

三 manifest.webapp.png

  • project.json 是配置项目资源的核心文件 主要包括后续js类文件的引用

Pasted Graphic 4.png

  • res 所有用到资源的文件目录(图片 音频 字体 动画资源等等)

Achievement.png

  • src

也就是js代码的目录 这个文件夹下有一个resource.js 文件 项目中用到的资源文件需要在此文件中引用方可加载

Sre.png

THE SOFTMARE..png

以上为整个工程的文件目录功能介绍

开发工具

因为cocos2d-js 是基于js来开发的,那么关于编辑器就需要用到js相关开发工具,推荐webstrom 或者 vscode ,另外如果需要用到原生相关的功能,譬如iOS 相关的,那么就需要用到xcode,如果是安卓就要用Android studio。

环境搭建&生成工程

github.com/cocos2d/coc…

这里拿3.17.2版本为例,下载完成后目录如下

cocos2d-x.org/filedown/co…

AUTHORS.png

Setup.py为环境配置脚本,由于目前此版本脚本python 要求 2.x 版本 ,我这边就不去演示了,因为我电脑是python 3.x ,有兴趣的可以自己去安装一个2.x 尝试。

官方的目录下有关于js的demo 示例 目录在 js-tests里边,有兴趣的可以逐个研究下官方demo

Index.html.png

安装完成环境 通过 cocos new 快速生成工程模板

cocos **new** -**l** js ProjectName

模板如下

。• Ov.png

模板核心源码介绍

拿iOS 工程举例讲解

Pasted Graphic 4.png

可以看到 和 iOS 新建工程类似,区别在于cocos 项目是在启动生命周期做了cocos引擎的初始化并且加载了一个GLView来渲染

cocos2d::Application *app = cocos2d::Application::getInstance();





    // Initialize the GLView attributes





    app->initGLContextAttrs();





    cocos2d::GLViewImpl::convertAttrs();




    // Override point for customization after application launch.




    // Add the view controller's view to the window and display.



    window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];



    // Use RootViewController to manage CCEAGLView



    _viewController = [[RootViewController alloc]init];



    _viewController.wantsFullScreenLayout = YES;



    // Set RootViewController to window



    if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)


    {
        // warning: addSubView doesn't work on iOS6

        [window addSubview: _viewController.view];
    }



    else



    {
        // use this method on ios6


        [window setRootViewController:_viewController];
    }


    [window makeKeyAndVisible];
    [[UIApplication sharedApplication] setStatusBarHidden:true];

    // IMPORTANT: Setting the GLView should be done after creating the RootViewController

    cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)_viewController.view);

    cocos2d::Director::getInstance()->setOpenGLView(glview);

    //run the cocos2d-x game scene

    app->run();

    return YES;

}

此外initGLContextAttrs是cocos 的初始化核心方法,也就是启动js相关模块的初始化方法,核心方法都在AppDelegate.cpp类里边

Appowepate.png

同时可以看到applicationDidFinishLaunching 中的    ScriptingCore::getInstance()->runScript(“main.js”); 即为启动js模块的入口类

sc-9addRegisterCallback(reqister a1l cocos2dx experinontal video);.png

App前后台切换暂停 重启游戏都是通过原生调用cocos引擎来完成的

NeoJavssoret Cmtses) c ogOwleame M AoroelesweescelcrionddrnlabLamching0.png

这里main.js 运行起来后 就开始了游戏的初始化流程了,我这里拿我之前做的项目来展示

Pasted Graphic 8.png

发行说明:1.8.png

//load resources





    cc.LoaderScene.preload(g_resources, function () {





        cc.director.runScene(new SXTHomePageScene());





    }, this);

即为第一个页面场景的类,在场景加载之前可以自定义的处理一些事情,如预加载资源,做屏幕适配等初始化等,后边我会详细讲下我之前项目的整体结构和大概功能点。

实战项目功能介绍

我这边会结合我之前做的项目 介绍下 cocos2d-js相关的开发 以及 cocos和 na交互能技术,包括cocos2d-js 功能代码结构等,以及 cocos 核心概念动画等。

我这边拿部分功能举例

cocos2d-js项目结构

我这边不详细介绍游戏实现,主要说下项目模块的功能梳理和框架

SHVRAOTONG.png

游戏模块

游戏网络请求

主要通过Api 实现游戏业务网络请求处理

Pasted Graphic 11.png

统一通过Network 类实现网络请求处理

Pasted Graphic 12.png

Cocos2d-js 网络请求用的是 cc.loader.getXMLHttpRequest()  ,此类主要是封装post 和get方法和业务明确的一些状态码以及加密解密数据的逻辑

代码如下

  1. 请求参数处理

Netvork.ajex - funetten (eot ions) (cot HoNs..png

  1. 设置参数相关编码和预处理等

sgl1ons.da3e - ont 1cns.da3a + Eversf RdS (GecoseaklCongerent(or3.png

  1. 真正的请求逻辑

Pasted Graphic 18.png

Pasted Graphic 15.png

  1. 错误超时的处理

Pasted Graphic 17.png

游戏部分功能模块

游戏模块使用 layer scene 和script 来分层

Games.png

Layer 主要做ui的布局和交互逻辑

var SxTPLayFootba 1 UAnsaatHorLayer  cc. Layer.extend(.png

Scene 来做场景的切换和游戏逻辑处理 每个场景都会用一个layer来处理核心逻辑

〉Games 〉 playFootbMl 〉 Soene 〉 Js SXTPlaFootbalScene.ls  ke) SxTPayFootbalkayer.png

Piyfooxbel 〉Scene〉p SxTPaayfootbu Seene i  0e SxTPlay footbonL D setupDispla.png

Script 就是对一些自定义精灵 的封装

var ScTFootbaltSprite a cc.Sorite.ertendlt.png

场景的切换统一封装了route

SxIGoncBaute.opesGane - function (eae Typ. Jameld. 1sPutn, Jstrrercame).png

游戏列表页面

列表页面使用的是ccui.ScrollView 实现的

SetupListVlew functlon (listview).png

游戏写字模块

1.轮廓绘制

首先使用了一个开源的笔画数据,这个数据是每个文字的每一笔画的点,核心绘制笔画轮廓的部分代码

//绘制轮廓





    makePath: function (strokeStr) {





        let strokeCommands = strokeStr.split(" ");





        let offset = GC.h - this._Offset_y * this.getStrokeYRatio();




        let lastPos = cc.p;




        let outlineColor = cc.color(221, 113, 60);



        let counter = 0;



        while (counter < strokeCommands.length) {



            let commend = strokeCommands[counter];



            if (commend == "M") {



                let x = this.scalePointX(strokeCommands[counter + 1]);



                let y = this.scalePointY(strokeCommands[counter + 2]);
                
                this._m_drawNode.drawDot(cc.p(x, offset - y), 0, outlineColor);


                lastPos = cc.p(x, offset - y);


                counter += 3;



            }



            if (commend == "Q") {

                let x1 = this.scalePointX(strokeCommands[counter + 1]);

                let y1 = this.scalePointY(strokeCommands[counter + 2]);


                let x2 = this.scalePointX(strokeCommands[counter + 3]);

                let y2 = this.scalePointY(strokeCommands[counter + 4]);

                this._m_drawNode.drawQuadBezier(lastPos, cc.p(x1, offset - y1), cc.p(x2, offset - y2), 50, 1, outlineColor);

                lastPos = cc.p(x2, offset - y2);

                counter += 5;

            }

            if (commend == "C") {

                let control1x = this.scalePointX(strokeCommands[counter + 1]);

                let control1y = this.scalePointY(strokeCommands[counter + 2]);

                let control2x = this.scalePointX(strokeCommands[counter + 3]);

                let control2y = this.scalePointY(strokeCommands[counter + 4]);

                let destinationX = this.scalePointX(strokeCommands[counter + 5]);

                let destinationY = this.scalePointY(strokeCommands[counter + 6]);

                this._m_drawNode.drawCubicBezier(lastPos, cc.p(control1x, offset - control1y), cc.p(control2x, offset - control2y), cc.p(destinationX, offset - destinationY), 50, 1, outlineColor);

                lastPos = cc.p(destinationX, offset - destinationY);

                counter += 7;

            }

            if (commend == "L") {

                let x = this.scalePointX(strokeCommands[counter + 1]);

                let y = this.scalePointY(strokeCommands[counter + 2]);

                this._m_drawNode.drawSegment(lastPos, cc.p(x, offset - y), 1, outlineColor);

                lastPos = cc.p(x, offset - y);

                counter += 3;

            }

            if (commend == "Z") {

                break;

            }

        }

    },

2.画笔处理

通过自定义一个精灵元素,实现拖拽逻辑进行笔画绘制

onTouchBegan : function (touch, event) {





        this. _enableTouch = true;





        var target = event.getCurrentTarget();





        if (false == target._enableMoved){




            return;




        }



        if (!target.isTouchInRect(touch)){



            return false



        }



        target._callback();



        return true;



    },


    onTouchMoved : function (touch, event) {


        var pos = touch.getLocation();


        var target = event.getCurrentTarget();



        var delta = touch.getDelta();



        var point = target.parent.convertToNodeSpace(cc.p(target.x,target.y));
        target.setPosition(cc.p(target.x+delta.x,target.y+delta.y));


        target._callback();

    },

在layer层通过移动的坐标点和 之前绘制出来目标点的位置进行碰撞检测cc.rectContainsPoint,如果绘制出的目标点最后一个被吃掉视为完成写字。

游戏场景模块

主要有打地鼠,推箱子,朗诵,连线等10几种小游戏。

1.游戏音频播放

短音频

//播放





this.audioId =audio.playEffect(res);





 audio.setEffectsVolume(1);





//停止




 cc.audioEngine.stopEffect(audioID)




长音频

用的ccui.VideoPlayer()

Aadio.plaver e new ccul.VideopLaver().png

有些场景cocos的播放器不太好用,就通过原生封装了一个播放器,通过jsb调用实现,这里iOS 是单独用的iOS  avplayer播放器,安卓用的cocos系统的,其实系统底层也是用的原生播放器。

Adfo.holdertode . sender.png

Pasted Graphic 29.png

原生模块

主要做语音评测 ,分享能力,登录能力 支付能力 以及一些竖屏用户学习数据展示列表页面等等。

原生游戏交互模块

1.核心调用是通过jsb.reflection实现的

ver Netioonetsod wtivethod 0.png

2.这里也处理了一下多方法调用原生,并且需要原生返回处理的逻辑

Caltbackranager • CallbackManager.png

譬如获取用户信息是异步的,会把js方法对象传递到native,最终端上处理完成回调到callbackmannager,通过传递生成的时间戳作对比找到回调

Pasted Graphic 32.png

3.端上其实就是一个类方法实现

Qinterface JSewanager.png

(void)getUserinfo(NSString acs11back(.png

Clnplenentation JseNanager.png

三.官方学习资料

docs.cocos.com/cocos2d-x/m…

docs.cocos.com/cocos2d-x/m…

总结

以上为我在项目实战中的一些记录,有兴趣可以自己去尝试学习,希望也能对大家有一定的帮助,同时也是自己对过去的一个简要总结。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYx3qNv0' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片