1

我有一个使用 cocos2d-iphone 构建的相当简单的应用程序,但是我无法解决一个奇怪的定位问题。该应用程序使用精灵表,并且应用程序中有一个 Retina 和非 Retina 精灵表使用完全相同的图稿(当然分辨率除外)。应用程序中还有其他用于CCSprites标准和 -hd 后缀的艺术品。

在应用程序中,当应用程序启动时会创建一组精灵。这些最初创建CCSprites的在 Retina 和非 Retina 屏幕上的位置始终相同(且正确)。

// In method called to setup sprites when app launches
// Cache & setup app sprites
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: @"sprites.plist"];
sprites = [CCSpriteBatchNode batchNodeWithFile: @"sprites.png"];

hill = [CCSprite spriteWithSpriteFrameName: @"hill.png"];
hill.position = ccp( 160, 75 );
[sprites addChild: hill z: 1];

// ... [create more sprites in same fashion]
// NOTE: All sprites created here have correct positioning on Retina & non-Retina screens

当用户以某种方式点击屏幕时,会调用一个方法来创建另一组CCSprites(屏幕上和屏幕外),并为它们全部设置动画。其中一个精灵 ,hand始终在 Retina &非视网膜屏幕。其他(一组云)成功创建和动画,但它们的位置在 Retina 显示器上是正确的。在非 Retina 显示器上,每个云的起始位置不正确(对于xy或有时两者都不正确),并且它们在动画后的结束位置也是错误的。

我在下面的 on-touch 方法中包含了负责的代码,该方法创建了新的 sprite 并将它们动画化。同样,它在 Retina 显示器上按预期工作,但在非 Retina 屏幕上不正确。used 在应用程序启动时以相同的CCSprites方式创建,以设置应用程序中的所有初始精灵,它们始终具有正确的位置。

// Elsewhere, in a method called on touch
// Create clouds
cloud1 = [CCSprite spriteWithSpriteFrameName: @"cloud_1.png"];
cloud1.position = ccp(-150, 320);
cloud1.scale = 1.2f;

cloud2 = [CCSprite spriteWithSpriteFrameName: @"cloud_2.png"];
cloud2.position = ccp(-150, 335);
cloud2.scale = 1.3f;

cloud3 = [CCSprite spriteWithSpriteFrameName: @"cloud_4.png"];
cloud3.position = ccp(-150, 400);

cloud4 = [CCSprite spriteWithSpriteFrameName: @"cloud_5.png"];
cloud4.position = ccp(-150, 420);

cloud5 = [CCSprite spriteWithSpriteFrameName: @"cloud_3.png"];
cloud5.position = ccp(400, 350);

cloud6 = [CCSprite spriteWithSpriteFrameName: @"cloud_1.png"];
cloud6.position = ccp(400, 335);
cloud6.scale = 1.1f;

cloud7 = [CCSprite spriteWithSpriteFrameName: @"cloud_2.png"];
cloud7.flipY = YES;
cloud7.flipX = YES;
cloud7.position = ccp(400, 380);

// Create hand
hand = [CCSprite spriteWithSpriteFrameName:@"hand.png"];
hand.position = ccp(160, 650);

[sprites addChild: cloud1 z: 10];
[sprites addChild: cloud2 z: 9];
[sprites addChild: cloud3 z: 8];
[sprites addChild: cloud4 z: 7];
[sprites addChild: cloud5 z: 6];
[sprites addChild: cloud6 z: 10];
[sprites addChild: cloud7 z: 8];
[sprites addChild: hand z: 10];


// ACTION!!
[cloud1 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(70, 320)]];
[cloud2 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(60, 335)]];
[cloud3 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(100, 400)]];
[cloud4 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(80, 420)]];
[cloud5 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(250, 350)]];
[cloud6 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(250, 335)]];
[cloud7 runAction:[CCMoveTo actionWithDuration: 1.0f position: ccp(270, 380)]];
[hand runAction: handIn];

值得一提的是,在运行应用程序并在标准 iPhone 和 iPhone (Retina) 硬件选项之间切换时,我在 iOS 模拟器中看到了这种不正确的定位行为。我无法验证这种情况是否发生在实际的非 Retina iPhone 上,因为我没有。

然而,这是我唯一一次看到这种奇怪的定位行为发生(用户触摸后获得的不正确结果),并且由于我以完全相同的方式创建所有精灵(即,[CCSprite spriteWithSpriteFrameName:]然后position使用设置cpp()),我会特别感谢任何帮助追踪为什么这组精灵在非 Retina 屏幕上总是不正确的原因。

