Cocos2d-x Coordinate System(坐标系统)

本文详细解析了Cocos2d-x中的各种坐标系,包括世界坐标系与本地坐标系的区别,描点(AnchorPoint)的概念及其作用,以及触摸点如何在不同坐标系间进行转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系。就是数学里面的直角坐标系。右手法则坐标系。
  • 伸出右手
  • 大拇指、食指、中指做出直角坐标系的形状,对应关系为
  • 大拇指 -- X 轴
  • 食指 -- Y 轴
  • 中指 -- Z 轴
  • 当中指垂直屏幕向外,原点在屏幕坐下角就是Cocos2d-x 的坐标系统



世界坐标系(World Coordinate) VS 本地坐标系(Node Local)
  • 世界坐标系,听得好牛逼哦,但没有什么卵用,我不明白呀,猜想理解法:世界是指游戏世界,世界坐标系,就是游戏世界的坐标系,就是每一个Node 在游戏世界里面的坐标,合适的就是绝对坐标系
    • 使用世界二字,就是想告诉开发者,每一个游戏都是一个世界,这个世界的规则由开发者定。
  • 本地坐标,不用说了,就是相对坐标。每一个Node 都有独立的坐标系,有位置和方向,当Node 移动或改变方向,和该Node 关联的坐标系将随之移动或改变方向。

描点(Anchor Point)
  • 描:描绘,绘制,画。
  • 描点:绘制的起点,就是Node 的左下角。
    • [0,0] 那么绘制的起点和position 重合
    • [0.5,0.5] 那绘制的起点比position 早Node.size*0.5
    • [0.2,0.3] 那么绘制的起点比position 早[Node.size.width*0.2,Node.size.height*0.3]
    • [1,1] 那绘制的起点比position 早Node.size,相当于Node 的右上角和position 重合
    • Anchor Point的两个参数都在0~1之间。它们表示的并不是像素点,而是乘数因子。(0.5, 0.5)表示Anchor Point位于节点长度乘0.5和宽度乘0.5的地方,即节点的中心
    • 在Cocos2d-x中Layer的Anchor Point为默认值(0, 0),其他Node的默认值为(0.5, 0.5)。
  • Node
    • size = [100,100]
      • width = 100
      • height = 100
    • position = [100,100]
    • anchorPoint = [0.5,0.5]
  • ParentNode = Scene
  • 我们以Android 的形式分析一下这个Node,坐标系统Cocos2d-x
    • measure 侧量Node 的大小,这里对应的是size
    • layout 布局Node 的位置
      • position 得出相对Scene 的位置是[100,100]
      • anchorPoint 得出绘制的起点比position 早size*0.5 = [50,50]
      • 绘制的起点(Node 的左下角)[50,50]
        • 这个值是相对Scene
    • draw 绘制Node

  • 记住一点
    • Anchor Point and Size belong ChildNode
    • Position belong ParentNode
    • Anchor Point 是ChildNode 为了不让ParentChild 囚禁而出现
    • Size 是属于ChildNode自己
    • Position 是ParentNode 想囚禁ChildNode 而出现
    • Size、Anchor Point、Position ParentChild 都委托为ChildNode,这样ParentNode 只管把ChildNode加入进来就可以了,要怎么样显示ChildNode自己定吧
      • 很好的设计,委托了 
设置描点
  • ignoreAnchorPointForPosition(bool) -- 忽略Anchor Point
  • setAnchorPoint(Point(1, 1)); -- 设置Anchor Point

Z Coordinate -- VertexZ,PositionZ和zOrder

VerextZ是OpenGL坐标系中的Z值
  • PositionZ == VerextZ,两个坐标是一样的
  • 全局渲染顺序
PositionZ是Cocos2d-x坐标系中Z值
  • setPosition(Point(1,1))
  • PositionZ == VerextZ,两个坐标是一样的
zOrder是Cocos2d-x本地坐标系中Z值
  • this->addChild(red, 0); -- zOrder = 0
  • this->addChild(green, 1); -- zOrder = 1
  • 局部渲染顺序

