在图形图像和游戏应用开发中坐标系是非常重要的,我们在Android和iOS等平台应用开发的时候使用的二维坐标系它的原点是在左上角的。而在Cocos2d-JS坐标系中它原点是在左下角的,而且Cocos2d-JS坐标系又可以分为:世界坐标和模型坐标。
UI坐标
UI坐标就是Android和iOS等应用开发的时候使用的二维坐标系。它的原点是在左上角的。

UI坐标

UI坐标原点是在左上角,x轴向右为正,y轴向下为正。我们在Android和iOS等平台使用的视图、控件等都是遵守这个坐标系。然而在Cocos2d-JS默认不是采用UI坐标,但是有的时候也会用到UI坐标,例如在触摸事件发生的时候,我们会获得一个触摸对象(Touch),触摸对象(Touch)提供了很多获得位置信息的方法,如下面代码所示:
var touchLocation = touch.getLocationInView();
使用getLocationInView()方法获得触摸点坐标事实上就是UI坐标,它的坐标原点在左上角。

OpenGL坐标
我们在上面提到了OpenGL坐标,OpenGL坐标是种三维坐标。由于Cocos2d-JS的JSB是采用OpenGL渲染,因此默认坐标就是OpenGL坐标,只不过只采用两维(x和y轴)。如果不考虑z轴,OpenGL坐标的原点在左下角。

 OpenGL坐标

我们会通过一个触摸对象(Touch)获得OpenGL坐标位置,如下面代码所示:

  1. var touchLocation = touch.getLocation();

