`
song020cn
  • 浏览: 63180 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

CCSpriteFrameCache添加plist时不同plist中存在重复的文件

阅读更多

 

最近在做一项工作,将基于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中。

 

分享到:
评论

相关推荐

    Window Plist文件 查看工具

    在Windows操作系统中,由于系统内核...在处理Plist文件时,用户应当根据自己的需求选择合适的工具,并注意定期更新以获取最新的功能和安全修复。同时,了解XML基础和Plist文件的结构将有助于更好地理解和利用这些工具。

    iOS开发中plist文件的简单读取

    在新创建的plist文件中,你可以直接编辑添加键值对或者数组元素,它们会以XML的形式展示。 接下来,我们将讨论如何在代码中读取 plist 文件。iOS SDK 提供了 `NSBundle` 和 `NSDictionary` 类来处理这一任务。以下...

    读取plist文件切割图集

    在游戏开发中,为了优化资源加载和性能,通常会将多张小图片打包成一个大图,即图集(Sprite Sheet)。这样的图集文件通常会伴随...在实践中,你可以根据具体需求调整代码,如添加错误处理、支持不同格式的图集文件等。

    cocos plist资源图片文件等

    在Cocos2d-x中,我们可以使用`CCSpriteFrameCache`类来加载和管理精灵帧,它可以从plist文件中读取信息,创建并缓存`CCSpriteFrame`对象。例如,`CCSpriteFrameCache::getInstance()-&gt;addSpriteFramesWithFile(...

    三级联动城市 plist 文件

    在IT行业中,"三级联动城市 plist 文件"是一个常见的概念,特别是在开发iOS应用或者网页时用于实现省市区选择功能。这个概念涉及到数据结构、文件格式以及前端或后端的数据交互。下面将详细介绍这些知识点。 首先,...

    iOS基础源码之 plist文件的读取例子

    在iOS开发中,Plist(Property List)文件是一种常见的数据存储格式,用于存储结构化的XML或二进制数据。Plist文件通常用来保存应用程序的配置信息、用户偏好设置或者简单的数据结构,如数组、字典、字符串、数字等...

    根据plist文件还原小图片

    开发者可以使用`CCSpriteFrameCache`类加载`plist`文件,该类会自动处理图集和帧数据,帮助你在游戏逻辑中方便地创建和显示精灵。 5. **Android适配**: 在Android平台上,由于硬件和系统兼容性问题,通常不直接使用...

    plist文件加密方法

    Plist(Property List)文件是苹果系统中用于存储配置信息或轻量级数据的文件,通常以XML或二进制格式存在。当这些文件包含敏感信息时,如用户登录凭证、设置或者应用内部数据,对其进行加密就显得尤为重要。本篇将...

    plist解压工具.rar

    Plist文件通常以XML或二进制格式存在,可以包含字符串、数字、日期、数组、字典等多种数据类型。在某些情况下,开发者可能会遇到Plist文件被碎片化的问题,这通常是由于文件被不完整地读取或写入导致的。在这种情况...

    iOS开发读取plist文件、iphone中plist文件的读写存 DEMO

    在iOS开发中,plist(Property List)文件是一种常用的存储数据的方式,它以XML或二进制格式保存数据,包括字符串、数字、数组、字典等类型。本DEMO旨在教授如何在iPhone和iPad上读取、写入和保存plist文件。下面...

    移动开发配置文件plist文件

    该文件是iOS开发plist文件,下载可以直接使用,为iOS开发

    plist文件解析CutPNG

    例如,当一个.plist文件与.png文件配合使用时,CutPNG可以帮助开发者快速解析.plist文件中的图片数据,并进行分解或编辑。这对于处理游戏中的人物技能、UI元素或其他图像资源非常有用。 在提供的压缩包中,`...

    plist文件示例程序

    Plist文件可以以XML或二进制格式存在。XML格式的人读性更强,便于调试和查看,而二进制格式则更小、更快,适用于存储大量数据。XML格式的Plist文件通常以`&lt;?xml ...&gt;`开头,`&lt;!DOCTYPE plist ...&gt;`定义文档类型,...

    Plist文件查看器

    Plist文件通常用于存储配置信息、应用设置或者轻量级的数据结构,它以XML或二进制的形式存在。本文将基于给定的“Plist文件查看器”项目,探讨Plist文件的结构、解析方法以及如何利用MFC(Microsoft Foundation ...

    plist文件编辑器

    - 在编辑敏感或关键的系统Plist文件时,应谨慎操作,以防影响系统的正常运行。 - 对于二进制格式的Plist文件,编辑前最好先将其转换为XML格式,以便于理解和编辑,然后再转换回去。 总之,“Plist文件编辑器”是一...

    Android plist 解析工具类及城市plist文件

    在Android开发中,有时我们需要处理iOS平台常用的.plist文件,这些文件通常用来存储XML格式的数据,如设置、配置信息等。本教程将详细讲解如何在Android环境中解析.plist文件,并提供一个实用的工具类和示例代码。 ...

    iOS省市区PList文件

    在集成这些PList文件时,开发者需要注意以下几点: 1. **资源管理**:确保PList文件在项目中正确引入,并在运行时能够被加载。 2. **性能优化**:如果数据量较大,可以考虑在应用启动时缓存到内存,避免频繁的磁盘...

    IOS plist文件详解

    iOS中的.plist文件是一种用于存储数据的简单且灵活的格式,全称为Property List,即属性列表。它是Apple操作系统(包括iOS和macOS)中常见的数据存储方式,尤其适用于配置文件、偏好设置或者轻量级的数据持久化。这...

    plist文件读写操作

    在iOS开发中,plist文件是一种常见的数据存储方式,它用于保存结构化数据,如数组、字典、字符串、数字和布尔值等。Plist是Property List(属性列表)的缩写,这种格式易于人类阅读,同时也能够被各种Apple设备和...

Global site tag (gtag.js) - Google Analytics