同样节点的PositionZ也是决定了该节点的渲染顺序,值大的渲染在上层,但是与zOrder不同的区别在于,PositionZ是全局渲染顺序即在根节点上的渲染顺序,而zOrder则是局部渲染顺序,即该节点在其父节点上的渲染顺序,与Node的层级有关。用以下事例来说明:

触摸点(Touch Position)

在处理触摸事件时,我们需要重写以下四个函数
virtual bool onTouchBegan(Touch *touch, Event * event);
virtual void onTouchEnded(Touch *touch, Event * event);
virtual void onTouchCancelled(Touch *touch, Event * event);
virtual void onTouchMoved(Touch *touch, Event * event);
这个时候我们需要讲Touch 的坐标转换为Cocos2d坐标系中的坐标
  • Touch 坐标使用的是屏幕坐标系
// returns the current touch location in OpenGL coordinates
Vec2 Touch::getLocation() const
{
return Director::getInstance()->convertToGL(_point);
}
// returns the current touch location in screen coordinates
Vec2 Touch::getLocationInView() const
{
return _point;
}

常用接口
  • 函数声明在Node 类里面,所以大家都可以用Scene、Layer、Sprite
  • 想象Cocos 世界只有一个Node,就像自己一个在宇宙游荡,为自己去一个名字就OnlyNode,这样Cocos 就只有两个东西,Cocos世界和OnlyNode
    • 有一个天OnlyNode 看到自己的原点Point(0,0)突然发出一道闪光
    • 一瞬间闪光跑到了OnlyNode 坐标系的Point(10,10)位置
    • 过了一秒钟后,闪光跑到了Cocos坐标系的Point(10,10)位置
    • OnlyNode不知道自己在哪里,更加无法找到Cocos坐标系的Point(10,10)在哪里,OnlyNode 自己很孤独想找到这个闪光在哪里。
    • 问题1:求闪光第一次出现在Cocos坐标系的坐标。
    • 问题2:求闪光第一次出现在Cocos坐标系的坐标。
    • 问题3:求闪光过了一分钟后,闪光在OnlyNode 坐标系的哪个坐标。
    • 闪光游走了一个晚上,第二天,OnlyNode还没有找到闪光,OnlyNode使用了AnchorPoint,把AnchorPoint设置为了Point(1,1) 希望能找到闪光,果真,设置完之后闪光再次出现在OnlyNode 坐标系的Point(10,10)位置
    • 一瞬间闪光跑到了OnlyNode 坐标系的Point(10,10)位置
    • 过了一秒钟后,闪光不见了。OnlyNode很希望,希望闪光能再次回来
    • 问题4:求设置AnchorPoint后,闪光出现在Cocos坐标系的坐标。
    • 问题5:你闪光消失了,闪光最大可能跑去哪里了?
  • 解:
    • 问题1:OnlyNode->convertToWorldSpace(Point(0,0));
    • 问题2:OnlyNode->convertToWorldSpace(Point(10,10));
    • 问题3:OnlyNode->convertToNodeSpace(Point(10,10));
    • 问题4:OnlyNode->convertToWorldSpaceAR(Point(0,0));
    • 问题5:这是一个笛卡尔坐标系游戏,只要OnlyNode在这里等就可以了,明天天黑就可以再次看到闪光。
      • OnlyNode->convertToWorldSpaceAR(Point(0,0));
// 把世界坐标转换到当前节点的本地坐标系中
Point convertToNodeSpace(const Point& worldPoint) const;
 
// 把基于当前节点的本地坐标系下的坐标转换到世界坐标系中
Point convertToWorldSpace(const Point& nodePoint) const;
 
// 基于Anchor Point把基于当前节点的本地坐标系下的坐标转换到世界坐标系中
Point convertToNodeSpaceAR(const Point& worldPoint) const;
 
// 基于Anchor Point把世界坐标转换到当前节点的本地坐标系中
Point convertToWorldSpaceAR(const Point& nodePoint) const;

