cocos2d-x 坐标研究

本文详细解析了Cocos2d-x中四种坐标转换方法:convertToNodeSpace、convertToWorldSpace及其带AR后缀的版本。通过具体示例对比了不同方法在处理锚点时的区别,并附上了测试代码及运行结果。

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

今天晚上,对cocos2d-x里面的四个表示坐标的方法进行了一下研究,特意做了下笔记,如下:
    /** 
     * Converts a Point to node (local) space coordinates. The result is in Points.
     */
    CCPoint convertToNodeSpace(const CCPoint& worldPoint);
    
    /** 
     * Converts a Point to world space coordinates. The result is in Points.
     */
    CCPoint convertToWorldSpace(const CCPoint& nodePoint);
    
    /** 
     * Converts a Point to node (local) space coordinates. The result is in Points.
     * treating the returned/received node point as anchor relative.
     */
    CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);
    
    /** 
     * Converts a local Point to world space coordinates.The result is in Points.
     * treating the returned/received node point as anchor relative.
     */
    CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);

按照cocos2d-x的注释,可能很难理解出这几个方法有什么不同,特别是有没有AR后缀的。这里先给出结论:有AR的后缀的方法<convertToNodeSpaceAR,convertToWorldSpaceAR>在转化的时候,和参照物的锚点有关系,而没有AR后缀的方法<convertToNodeSpace,convertToWorldSpace>跟参照物的锚点没有关系,也就是永远都是以<0,0>作为锚点,换句话说如果参照物的描点不是<0,0>的话,要先假定参照物的锚点是<0,0>,得出在锚点为<0,0>的时候的坐标,然后以这个坐标参与转化计算
假设创建了两个CCSprite,node1锚点为(0,0),位置为(20,40),size为(40,40),node2锚点为(1,1)位置为(-5,-20),size为(40,40)

接下来,convertToNodeSpace:调用CCPoint point = node1->convertToNodeSpace(node2->getPosition());

将node2的坐标转化成相对于node1的本地坐标

cocos2d-x 坐标研究 - zjfzjf - zjfzjf
 

node1的锚点为(0,0)位置(20,40),node2的锚点为(1,1),位置(-5,-20),上面说过convertToNodeSpace作为参照物时,锚点的位置是(0,0),程序中设置的描点不起作用,碰巧,node1的锚点为(0,0),所以以(20,40)这个点做为参照物,方向为向右,向上为正方向,(-5,-20)相对于这个参考点就是(-25,-60)

convertToWorldSpace:调用CCPoint point = node1->convertToWorldSpace(node2->getPosition());
cocos2d-x 坐标研究 - zjfzjf - zjfzjf
 
是将node2的坐标转化成相对于node1的世界坐标,这个可以这样理解,因为世界坐标是固定的,node1的世界坐标只是在固定世界坐标的基础上做了平移,这边是(20,40),而node2相对于node1的世界坐标也只是做了同样大小的平移而已,也就是(-5,-20)通过(20,40)做了平移,结果(15,20)

convertToNodeSpaceAR就是把node1的坐标系原点设置在锚点的位置,这里的锚点是(0,0)所以转化之后和上面的convertToNodeSpace一样,结果也是一样的,convertToWorldSpaceAR同理


测试:
CCSprite *sprite1 = CCSprite::spriteWithFile("CloseNormal.png");
sprite1->setPosition(ccp(20,40));
sprite1->setAnchorPoint(ccp(0,0));
this->addChild(sprite1);
CCSprite *sprite2 = CCSprite::spriteWithFile("CloseNormal.png");
sprite2->setPosition(ccp(-5,-20));
sprite2->setAnchorPoint(ccp(1,1));
this->addChild(sprite2);
CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
CCLog("position = (%f,%f)",point1.x,point1.y);
CCLog("position = (%f,%f)",point2.x,point2.y);
CCLog("position = (%f,%f)",point3.x,point3.y);
CCLog("position = (%f,%f)",point4.x,point4.y);
运行结果:
position = (-25.000000,-60.000000)
position = (15.000000,20.000000)
position = (-25.000000,-60.000000)
position = (15.000000,20.000000)
和预算的一样


如果这时将sprite1的锚点设置成(0.5,0.5),对哪两个方法的转化会有影响呢?上面我们提到,convertToNodeSpace,convertToWorldSpace这两个方法会有影响的,他们在转化的时候,跟程序设置的锚点没有关系,横用(0,0)作为描点,所以在这两个方法进行转化的时候,我们要先计算出,以锚点(0,0)的坐标。这里实际上是以(0,20)这个坐标点在进行转化的。上面说过了,sprite的size为(40,40)。从上上面的分析,我们得出,convertToNodeSpace转化后为(-5,-40), convertToWorldSpace转化后为(-5,0) convertToNodeSpaceAR和convertToWorldSpaceAR则没有受到影响

sprite1->setAnchorPoint(ccp(0.5,0.5));
    CCPoint point5 = sprite1->convertToNodeSpace(sprite2->getPosition());
    CCPoint point6 = sprite1->convertToWorldSpace(sprite2->getPosition());
    CCPoint point7 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
    CCPoint point8 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
    
    CCLog("position = (%f,%f)",point5.x,point5.y);
    CCLog("position = (%f,%f)",point6.x,point6.y);
    CCLog("position = (%f,%f)",point7.x,point7.y);
    CCLog("position = (%f,%f)",point8.x,point8.y);

运算结果:
Cocos2d: position = (-5.000000,-40.000000)
Cocos2d: position = (-5.000000,0.000000)
Cocos2d: position = (-25.000000,-60.000000)
Cocos2d: position = (15.000000,20.000000)
总之,没有AR后缀在转化的时候,实际上是以参照物的左下角,向上,向右来建立坐标系的,而有AR后缀在转化的时候,以参照物的锚点,向上向右来建立坐标系的,可以通过实际运行下,更加容易理解

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
内容概要:本文深入探讨了利用历史速度命令(HVC)增强仿射编队机动控制性能的方法。论文提出了HVC在仿射编队控制中的潜在价值,通过全面评估HVC对系统的影响,提出了易于测试的稳定性条件,并给出了延迟参数与跟踪误差关系的显式不等式。研究为两轮差动机器人(TWDRs)群提供了系统的协调编队机动控制方案,并通过9台TWDRs的仿真和实验验证了稳定性和综合性能改进。此外,文中还提供了详细的Python代码实现,涵盖仿射编队控制类、HVC增强、稳定性条件检查以及仿真实验。代码不仅实现了论文的核心思想,还扩展了邻居历史信息利用、动态拓扑优化和自适应控制等性能提升策略,更全面地反映了群体智能协作和性能优化思想。 适用人群:具备一定编程基础,对群体智能、机器人编队控制、时滞系统稳定性分析感兴趣的科研人员和工程师。 使用场景及目标:①理解HVC在仿射编队控制中的应用及其对系统性能的提升;②掌握仿射编队控制的具体实现方法,包括控制器设计、稳定性分析和仿真实验;③学习如何通过引入历史信息(如HVC)来优化群体智能系统的性能;④探索中性型时滞系统的稳定性条件及其在实际系统中的应用。 其他说明:此资源不仅提供了理论分析,还包括完整的Python代码实现,帮助读者从理论到实践全面掌握仿射编队控制技术。代码结构清晰,涵盖了从初始化配置、控制律设计到性能评估的各个环节,并提供了丰富的可视化工具,便于理解和分析系统性能。通过阅读和实践,读者可以深入了解HVC增强仿射编队控制的工作原理及其实际应用效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值