提示  三维坐标根据z轴的指向不同分为:左手坐标和右手坐标。右手坐标是z轴指向屏幕外,如3-49左图所示。左手坐标是z轴指向屏幕里,如下图所示。OpenGL坐标是右手坐标,而微软平台的Direct3D[ Direct3D(简称:D3D)是微软公司在Microsoft Windows操作系统上所开发的一套3D绘图编程接口,是DirectX的一部份,目前广为各家显卡所支持。与OpenGL同为计算机绘图软件和计算机游戏最常使用的两套绘图编程接口之一。—— 引自于维基百科 http://zh.wikipedia.org/wiki/Direct3D]是左手坐标。

三维坐标

世界坐标和模型坐标
由于OpenGL坐标有可以分为:世界坐标和模型坐标,所以Cocos2d-JS的坐标也有世界坐标和模型坐标。
你是否有过这样的问路经历:张三会告诉你向南走一公里,再向东走500米。而李四会告诉你向右走一公里,再向左走500米。这里两种说法或许都可以找到你要寻找的地点。张三采用的坐标是世界坐标,他把地球作为参照物,表述位置使用地理的东、南、西和北。而李四采用的坐标是模型坐标,他让你自己作为参照物,表述位置使用你的左边、你的前边、你的右边和你的后边。
我们看看下图,从图中可以看到A的坐标是(5,5),B的坐标是(6,4),事实上这些坐标值就是世界坐标。如果采用A的模型坐标来描述B的位置,则B的坐标是(1,-1)。

世界坐标和模型坐标

有的时候我们需要将世界坐标与模型坐标互相转换。我们可以通过Node对象如下方法实现:
{cc.Point} convertToNodeSpace(worldPoint)。将世界坐标转换为模型坐标。
{cc.Point} convertToNodeSpaceAR(worldPoint)。将世界坐标转换为模型坐标。AR表示相对于锚点。
{cc.Point} convertTouchToNodeSpace(touch)。将世界坐标中触摸点转换为模型坐标。
{cc.Point} convertTouchToNodeSpaceAR(touch)。将世界坐标中触摸点转换为模型坐标。AR表示相对于锚点。
{cc.Point} convertToWorldSpace(nodePoint)。将模型坐标转换为世界坐标。
{cc.Point} convertToWorldSpaceAR(nodePoint)。将模型坐标转换为世界坐标。AR表示相对于锚点。

下面我们通过两个例子了解一下世界坐标与模型坐标互相转换。

1、世界坐标转换为模型坐标

所示是世界坐标转换为模型坐标实例运行结果。

世界坐标转换为模型坐标

在游戏场景中有两个Node对象,其中Node1的坐标是(400, 500),大小是300 x 100像素。Node2的坐标是(200, 300),大小也是300 x 100像素。这里的坐标事实上就是世界坐标,它的坐标原点是屏幕的左下角。
编写代码如下:

  1. var HelloWorldLayer = cc.Layer.extend({
  2. sprite: null,
  3. ctor: function () {
  4. this._super();
  5. var size = cc.winSize;
  6. var closeItem = new cc.MenuItemImage(
  7. res.CloseNormal_png,
  8. res.CloseSelected_png,
  9. function () {
  10. cc.log("Menu is clicked!");
  11. }, this);
  12. closeItem.attr({
  13. x: size.width - 20,
  14. y: 20,
  15. anchorX: 0.5,
  16. anchorY: 0.5
  17. });
  18. var menu = new cc.Menu(closeItem);
  19. menu.x = 0;
  20. menu.y = 0;
  21. this.addChild(menu, 1);
  22. //创建背景
  23. var bg = new cc.Sprite(res.bg_png);                                     ①
  24. bg.setPosition(size.width / 2, size.height / 2);
  25. this.addChild(bg, 2);                                               ②
  26. //创建Node1
  27. var node1 = new cc.Sprite(res.node1_png);                               ③
  28. node1.setPosition(400, 500);
  29. node1.setAnchorPoint(1.0, 1.0);
  30. this.addChild(node1, 2);                                            ④
  31. //创建Node2
  32. var node2 = new cc.Sprite(res.node2_png);                               ⑤
  33. node2.setPosition(200, 300);
  34. node2.setAnchorPoint(0.5, 0.5);
  35. this.addChild(node2, 2);                                            ⑥
  36. var point1 = node1.convertToNodeSpace(node2.getPosition());             ⑦
  37. var point3 = node1.convertToNodeSpaceAR(node2.getPosition());               ⑧
  38. cc.log("Node2 NodeSpace = (" + point1.x + "," + point1.y + ")");
  39. cc.log("Node2 NodeSpaceAR =  (" + point3.x + "," + point3.y + ")");
  40. return true;
  41. }
  42. });

代码①~②行是创建背景精灵对象,这个背景是一个白色900 x 640像素的图片。代码第③~④行是创建Node1对象,并设置了位置和锚点属性。代码第⑤~⑥行是创建Node2对象,并设置了位置和锚点属性。第⑦行代码将Node2的世界坐标转换为相对于Node1的模型坐标。而第⑧行代码是类似的,它是相对于锚点的位置。
运行结果如下:
JS: Node2 NodeSpace = (100,-100)
JS: Node2 NodeSpaceAR =  (-200,-200)
结合图3-52我们解释一下,Node2的世界坐标转换为相对于Node1的模型坐标,就是将Node1的左下角作为坐标原点(如下图中的A点),我们不难计算出A点的世界坐标是(100, 400),那么convertToNodeSpace方法就是A点坐标减去C点坐标,结果是(-100,100)。
而convertToNodeSpaceAR方法要考虑锚点,因此坐标原点是B点,B点坐标减去C点坐标,结果是(-200, -200)。
2、模型坐标转换为世界坐标
下图所示是模型坐标转换为世界坐标实例运行结果。

模型坐标转换为世界坐标

在游戏场景中有两个Node对象,其中Node1的坐标是(400, 500),大小是300 x 100像素。Node2是放置在Node1中的,它对于Node1的模型坐标是(0, 0),大小是150 x 50像素。
编写代码如下:

  1. var HelloWorldLayer = cc.Layer.extend({
  2. sprite: null,
  3. ctor: function () {
  4. this._super();
  5. var size = cc.winSize;
  6. var closeItem = new cc.MenuItemImage(
  7. res.CloseNormal_png,
  8. res.CloseSelected_png,
  9. function () {
  10. cc.log("Menu is clicked!");
  11. }, this);
  12. closeItem.attr({
  13. x: size.width - 20,
  14. y: 20,
  15. anchorX: 0.5,
  16. anchorY: 0.5
  17. });
  18. var menu = new cc.Menu(closeItem);
  19. menu.x = 0;
  20. menu.y = 0;
  21. this.addChild(menu, 1);
  22. //创建背景
  23. var bg = new cc.Sprite(res.bg_png);
  24. bg.setPosition(size.width / 2, size.height / 2);
  25. this.addChild(bg, 2);
  26. //创建Node1
  27. var node1 = new cc.Sprite(res.node1_png);
  28. node1.setPosition(400, 500);
  29. node1.setAnchorPoint(0.5, 0.5);
  30. this.addChild(node1, 2);
  31. //创建Node2
  32. var node2 = new cc.Sprite(res.node2_png);
  33. node2.setPosition(0, 0);                                            ①
  34. node2.setAnchorPoint(0, 0); ;                                       ②
  35. node1.addChild(node2, 2);                                           ③
  36. var point2 = node1.convertToWorldSpace(node2.getPosition());                ④
  37. var point4 = node1.convertToWorldSpaceAR(node2.getPosition());              ⑤
  38. cc.log("Node2 WorldSpace = (" + point2.x + "," + point2.y + ")");
  39. cc.log("Node2 WorldSpaceAR =  (" + point4.x + "," + point4.y + ")");
  40. return true;
  41. }
  42. });

上述代码我们主要关注第③行,它是将Node2放到Node1中,这是与之前的代码的区别。这样第①行设置的坐标就变成了相对于Node1的模型坐标了。
第④行代码将Node2的模型坐标转换为世界坐标。而第⑤行代码是类似的,它是相对于锚点的位置。
运行结果如下:
JS: Node2 WorldSpace = (250,450)
JS: Node2 WorldSpaceAR =  (400,500)
图所示的位置,可以用世界坐标描述。代码①~③行修改如下:
node2->setPosition(Vec2(250, 450));
node2->setAnchorPoint(Vec2(0.0, 0.0));

this->addChild(node2, 0);

更多内容请关注最新Cocos图书《Cocos2d-x实战:JS卷——Cocos2d-JS开发》

本书交流讨论网站:http://www.cocoagame.net

欢迎加入Cocos2d-x技术讨论群:257760386

更多精彩视频课程请关注智捷课堂Cocos课程:http://v.51work6.com

《Cocos2d-x实战 JS卷》现已上线,各大商店均已开售:

京东:http://item.jd.com/11659698.html

欢迎关注智捷iOS课堂微信公共平台,了解最新技术文章、图书、教程信息

Cocos2d-JS坐标系的更多相关文章

  1. cocos2d js jsb XMLHttpRequest 中文乱码

    1.首先讲下怎样使用XMLHttpRequest 下面所说的是在cocos2d-x 2.2.2 或者 2.3 版本号中. 首先要明确cocos2d js事实上分两个版本号,一个是html5的版本号,另 ...

  2. cocos2d js的一些tip

    cocos2d-js-v3.2-rc0 cc.director.end();//退出app cc.Application.getInstance().openURL("http://www. ...

  3. cocos2d js ClippingNode 制作标题闪亮特效

    1.效果图: 之前在<Android 高仿 IOS7 IPhone 解锁 Slide To Unlock>中制作了文字上闪亮移动的效果,这次我们来看下怎样在cocos2d js 中做出类似 ...

  4. cocos2d.js

    1.节点是Cocos2d最基础的东西 2.坐标与普通数学坐标一致 3.children属性表示节点的孩子,父节点位置变化,它包含的子节点也会跟着变化,以整体的形势移动 4.层(layer), 新建层: ...

  5. cocos2d JS 源生js实现each方法

    javascript笔记——源生js实现each方法   出处:http://www.lovejavascript.com/#!zone/blog/content.html?id=48 jquery里 ...

  6. cocos2d JS 错误异常抛出捕获和崩溃拦截

    Error对象 一旦代码解析或运行时发生错误,JavaScript引擎就会自动产生并抛出一个Error对象的实例,然后整个程序就中断在发生错误的地方. Error对象的实例有三个最基本的属性: nam ...

  7. cocos2d JS 在 JavaScript 中,怎样把一个对象转化成 JSON 字符串?

    为什么今天要做这样子的操作,原因很简单,因为cocos JS 的本地缓存储存不了对象,所以当我通过本地缓存的 key和value来取值的时候就取不出来来,json的消息数据是一个对象来的,然而在做牌局 ...

  8. cocos2d JS 本地缓存存储登陆记住账号密码->相当于C++中的UserDefault

    在cocos-js 3.0以上的版本中,当我们用到本地存储的时候,发现以前用到的UserDefault在JS中并没有导出,而是换成了LocalStorage. 在LocalStorage.h文件中我们 ...

  9. html5 cocos2d js Access-Control-Allow-Origin

    1.No 'Access-Control-Allow-Origin' header is present on the requested 近期在接html5的渠道,遇到了跨域的问题,使用 js 的 ...

  10. VSCode配合chrome浏览器调试cocos2d js项目

    1.准备阶段 具备调试功能的VSCode(我的是在win10上,版本是1.17.1) 在VSCode里下载安装Debugger for Chrome扩展插件. 2.具体操作 创建一个cocosjs工程 ...

随机推荐

  1. AIM Tech Round (Div. 2) C. Graph and String 二分图染色

    C. Graph and String 题目连接: http://codeforces.com/contest/624/problem/C Description One day student Va ...

  2. Android应用增量更新

    Original:https://github.com/cundong/SmartAppUpdates Backup:https://github.com/eltld/SmartAppUpdates

  3. [AngularJS+ GSAP] Greensock TimelineLite Animation Sequences

    TimelineLite is a piece of the Greensock TweenMax library that provides the ability to create sequen ...

  4. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  5. javascript 基本数据类型

    1. javascript 五种基本数据类型  Undefined Boolean Number String Null,Undefined 对应的值只有一个 undefined, Boolean 对 ...

  6. SQL server connection KeepAlive[转]

    1.什么是SQL server TCP连接的keep Alive? 简单说,keep alive 是SQL server在建立每一个TCP 连接的时候,指定了TCP 协议的keepaliveinter ...

  7. C# 程序集反射

    namespace AssemblyLibrary { public class AssemblyLibrary { public static object LoadAssembly(string ...

  8. Python练习题 024:求位数及逆序打印

    [Python练习题 024] 给一个不多于5位的正整数,要求:一.求它是几位数,二.逆序打印出各位数字. ---------------------------------------------- ...

  9. [Windows] 解决kmplayer播放rmvb文件音视不同步

    1. 到該帖子 http://www.kmplayer.com/forums/showthread.php?t=8755 下載附件中的4個檔案放到KMP 根 目錄下(此文件已在附件中上传) 2.於KM ...

  10. 140个google面试题

    某猎头收集了140多个Google的面试题,主要是下面这些职位的. Product Marketing Manager Product Manager Software Engineer Softwa ...