最近在做一项工作,将基于cocos2d-iphone游戏转换为跨平台版本。
以下为OC代码:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"game_ui.plist"]; [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"game_effect.plist"];
以下为Lua代码(我们的UI采用Lua编码):
display.addSpriteFramesWithFile('game_ui.plist') display.addSpriteFramesWithFile('game_effect.plist')
运行时,却发现了在OC版本中没有出现的异常“CCSprite is not using the same texture id”
跟踪该png文件,却发现health_bar.png文件同时存在于这两个plist。
这时候就产生疑问了,OC和C++版本的资源文件都是一样的。为什么cocos2d-x就会报异常呢?
好在cocos2d是开源的,所以开始研究addSpriteFramesWithFile的实现细节。
cocos2d-iphone
-(void) addSpriteFramesWithFile:(NSString*)plist { NSAssert(plist, @"plist filename should not be nil"); if( ! [_loadedFilenames member:plist] ) { NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist]; NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; NSString *texturePath = nil; NSDictionary *metadataDict = [dict objectForKey:@"metadata"]; if( metadataDict ) // try to read texture file name from meta data texturePath = [metadataDict objectForKey:@"textureFileName"]; if( texturePath ) { // build texture path relative to plist file NSString *textureBase = [plist stringByDeletingLastPathComponent]; texturePath = [textureBase stringByAppendingPathComponent:texturePath]; } else { // build texture path by replacing file extension texturePath = [plist stringByDeletingPathExtension]; texturePath = [texturePath stringByAppendingPathExtension:@"png"]; CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath); } [self addSpriteFramesWithDictionary:dict textureFilename:texturePath]; [_loadedFilenames addObject:plist]; } else CCLOGINFO(@"cocos2d: CCSpriteFrameCache: file already loaded: %@", plist); }
cocos2d-x
void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary* dictionary, CCTexture2D *pobTexture) { /* Supported Zwoptex Formats: ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1 ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+ */ CCDictionary *metadataDict = (CCDictionary*)dictionary->objectForKey("metadata"); CCDictionary *framesDict = (CCDictionary*)dictionary->objectForKey("frames"); int format = 0; // get the format if(metadataDict != NULL) { format = metadataDict->valueForKey("format")->intValue(); } // check the format CCAssert(format >=0 && format <= 3, "format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:textureFilename:"); CCDictElement* pElement = NULL; CCDICT_FOREACH(framesDict, pElement) { CCDictionary* frameDict = (CCDictionary*)pElement->getObject(); std::string spriteFrameName = pElement->getStrKey(); CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName); if (spriteFrame) { continue; } if(format == 0) { float x = frameDict->valueForKey("x")->floatValue(); float y = frameDict->valueForKey("y")->floatValue(); float w = frameDict->valueForKey("width")->floatValue(); float h = frameDict->valueForKey("height")->floatValue(); float ox = frameDict->valueForKey("offsetX")->floatValue(); float oy = frameDict->valueForKey("offsetY")->floatValue(); int ow = frameDict->valueForKey("originalWidth")->intValue(); int oh = frameDict->valueForKey("originalHeight")->intValue(); // check ow/oh if(!ow || !oh) { CCLOGWARN("cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenrate the .plist"); } // abs ow/oh ow = abs(ow); oh = abs(oh); // create frame spriteFrame = new CCSpriteFrame(); spriteFrame->initWithTexture(pobTexture, CCRectMake(x, y, w, h), false, CCPointMake(ox, oy), CCSizeMake((float)ow, (float)oh) ); } else if(format == 1 || format == 2) { CCRect frame = CCRectFromString(frameDict->valueForKey("frame")->getCString()); bool rotated = false; // rotation if (format == 2) { rotated = frameDict->valueForKey("rotated")->boolValue(); } CCPoint offset = CCPointFromString(frameDict->valueForKey("offset")->getCString()); CCSize sourceSize = CCSizeFromString(frameDict->valueForKey("sourceSize")->getCString()); // create frame spriteFrame = new CCSpriteFrame(); spriteFrame->initWithTexture(pobTexture, frame, rotated, offset, sourceSize ); } else if (format == 3) { // get values CCSize spriteSize = CCSizeFromString(frameDict->valueForKey("spriteSize")->getCString()); CCPoint spriteOffset = CCPointFromString(frameDict->valueForKey("spriteOffset")->getCString()); CCSize spriteSourceSize = CCSizeFromString(frameDict->valueForKey("spriteSourceSize")->getCString()); CCRect textureRect = CCRectFromString(frameDict->valueForKey("textureRect")->getCString()); bool textureRotated = frameDict->valueForKey("textureRotated")->boolValue(); // get aliases CCArray* aliases = (CCArray*) (frameDict->objectForKey("aliases")); CCString * frameKey = new CCString(spriteFrameName); CCObject* pObj = NULL; CCARRAY_FOREACH(aliases, pObj) { std::string oneAlias = ((CCString*)pObj)->getCString(); if (m_pSpriteFramesAliases->objectForKey(oneAlias.c_str())) { CCLOGWARN("cocos2d: WARNING: an alias with name %s already exists", oneAlias.c_str()); } m_pSpriteFramesAliases->setObject(frameKey, oneAlias.c_str()); } frameKey->release(); // create frame spriteFrame = new CCSpriteFrame(); spriteFrame->initWithTexture(pobTexture, CCRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height), textureRotated, spriteOffset, spriteSourceSize); } // add sprite frame m_pSpriteFrames->setObject(spriteFrame, spriteFrameName); spriteFrame->release(); } } void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist, CCTexture2D *pobTexture) { std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszPlist); CCDictionary *dict = CCDictionary::createWithContentsOfFileThreadSafe(fullPath.c_str()); addSpriteFramesWithDictionary(dict, pobTexture); dict->release(); }
OK!事情明了了。cocos2d-x比cocos2d-iphone多做了一步校验。
CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName); if (spriteFrame) { continue; }
然后,我将c++版本的plist加载顺序调整一下。搞定。
多说一句,一个png就不应该同时添加到两个plist中。
相关推荐
在Windows操作系统中,由于系统内核...在处理Plist文件时,用户应当根据自己的需求选择合适的工具,并注意定期更新以获取最新的功能和安全修复。同时,了解XML基础和Plist文件的结构将有助于更好地理解和利用这些工具。
在新创建的plist文件中,你可以直接编辑添加键值对或者数组元素,它们会以XML的形式展示。 接下来,我们将讨论如何在代码中读取 plist 文件。iOS SDK 提供了 `NSBundle` 和 `NSDictionary` 类来处理这一任务。以下...
在游戏开发中,为了优化资源加载和性能,通常会将多张小图片打包成一个大图,即图集(Sprite Sheet)。这样的图集文件通常会伴随...在实践中,你可以根据具体需求调整代码,如添加错误处理、支持不同格式的图集文件等。
在Cocos2d-x中,我们可以使用`CCSpriteFrameCache`类来加载和管理精灵帧,它可以从plist文件中读取信息,创建并缓存`CCSpriteFrame`对象。例如,`CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile(...
在IT行业中,"三级联动城市 plist 文件"是一个常见的概念,特别是在开发iOS应用或者网页时用于实现省市区选择功能。这个概念涉及到数据结构、文件格式以及前端或后端的数据交互。下面将详细介绍这些知识点。 首先,...
在iOS开发中,Plist(Property List)文件是一种常见的数据存储格式,用于存储结构化的XML或二进制数据。Plist文件通常用来保存应用程序的配置信息、用户偏好设置或者简单的数据结构,如数组、字典、字符串、数字等...
开发者可以使用`CCSpriteFrameCache`类加载`plist`文件,该类会自动处理图集和帧数据,帮助你在游戏逻辑中方便地创建和显示精灵。 5. **Android适配**: 在Android平台上,由于硬件和系统兼容性问题,通常不直接使用...
Plist(Property List)文件是苹果系统中用于存储配置信息或轻量级数据的文件,通常以XML或二进制格式存在。当这些文件包含敏感信息时,如用户登录凭证、设置或者应用内部数据,对其进行加密就显得尤为重要。本篇将...
Plist文件通常以XML或二进制格式存在,可以包含字符串、数字、日期、数组、字典等多种数据类型。在某些情况下,开发者可能会遇到Plist文件被碎片化的问题,这通常是由于文件被不完整地读取或写入导致的。在这种情况...
在iOS开发中,plist(Property List)文件是一种常用的存储数据的方式,它以XML或二进制格式保存数据,包括字符串、数字、数组、字典等类型。本DEMO旨在教授如何在iPhone和iPad上读取、写入和保存plist文件。下面...
该文件是iOS开发plist文件,下载可以直接使用,为iOS开发
例如,当一个.plist文件与.png文件配合使用时,CutPNG可以帮助开发者快速解析.plist文件中的图片数据,并进行分解或编辑。这对于处理游戏中的人物技能、UI元素或其他图像资源非常有用。 在提供的压缩包中,`...
Plist文件可以以XML或二进制格式存在。XML格式的人读性更强,便于调试和查看,而二进制格式则更小、更快,适用于存储大量数据。XML格式的Plist文件通常以`<?xml ...>`开头,`<!DOCTYPE plist ...>`定义文档类型,...
Plist文件通常用于存储配置信息、应用设置或者轻量级的数据结构,它以XML或二进制的形式存在。本文将基于给定的“Plist文件查看器”项目,探讨Plist文件的结构、解析方法以及如何利用MFC(Microsoft Foundation ...
- 在编辑敏感或关键的系统Plist文件时,应谨慎操作,以防影响系统的正常运行。 - 对于二进制格式的Plist文件,编辑前最好先将其转换为XML格式,以便于理解和编辑,然后再转换回去。 总之,“Plist文件编辑器”是一...
在Android开发中,有时我们需要处理iOS平台常用的.plist文件,这些文件通常用来存储XML格式的数据,如设置、配置信息等。本教程将详细讲解如何在Android环境中解析.plist文件,并提供一个实用的工具类和示例代码。 ...
在集成这些PList文件时,开发者需要注意以下几点: 1. **资源管理**:确保PList文件在项目中正确引入,并在运行时能够被加载。 2. **性能优化**:如果数据量较大,可以考虑在应用启动时缓存到内存,避免频繁的磁盘...
iOS中的.plist文件是一种用于存储数据的简单且灵活的格式,全称为Property List,即属性列表。它是Apple操作系统(包括iOS和macOS)中常见的数据存储方式,尤其适用于配置文件、偏好设置或者轻量级的数据持久化。这...
在iOS开发中,plist文件是一种常见的数据存储方式,它用于保存结构化数据,如数组、字典、字符串、数字和布尔值等。Plist是Property List(属性列表)的缩写,这种格式易于人类阅读,同时也能够被各种Apple设备和...