开发者给出的代码from ptm-pose import project my_splice_data_annotated, spliced_ptms = project.project_ptms_onto_splice_events(my_splice_data, ptm_coordinates, chromosome_col = 'chromosome', strand_col = 'strand', region_start_col = 'region_start', region_end_col = 'region_end', event_id_col = 'event_id', gene_col = 'Gene name', dPSI_col='dPSI', coordinate_type = 'hg19') 运行后显示 my_splice_data_annotated, spliced_ptms = project.project_ptms_onto_splice_events(my_splice_data, ptm_coordinates, ^^^^^^^^^^^^^^^ NameError: name 'ptm_coordinates' is not defined 打开project.py文件找到 ptm_coordinates: pandas.DataFrame dataframe containing PTM information, including chromosome, strand, and genomic location of PTMs SE_events: pandas.DataFrame dataframe containing skipped exon event information from MATS A5SS_events: pandas.DataFrame dataframe containing 5' alternative splice site event information from MATS A3SS_events: pandas.DataFrame dataframe containing 3' alternative splice site event information from MATS RI_events: pandas.DataFrame dataframe containing retained intron event information from MATS MXE_events: pandas.DataFrame dataframe containing mutually exclusive exon event information from MATS coordinate_type: str indicates the coordinate system used for the start and end positions. Either hg38 or hg19. Default is 'hg38'. dPSI_col: str Column name indicating delta PSI value. Default is 'meanDeltaPSI'. sig_col: str Column name indicating significance of the event. Default is 'FDR'. extra_cols: list List of column names for additional information to add to the results. Default is None. separate_modification_types: bool Indicate whether residues with multiple modifications (i.e. phosphorylation and acetylation) should be treated as separate PTMs and be placed in unique rows of the output dataframe. Default is False. PROCESSES: int Number of processes to use for multiprocessing. Default is 1. 请问是我的输入有问题还是需要重新定义ptm_coordinates
最新发布
07-08
<think>我们正在处理一个Python的NameError错误,具体是`NameError: name 'ptm_coordinates' is not defined`。这个错误通常意味着我们尝试使用一个名为`ptm_coordinates`的变量或函数,但它在当前作用域中尚未定义。 根据用户提供的引用信息,我们注意到引用[1]提到“ptm_coordinates”可能是从某个文件(如sprites.plist)中获取的坐标数据。因此,我们可以推测用户可能在处理一个与坐标相关的程序,可能是游戏开发(如Cocos2D)或数据处理。 错误原因分析: 1. 变量未定义:在代码中使用`ptm_coordinates`之前,没有对其进行定义或赋值。 2. 作用域问题:变量可能定义在另一个作用域(如函数内部)中,而在当前作用域中不可用。 3. 拼写错误:可能是变量名拼写错误导致。 4. 未导入模块:如果`ptm_coordinates`是某个模块中的变量,可能忘记导入该模块。 解决方案: 1. 确保在使用`ptm_coordinates`之前已经定义它。例如,通过赋值: ```python ptm_coordinates = ... # 这里可以是具体的坐标数据,如列表或字典 ``` 2. 检查作用域:如果变量在函数内部定义,而你在外部使用,需要将其作为返回值传递出来,或者定义为全局变量(但不推荐滥用全局变量)。 3. 检查拼写:确认变量名的拼写是否正确。 4. 如果`ptm_coordinates`来自外部文件(如引用[1]中提到的plist文件),则需要先读取该文件并解析出坐标数据。例如,使用`plistlib`模块读取plist文件: ```python import plistlib with open('sprites.plist', 'rb') as f: data = plistlib.load(f) ptm_coordinates = data.get('ptm_coordinates') # 假设在plist文件中有一个键为'ptm_coordinates' ``` 注意:这里假设文件中有名为'ptm_coordinates'的键,实际键名需要根据文件内容确定。 5. 如果`ptm_coordinates`是某个类或模块的属性,确保已经正确导入。例如: ```python from some_module import ptm_coordinates ``` 根据引用[1]的上下文,我们猜测用户可能是在处理一个包含多个精灵坐标的plist文件,并希望使用这些坐标。因此,重点应该放在如何从plist文件中读取数据。 示例代码(读取plist文件): 假设我们有一个名为'sprites.plist'的文件,其中包含一个名为'ptm_coordinates'的键,其值是一个坐标字典或数组。 ```python import plistlib # 尝试打开并解析plist文件 try: with open('sprites.plist', 'rb') as f: plist_data = plistlib.load(f) # 获取ptm_coordinates,如果键不存在则返回None ptm_coordinates = plist_data.get('ptm_coordinates') if ptm_coordinates is None: print("警告:在plist文件中未找到'ptm_coordinates'键。") else: # 使用ptm_coordinates print(ptm_coordinates) except FileNotFoundError: print("错误:未找到sprites.plist文件。") except Exception as e: print(f"读取plist文件时出错:{e}") ``` 如果用户没有这个文件,或者文件中的键名不是'ptm_coordinates',那么需要根据实际情况调整。 另外,引用[2]提到“Errored Second”等术语,但似乎与当前问题关系不大,可能是其他引用。 总结: 首先检查变量`ptm_coordinates`是否在代码中定义。如果没有,则需要从外部文件(如plist)中读取,或者从其他来源获取。同时,注意文件路径和键名的正确性。 如果用户的问题是在特定的框架(如Cocos2D)中,可能需要查看框架文档是否有提供相关的方法来获取坐标。 最后,如果用户已经尝试了上述方法仍然无法解决,建议提供更多的代码上下文以便进一步分析。 §§相关问题§§ 1. 如何读取和解析plist文件? 2. 在Python中如何避免变量未定义的错误? 3. Cocos2D中如何处理精灵坐标?</think>### NameError: name 'ptm_coordinates' is not defined 解决方案 这个错误表示 Python 解释器无法识别 `ptm_coordinates` 变量或对象。以下是系统性的解决步骤: #### 1. **检查变量定义** - 确保在使用 `ptm_coordinates` 前已正确定义: ```python # 明确定义变量(示例) ptm_coordinates = [ (x1, y1), (x2, y2) ] # 坐标列表 ``` - 如果是**函数内部使用**,需确认: ```python def process_coordinates(): global ptm_coordinates # 声明使用全局变量 # 或通过参数传入 ptm_coordinates ``` #### 2. **验证数据来源** - 如果数据来自外部文件(如引用[1]中的 `sprites.plist`): ```python import plistlib # 处理plist文件 with open('sprites.plist', 'rb') as f: data = plistlib.load(f) ptm_coordinates = data.get('ptm_coordinates') # 检查键名是否匹配 ``` **关键检查**: - 文件路径是否正确 - 键名是否完全匹配(大小写敏感) - 文件格式是否支持(如 XML/binary plist) #### 3. **作用域排查** | 场景 | 解决方案 | |------|----------| | 在函数/类内部使用 | 添加 `global ptm_coordinates` 或通过参数传递 | | 在模块间使用 | 使用 `import module; module.ptm_coordinates` | | Jupyter Notebook 单元格 | 确保定义单元格已执行 | #### 4. **拼写和大小写验证** Python 变量名**严格区分大小写**: ```python # 错误示例 print(PTM_Coordinates) # 与 ptm_coordinates 不同 ``` 使用 IDE 的查找功能全局搜索 `ptm_coordinates` 确认一致性。 #### 5. **依赖库检查** 如果 `ptm_coordinates` 来自第三方库: - 确认库已安装:`pip show 库名` - 检查导入方式: ```python from some_module import ptm_coordinates # 直接导入变量 # 或 import some_module coords = some_module.ptm_coordinates ``` #### 6. **文件未加载的调试方法** ```python try: print(ptm_coordinates) except NameError: print("未找到变量!检查:") print("1. 文件路径 | 2. 变量作用域 | 3. 拼写") # 添加重新加载逻辑 reload_data() # 自定义重载函数 ``` #### 根本原因判断 根据引用[1]的上下文: > 引用[1]: Just for fun, open up sprites.plist... We can provide this to Cocos2D instead of typing in the coordinates manually! [^1] 最可能的原因是: 1. **数据文件未正确加载**(路径错误/格式错误) 2. **键名不匹配**(plist 中实际键名非 `ptm_coordinates`) 3. **作用域问题**(在函数内访问未声明全局变量) 建议优先检查 plist 文件内容: ```python import plistlib with open('sprites.plist', 'rb') as f: print(plistlib.load(f).keys()) # 打印所有键名 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值