编辑/更新 我添加了一些额外的日志记录来准确调查创建的精灵发生了什么。以下是其中一种云的示例:

// Non-Retina
cloud1 position -- x: 70.000000 y: 320.000000
cloud1 anchor -- x: 0.500000 y: 0.500000
cloud1 size -- w: 384.000000 h: 576.000000
cloud1 origin -- x: -122.000008 y: 31.999989

// Retina
cloud1 position -- x: 70.000000 y: 320.000000
cloud1 anchor -- x: 0.500000 y: 0.500000
cloud1 size -- w: 172.800003 h: 121.800003
cloud1 origin -- x: -16.400003 y: 259.100006

我必须说我对此感到非常困惑。我也没有混淆这些日志。非 Retina 上的边界框比 Retina 上的大?而且这些宽度/高度值甚至与它们引用的图像的大小不匹配。也许精灵表/纹理内部发生了一些奇怪的事情?我也注意到起源不匹配。也许这也影响了输出?很奇怪,它只发生在这些精灵身上,没有其他精灵。

任何想法和建议表示赞赏。

4

4 回答 4

2

我可以想象两个原因:

  1. SD 图像不完全是 HD 图像大小的一半
  2. plist 中的图像命名错误

验证您的高清图像的宽度和高度是否正好是标清图像的两倍(反之亦然)。由于您是从 HD 缩小尺寸,因此请确保您的 HD 图像尺寸可被 2 整除。

plists 会发生一个常见的命名错误。通常你会有 image.png 和 image-hd.png。然而,对于纹理图集,这略有不同。你应该有 atlas.png 和 atlas-hd.png 文件和相关的 plist 文件,但是纹理图集中的图像应该参考 image.png 两个版本。一个典型的错误是将 image-hd.png 添加到 atlas-hd.png 纹理图集中。

不确定这些问题是否适用。当然听起来您可能想将日志记录添加到您的精灵位置,然后比较 Retina 与标准分辨率位置。如果这些位置正好偏移另一个版本的位置的一半或两倍,您就知道您有 Retina vs Non-Retina 定位错误。如果不是,则更有可能是您的定位或移动代码中存在错误。

于 2012-06-11T10:36:29.667 回答
0

我的猜测是替换你的 spritesheets 是诀窍,但直到模拟器完全覆盖了应用程序的原始版本,你才发现有任何区别。我遇到了图像缓存在模拟器中的问题,我不得不删除应用程序(摆动它,按 X),然后神奇地出现了更新的图像。

如有疑问,请在设备上进行测试。模拟器是很多“高度陌生”的原因。不值得。

于 2012-06-13T01:39:28.863 回答
0

我刚刚创建了一个测试应用程序并进行了测试。

所以对于没有视网膜的设备: ImageName.png - 对于 iPhone/iPod ImageName~ipad.png - 对于 iPad

对于具有视网膜显示的设备: ImageName@2x.png - 对于 iPhone/iPod ImageName@2x~ipad.png -- 对于 iPad

如果您的 iPhone 高分辨率图像和 iPad 高分辨率图像具有相同大小,您仍然可以使用 @2x。要加载图像,只需使用 [UIImage imageNamed:@"ImageName.png"]; 我刚刚在 iOS 5.1、5.0 和 4.3 的 iOS 模拟器上对其进行了测试。顺便说一句,为什么你应该使用@2x,仅此而已。

最主要的是你不应该在 iPhone 和 iPad 上使用相同的图形,因为 iPhone 和 iPad 的尺寸不同。如果您将使用相同大小的图形,则 iPad 视网膜显示器(如果您以前使用 iPhone 视网膜显示器)已经完成了图形。如果您要使用不同尺寸的图像,那么您将为 iPhone 和 iPad 使用不同的图像名称。所以在这一边你只需要添加@2x 后缀。这就是为什么你应该只使用@2x 后缀。- 这些是我的想法。

于 2012-06-13T11:18:04.237 回答
0

尽管问题消失了,但对此没有可行的答案。

我再次将所有图像修剪为 2 的幂,在此过程中减少了一些额外的空间。我将纹理/精灵表创建工具从 Zwoptex 换成了 TexturePacker,并创建了两个新的精灵表作为 PVR 而不是 PNG,并带有新的 .plist 文件。

我还决定将 cocos2d 库升级到最新的稳定版(我之前使用的是 1.0.1 稳定版之前的旧 RC 版本)。

没有进行任何代码更改,问题就消失了。奇怪的。

于 2012-06-12T06:19:55.453 回答