1. 事件管理机制 1.1 在2.2.2版中分散的事件分发器cc.TouchDispatcher, cc.MouseDispatcher, cc.KeyboardDispatcher, cc.AccelerometerDispatcher的所有功能都已经被合并到cc.eventManager,所以事件(鼠标,触摸,键盘,陀螺仪, 用户自定义)都将由cc.eventManager负责分发,也都将通过它进行注册。
更多关于cc.eventManager的信息可以查看这篇 详细文档 1.2 由于新的事件管理机制支持开发者在任何对象上绑定事件,所以在2.2.2版中的cc.Layer的事件处理相关函数都被删除了,具体被删除的函数列表如下: isMouseEnabledsetMouseEnabledsetMousePrioritygetMousePriorityregisterWithTouchDispatcherisTouchEnabledsetTouchEnabledgetTouchPrioritysetTouchPrioritygetTouchModesetTouchModeisAccelerometerEnabledsetAccelerometerEnabled (被移到cc.inputManager中) --> cc.inputManager.setAccelerometerEnabledsetAccelerometerInterval (被移到cc.inputManager中) --> cc.inputManager.setAccelerometerIntervalisKeyboardEnabledsetKeyboardEnabledsetKeypadEnabled
2. 游戏创建和配置流程 2.1 游戏创建
在3.0 alpha版本中, cc.Application 和 cc.AppControl 已经被移除了。
取而代之,我们重构了整个游戏创建的流程,在3.0中游戏项目创建将变得前所未有的简单,开发者可以使用 cc.game 来创建并开始游戏。 cc.game.onStart = function(){ cc.director.runScene(new MyScene());};cc.game.run();
更详细的信息请参见这个文档: cc.game 2.2 游戏配置
在2.2.2版中,游戏的配置列表(包含renderMode, fps...)与初始化代码混在cocos2d.js文件中,这样很不美观,所以3.0版中我们移除了 cocos2d.js 文件并将配置列表单独抽出来放在了 project.json 中,所以修改配置非常简单直观。
所有配置项可以参见这篇文档: project.json 2.3 Cocos2d-html5模块配置
Cocos2d-html5已经成为了在2d游戏开发的各个方面都非常有竞争力的游戏引擎,引擎拥有覆盖面非常广泛的特性。也正因此,我们的引擎比 市面上大多数的2d游戏引擎占用空间要更大。假设开发者只需要引擎中一部分特性,并且希望引擎占有空间更小,3.0版中我们提供了按需定制引擎的功能。首 先,引擎被分割成了不同的模块,所有模块定义可以参见 cocos2d-html5/moduleConfig.json ,开发者可以在 project.json 的 modules 字段中指定自己需要的模块。默认情况下, cocos2d 是默认模块,它包含完整的Cocos2d-html5,开发者可以将它替换为自己需要的子模块。
moduleConfig.json文档
3. 资源加载过程 3.1 cc.loader
cc.Loader 和 cc.FileUtils 已经被 cc.loader 单例对象所取代。 // 设定图片资源路径cc.loader.resPath = "./res";// 设定音频资源路径cc.loader.resPath = "./audio";// 加载资源并获得回调cc.loader.load(res, function(err){ if(err) return console.log("load failed");});
详细文档请参见: cc.loader 3.2 资源加载工具
3.0版不仅提供了更统一易用的cc.loader,还提供了一些配套工具: 异步函数调用模块(模仿node.js): cc.async 资源路径配置工具: cc.path
4. 属性风格API 4.1 使用Javascript风格的API对对象属性进行直接存取
旧API 新API
node.setPosition(x, y);
node.setRotation(r); node.x = x; node.y = y; | node.rotation = r; 如表格所示,函数调用可以被属性的直接賦值所替代。在3.0版中不仅是 x , y 和 rotation ,cc.Node及其所有子类的属性都可以使用这种方式存取。 4.2 attr 函数 3.0版同时还提供了一个更加强大的对象配置方法:类似jQuery的 attr 函数可以让你一次性配置多个属性。 node.attr({ x: 20, y: 20, anchorX: 0.5, anchorY: 0.5, width: 400, height: 300, scale: 2}); 详细文档和具体属性列表参见: Property API 5. 基本数据结构重构 移除的API: cc.integerToColor3Bcc.c4FFromccc3Bcc.c4FFromccc4Bcc.c4BFromccc4Fcc.PointSpritecc.GridSizecc.gcc.V2F_C4F_T2Fcc.V2F_C4F_T2F_Quad 修改的API: cc.Color3B, cc.Color4B, cc.Color4F --> cc.Colorcc.c3b, cc.c4b, cc.c4f --> cc.colorcc.c3BEqual, cc.c4FEqual --> cc.colorEqualcc.convertColor3BtoHexString --> cc.colorToHexcc.convertHexNumToColor3B --> cc.hexToColorcc.white --> cc.color.whitecc.yellow --> cc.color.yellowcc.blue --> cc.color.bluecc.green --> cc.color.greencc.red --> cc.color.redcc.magenta --> cc.color.magentacc.black --> cc.color.blackcc.orange --> cc.color.orangecc.gray --> cc.color.gray 详细文档 6. 单例对象 3.0版将以前的C++风格单例类重构为Javascript对象,方便开发者的使用。下面是被重构的类列表: // 引擎核心类cc.AudioEngine.getInstance() --> cc.audioEnginecc.Configuration.getInstance() --> cc.configurationcc.Configuration.purgeConfiguration() removedcc.Director.getInstance() --> cc.directorcc.EGLView.getInstance() --> cc.viewcc.ShaderCache.getInstance() --> cc.shaderCachecc.TextureCache.getInstance() --> cc.textureCachecc.TextureCache.purgeSharedTextureCache() --> cc.textureCache._clear()cc.AnimationCache.getInstance() --> cc.animationCachecc.AnimationCache.purgeSharedAnimationCache() --> cc.animationCache._clear()cc.SpriteFrameCache.getInstance() --> cc.spriteFrameCachecc.SpriteFrameCache.purgeSharedSpriteFrameCache() --> cc.SpriteFrameCache._clear()cc.SAXParser.getInstance() --> cc.saxParsercc.PlistParser.getInstance() --> cc.plistParsercc.Screen.getInstance() --> cc.screencc.TIFFReader.getInstance() --> cc.tiffReadercc.IMEDispatcher.getInstance() --> cc.imeDispatcher// 扩展包中的类ccs.GUIReader.getInstance() --> ccs.guiReaderccs.GUIReader.purge() --> ccs.guiReader.clear()ccs.SceneReader.getInstance() --> ccs.sceneReaderccs.SceneReader.purge() --> ccs.sceneReader.clear()ccs.DataReaderHelper --> ccs.dataReaderHelperccs.DataReaderHelper.purge() --> ccs.dataReaderHelper.clear()ccs.SpriteFrameCacheHelper.getInstance() --> ccs.spriteFrameCacheHelperccs.SpriteFrameCacheHelper.purge() --> ccs.spriteFrameCacheHelper.clear()ccs.ArmatureDataManager.getInstance() --> ccs.armatureDataManagerccs.ArmatureDataManager.purge() --> ccs.armatureDataManager.clear()ccs.ActionManager.getInstance() --> ccs.actionManagerccs.ActionManager.purge() --> ccs.actionManager.clear()ccs.TriggerMng.getInstance() --> ccs.triggerManagerccs.ObjectFactory.getInstance() --> ccs.objectFactory 详细文档 。 7. [Alpha 2新添加] 对象创建与类的继承 在Cocos2d-html5 2.2.x中,创建一个引擎对象比如cc.Sprite,开发者需要使用正确的 create 函数: var sprite = cc.Sprite.create(filename, rect);var sprite = cc.Sprite.createWithTexture(texture, rect);var sprite = cc.Sprite.createWithSpriteFrameName(spriteFrameName); 在Cocos2d-JS v3.0 alpha中,我们做到一个非常重要的API进化,所有 createXXX 都被合并为统一的 create 函数: var sprite = cc.Sprite.create(filename, rect);var sprite = cc.Sprite.create(texture, rect);var sprite = cc.Sprite.create("#" + spriteFrameName); 这个改动不仅适用于cc.Sprite,同样适用于引擎中所有有类似API的类,支持的类列表以及关于 create 函数改造的更详细信息请参见 create API文档 。 我们从未停止改进我们的引擎,所以在Cocos2d-JS v3.0 alpha2中,引擎支持 new 直接构造对象!构造函数和 create 函数共享完全相同的参数: var sprite = new cc.Sprite(filename, rect);var sprite = new cc.Sprite(texture, rect);var sprite = new cc.Sprite("#" + spriteFrameName); 与此同时,为了向后兼容性,所有 create 函数也被保留,使用哪种API风格完全是开发者自由的选择。更重要的是,这个改进使得类的继承变得前所未有的简单。开发者现在可以完全忽略所有的 initXXX 函数,你可以简单得通过重载 ctor 函数并使用正确的参数调用 this._super 即可完成对象的初始化: var Enemy = cc.Sprite.extend({ hp: 0, fileName: "enemy.png" ctor: function (hp) { this._super(fileName); this.hp = hp; }});var enemy1 = new Enemy(100); 如上所示,一个 init 函数都不需要调用,非常便于使用。所有cocos2d和扩展类都被重构以支持这种风格,而且JSB也同样完美支持。详细内容请参考关于 new 对象构造和类的继承的 详细文档 。 8. GUI控件 8.1 Cocostudio扩展包中的GUI控件已经被移出单独作为独立的扩展包:ccui,所以所有这些控件类的命名空间都从 ccs. 变为 ccui. 。这样做的原因在于这些UI控件不仅可以被Cocostudio使用,也可以被不使用Cocostudio的开发者单独使用。下面是所有被重命名的类: ccs.Layout --> ccui.Layoutccs.Margin --> ccui.Marginccs.MarginZero --> ccui.MarginZeroccs.LayoutParameter --> ccui.LayoutParameterccs.RelativeLayoutParameter --> ccui.RelativeLayoutParameterccs.CocosGUIVersion --> ccui.cocosGUIVersionccs.UIHelper --> ccui.helperccs.Widget --> ccui.Widgetccs.Button --> ccui.Buttonccs.CheckBox --> ccui.CheckBoxccs.ImageView --> ccui.ImageViewccs.LoadingBar --> ccui.LoadingBarccs.Slider --> ccui.Sliderccs.Text --> ccui.Textccs.TextAtlas --> ccui.TextAtlasccs.TextBMFont --> ccui.TextBMFontccs.TextField --> ccui.TextFieldccs.UILayer --> deleted 8.2 除此之外,3.0版还提供了一个新的富文本控件 ccui.RichText . 8.3 ccs.UILayer 已经从v3.0a中删除,Widget对象要加到场景中,直接通过addChild加到Node节点中就可以了。示例如下: // v2.2.2用法: widget必须要通过UILayer的addWidget方法加入到UILayer之后,再将UILayer加入场景才行var uiLayer = ccs.UILayer.create();uiLayer.addWidget(aWidget);var node = cc.Node.create();node .addChild(uiLayer);...//v3.0a用法: widget可以直接调用node的addChild方法,就可以加入场景了。var node = cc.Node.create();node .addChild(aWidget); 9. NodeGrid 3.0版提供了一个新的节点 cc.NodeGrid ,这个节点可以包含一个目标节点并允许在这个目标节点上应用 ActionGrid类型的动作。在2.2.2版中cc.Node可以直接应用这种动作,但是这个行为会在未来版本中被移除,因为我们希望cc.Node 的逻辑可以更纯粹。下面是2.2.2版与3.0版中的ActionGrid动作使用示例比较: // 2.2.2版var shaky = cc.Shaky3D.create( duration, cc.size(15,10), 5, false );var sprite = cc.Sprite.create();sprite.runAction( shaky );// 3.0版var shaky = cc.Shaky3D.create( duration, cc.size(15,10), 5, false );var sprite = cc.Sprite.create();var nodeGrid = cc.NodeGrid.create();nodeGrid.addChild( sprite );nodeGrid.runAction( shaky ); 注意:在Cocos2d-html5 3.0a版中,第一种方式仍然有效,但是如果你希望你的游戏可以运行在JSB中,那么必须使用第二种方式。另外,在3.0正式版中,第一种方式也将被移除。 10. JSB相关 虽然我们尽力使Cocos2d-html5和Cocos2d-JSB的API趋于一致,但是我们发现Web应用开发者和JSB原生开发者需求还是有 一定的区别,有一些需求也很难在两个不同平台上完全融合起来,所以我们提供下面这些仅在JSB项目中支持的API,如果你需要使用它们,请首先进行平台检 查。 if (cc.sys.isNative) { cc.fileUtils.isFileExist("filename");} 10.1 C++宏定义 在JSB项目中,有一些宏定义只可能在C++代码中修改,这些宏定义如下,它们都可以在ccMacros.h或ccConfig.h中找到: CC_ENABLE_STACKABLE_ACTIONSCC_ENABLE_GL_STATE_CACHECC_FIX_ARTIFACTS_BY_STRECHING_TEXELCC_DIRECTOR_STATS_INTERVALCC_DIRECTOR_STATS_POSITIONCC_DIRECTOR_FPS_POSITIONCC_DIRECTOR_DISPATCH_FAST_EVENTSCC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREADCC_NODE_RENDER_SUBPIXELCC_SPRITEBATCHNODE_RENDER_SUBPIXELCC_TEXTURE_ATLAS_USE_VAOCC_USE_LA88_LABELSCC_SPRITE_DEBUG_DRAWCC_SPRITEBATCHNODE_DEBUG_DRAWCC_LABELBMFONT_DEBUG_DRAWCC_LABELATLAS_DEBUG_DRAWCC_NODE_DEBUG_VERIFY_EVENT_LISTENERSCC_ENABLE_PROFILERSCC_LUA_ENGINE_DEBUGCC_USE_PHYSICSCC_ENABLE_SCRIPT_BINDING 10.2 [Alpha 2新添加] cc.fileUtils 在Cocos2d-html5中,cc.FileUtils已经被cc.loader取代了,但是在JSB项目中,有一些需求cc.loader无 法满足,所以我们决定将cc.FileUtils作为仅JSB支持的API开放出来。并且为了符合新的单例对象API风格,开发者可以直接通过 cc.fileUtils 来获取cc.FileUtils单例对象。下面是详细API列表: cc.fileUtilscc.fileUtils.fullPathForFilename(filename)cc.fileUtils.loadFilenameLookup(filename)cc.fileUtils.getStringFromFile(filename)cc.fileUtils.getByteArrayFromFile(filename) // [beta新添加]cc.fileUtils.createDictionaryWithContentsOfFile(filename) // [beta新添加]cc.fileUtils.isAbsolutePath(path)cc.fileUtils.isPopupNotify()cc.fileUtils.getValueVectorFromFile(filename)cc.fileUtils.writeToFile(object, filename)cc.fileUtils.getValueMapFromFile(filename)cc.fileUtils.isFileExist(filename)cc.fileUtils.purgeCachedEntries()cc.fileUtils.fullPathFromRelativeFile(filename, relativeFile)cc.fileUtils.getWritablePath()cc.fileUtils.addSearchPath(path) // [beta新添加]cc.fileUtils.setSearchPaths(pathArray) // [beta新添加]cc.fileUtils.getSearchPaths() // [beta新添加]cc.fileUtils.setSearchResolutionsOrder(orderArray) // [beta新添加]cc.fileUtils.getSearchResolutionsOrder() // [beta新添加] 请注意关于搜索路径的函数的使用,因为它们会导致在Cocos2d-html5和Cocos2d-JSB中资源路径的不一致,而最终使得游戏代码较 难维护。如果需要使用,我们建议在Web端和JSB中使用两套不同的资源映射表,同样的资源变量对应不同的资源路径,这样可以较轻松得维护代码。 10.3 cc.AssetsManager cc.AssetsManager是用于管理和使用远程服务器资源的类,它也支持简单的版本控制和更新。下面是它的使用方式: var manager = new cc.AssetsManager(manifestPath, storagePath);// As the process is asynchronised, you need to retain the assets manager to make sure it won't be released before the process is ended.manager.retain();if (!manager.getLocalManifest().isLoaded()) { cc.log("Fail to update assets, step skipped.");}else { var listener = new cc.EventListenerAssetsManager(manager, function(event) { switch (event.getEventCode()) { case cc.EventAssetsManager.UPDATE_PROGRESSION: var percent = event.getPercent(); cc.log("Download percent : " + percent); break; case cc.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: case cc.EventAssetsManager.ERROR_PARSE_MANIFEST: cc.log("Fail to download manifest file, update skipped."); break; case cc.EventAssetsManager.ALREADY_UP_TO_DATE: case cc.EventAssetsManager.UPDATE_FINISHED: cc.log("Update finished."); // You need to release the assets manager while you are sure you don't need it any more manager.release(); break; case cc.EventAssetsManager.ERROR_UPDATING: cc.log("Asset update error: " + event.getAssetId() + ", " + event.getMessage()); break; default: break; } }} 更多信息请参考 cc.AssetsManager文档 . 11. 其他API变动 11.1 cc.Broswser 和 sys 被 cc.sys 取代: 详细文档 . 11.2 一些 cc.AudioEngine 的API被删除: preloadMusicpreloadEffectisFormatSupportedpreloadSound 11.3 cc.SAXParser 一些 cc.SAXParser 的API被删除: tmxParsepreloadPlistunloadPlistgetNamegetExtgetList 同时添加 cc.PlistParser 用于解析plist文件: cc.SAXParser文档 11.4 cc.textureCache 的 addImageAsync 方法被移除,请统一使用 addImage . addImage(url) --> addImage(url)addImageAsync(url, target, callback) --> addImage(url, callback, target) [Alpha 2新添加] 新的 addImage 使用方式也被JSB支持了。 11.5 MenuItemFont 的两个方法被重命名以适应统一的API风格: fontName --> getFontNamefontSize --> getFontSize 11.6 cc.view 3.0版已经支持所有苹果设备的视网膜屏分辨率,你可以使用 cc.view.enableRetina(enableOrNot) 来开启或关闭这项功能,你也可以使用 cc.view.isRetinaEnabled() 来检测当前视网膜屏适配是否已经开启。最后,你可以通过 cc.view.getDevicePixelRat io() 来获取视网膜屏的像素缩放比例,在目前的苹果设备上,该比例返回值为2。默认情况下,视网膜屏适配在苹果设备上自动开启,如果希望改变这一行为,在关闭这项功能之后,你将需要调用一次 cc.view.setDesignResolutionSize(width, height, policy) 来让改变生效。 [Alpha 2新添加] cc.view会在移动浏览器上自动尝试进入全屏。现在我们为这项功能添加了开关函数,默认情况下这项功能仍然是开启的。 cc.view.enableAutoFullScreen(enabled); // enabled参数值可以是true或falsecc.view.isAutoFullScreenEnabled(); // 该函数返回当前值 11.7 其他被删除的API cc.IS_SHOW_DEBUG_ON_PAGEcc.COCOS2D_DEBUGcc.PLATFORM_WINDOWScc.PLATFORM_LINUXcc.PLATFORM_MACOScc.PLATFORM_ANDROIDcc.PLATFORM_IPHONEcc.PLATFORM_BLACKBERRYcc.PLATFORM_NACLcc.PLATFORM_EMSCRIPTENcc.HASH_FIND_INTcc.isAddedHiddenEventcc.originalCanvasSizecc.configcc.loadImgcc.loadImage.handlercc.computeImageFormatTypecc.tgaLoadccs.UILayer 11.8 其他添加的API: cc.warncc.errorcc.defineGetterSettercc.BuilderReader.registerController 11.9 其他修改的API: cc.Assert --> cc.assertcc.ArrayVerifyType --> cc.arrayVerifyTypecc.ArrayRemoveObject --> cc.arrayRemoveObjectcc.ArrayRemoveArray --> cc.arrayRemoveArraycc.ArrayAppendObjectsToIndex --> cc.arrayAppendObjectsToIndexcc.ArrayRemoveObjectAtIndex(arr, index) --> arr.splice(index, 1)cc.ArrayGetIndexOfValue(arr, value) --> arr.indexOf(value)cc.ArrayAppendObject(arr, addObj) --> arr.push(addObj)cc.ArrayAppendObjectToIndex(arr, addObj, index) --> arr.splice(index, 0, addObj)cc.ArrayGetIndexOfObject(arr, findObj) --> arr.indexOf(findObj)cc.ArrayContainsObject(arr, findObj) --> arr.indexOf(findObj) != -1// 修改大写函数为小写函数以符合命名规范cc.PRIORITY_SYSTEM --> cc.Scheduler.PRIORITY_SYSTEMcc.SWAP --> cc.swap // [Alpha 2新添加]cc.RANDOM_MINUS1_1 --> cc.randomMinus1To1 // [Alpha 2新添加]cc.RANDOM_0_1 --> cc.random0To1 // [Alpha 2新添加]cc.DEGREES_TO_RADIANS --> cc.degreesToRadians // [Alpha 2新添加]cc.RADIANS_TO_DEGREES --> cc.radiansToDegress // [Alpha 2新添加]cc.NODE_DRAW_SETUP --> cc.nodeDrawSetup // [Alpha 2新添加]cc.ENABLE_DEFAULT_GL_STATES --> cc.enableDefaultGLStates // [Alpha 2新添加]cc.DISABLE_DEFAULT_GL_STATES --> cc.disableDefaultGLStates // [Alpha 2新添加]cc.INCREMENT_GL_DRAWS --> cc.incrementGLDraws // [Alpha 2新添加]cc.CONTENT_SCALE_FACTOR --> cc.contentScaleFactor // [Alpha 2新添加]cc.POINT_POINTS_TO_PIXELS --> cc.pointPointsToPixels // [Alpha 2新添加]cc.SIZE_POINTS_TO_PIXELS --> cc.sizePointsToPixels // [Alpha 2新添加]cc.SIZE_PIXELS_TO_POINTS --> cc.sizePixelsToPoints // [Alpha 2新添加]cc._SIZE_PIXELS_TO_POINTS_OUT --> cc._sizePixelsToPointsOut // [Alpha 2新添加]cc.POINT_PIXELS_TO_POINTS --> cc.pointPixelsToPoints // [Alpha 2新添加]cc._POINT_PIXELS_TO_POINTS_OUT --> cc._pointPixelsToPointsOut // [Alpha 2新添加]cc.RECT_PIXELS_TO_POINTS --> cc.rectPixelsToPoints // [Alpha 2新添加]cc.RECT_POINTS_TO_PIXELS --> cc.rectPointsToPixels // [Alpha 2新添加]cc.CHECK_GL_ERROR_DEBUG --> cc.checkGLErrorDebug // [Alpha 2新添加]cc.CardinalSplineAt --> cc.cardinalSplineAt **[Alpha 2新添加]**// 常量cc.SPRITE_INDEX_NOT_INITIALIZED --> cc.Sprite.INDEX_NOT_INITIALIZED // [Alpha 2新添加]cc.DIRECTOR_PROJECTION_2D --> cc.Director.PROJECTION_2D // [Alpha 2新添加]cc.DIRECTOR_PROJECTION_3D --> cc.Director.PROJECTION_3D // [Alpha 2新添加]cc.DIRECTOR_PROJECTION_CUSTOM --> cc.Director.PROJECTION_CUSTOM // [Alpha 2新添加]cc.DIRECTOR_PROJECTION_DEFAULT --> cc.Director.PROJECTION_DEFAULT // [Alpha 2新添加]cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888 --> cc.Texture2D.PIXEL_FORMAT_RGBA8888cc.TEXTURE_2D_PIXEL_FORMAT_RGB888 --> cc.Texture2D.PIXEL_FORMAT_RGB888cc.TEXTURE_2D_PIXEL_FORMAT_RGB565 --> cc.Texture2D.PIXEL_FORMAT_RGB565cc.TEXTURE_2D_PIXEL_FORMAT_A8 --> cc.Texture2D.PIXEL_FORMAT_A8cc.TEXTURE_2D_PIXEL_FORMAT_I8 --> cc.Texture2D.PIXEL_FORMAT_I8cc.TEXTURE_2D_PIXEL_FORMAT_AI88 --> cc.Texture2D.PIXEL_FORMAT_AI88cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444 --> cc.Texture2D.PIXEL_FORMAT_RGBA4444cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1 --> cc.Texture2D.PIXEL_FORMAT_RGB5A1cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC4 --> cc.Texture2D.PIXEL_FORMAT_PVRTC4cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC2 --> cc.Texture2D.PIXEL_FORMAT_PVRTC2cc.TEXTURE_2D_PIXEL_FORMAT_DEFAULT --> cc.Texture2D.PIXEL_FORMAT_DEFAULTcc.Texture2D.setDefaultAlphaPixelFormat(format) --> cc.Texture2D.defaultPixelFormat = formatcc.Texture2D.getDefaultAlphaPixelFormat() --> cc.Texture2D.defaultPixelFormatcc.Texture2D.defaultAlphaPixelFormat() --> cc.Texture2D.defaultPixelFormatcc.dumpConfig --> cc.sys.dump// 公有转为私有cc.setup --> cc._setupcc.initDebugSetting --> cc._initDebugSettingcc.canvas --> cc._canvascc.drawingUtil --> cc._drawingUtilcc.renderContext --> cc._renderContextcc.gameDiv --> cc._gameDivcc.setContextMenuEnable --> cc._setContextMenuEnablecc.renderContextType --> cc._renderTypecc.CANVAS --> cc._RENDER_TYPE_CANVAScc.WEBGL --> cc._RENDER_TYPE_CANVAScc.mainRenderContextBackup --> cc._mainRenderContextBackupcc.RectFromString --> cc.spriteFrameCache._rectFromStringcc.PointFromString --> cc.spriteFrameCache._pointFromStringcc.SizeFromString --> cc.spriteFrameCache._sizeFromStringccs.CocoStudioVersion --> ccs.cocostudioVersion// 修正拼写错误ccs.DecotativeDisplay --> ccs.DecorativeDisplay 11.10 [Alpha 2新添加] Alpha 2中其他API改动 pauseSchedulerAndActions --> pauseresumeSchedulerAndActions --> resume cc.MoveBy.create(duration, x, y);cc.MoveBy.create(duration, cc.p(x, y)); getCString --> getStringsetCString --> setString ccs.comAttribute中重命名的函数 : cc.CallFunc的 initWithTarget 函数被重命名为 initWithFunction cc.MoveBy的 create 函数现在支持 x 和 y 分开作为位置参数 cc.Node中重命名的函数 : 12.[Beta新添加]Actions API变动 12.1 提供action的短方法创建方式 我们还针对action的相关类,增加了更加简单的创建方法,通过类名第一个字母改为小写就能创建出一个新的对象: 比如: var action = cc.MoveBy.create(2, cc.p(10, 10)) 这个action可以通过下面更简单的方式创建: var action = cc.moveBy(2,cc.p(10,10)) 12.2 重新设计ease actions 所有的ease action其实是修饰性的action, 他们无法脱离目标action独立使用. 其有效部分也只是update函数,所以我们可以添加一个 easing 到 cc.ActionInterval 中, 它可以接受不同的ease对象来实现不同的ease动作效果。 新旧使用方法的比较,新的调用方式采用链式的调用更加简单、易用: 旧的调用方式: var easeMoveBy = cc.EaseIn.create(cc.MoveBy.create(2, cc.p(100,50)),0.3); 新的调用方式: var easeMoveBy = cc.moveBy(2,cc.p(100,50)).easing(cc.easeIn(0.3); 12.3 关于 cc.Repeat, cc.RepeatForever, cc.Speed 的新设计 以下的 cc.Repeat, cc.RepeatForever, cc.Speed 都是修饰性的actions, 所以我们添加对应的函数 repeat , repeatForever , speed , getSpeed , setSpeed 到 cc.ActionInterval 中. 通过这邪恶函数,开发者可以将原来复杂的动作以清晰的方式进行表示。All these changes allow developers to write complex actions more clearly. 旧的调用方式: var anAction = cc.Sequence.create( cc.Speed.create(cc.Repeat.create(cc.EaseIn.create(cc.MoveBy.create(2, cc.p(100,50)),0.3), 5),1.7), cc.RepeatForever.create(cc.RotateBy.create(2, 30))); 新的调用方式: var anAction = cc.sequence( cc.moveBy(2,cc.p(100,50)).easing(cc.easeIn(0.3)).repeat(5).speed(1.7), cc.rotateBy(2,30).repeatForever()); 注意 : 所有的Actions的旧API都保留,并向前兼容。 12.4 新增Actions API列表 旧的调用方法 新的调用方法 | cc.Repeat.create(action, num) | action.repeat(num) cc.RepeatForever.create(action) | action.repeatForever() |
---|
cc.Speed.create(action, speed) | action.speed(speed) | cc.Speed.setSpeed(speed) | action.setSpeed(speed) | cc.Speed.getSpeed() | action.getSpeed() | cc.EaseIn.create(action, rate) | action.easing(cc.easeIn(rate)) | cc.EaseOut.create(action, rate) | action.easing(cc.easeOut(rate)) | cc.EaseInOut.create(action, rate) | action.easing(cc.easeInOut(rate)) | cc.EaseExponentialIn.create(action) | action.easing(cc.easeExponentialIn()) | cc.EaseExponentialOut.create(action) | action.easing(cc.easeExponentialOut()) | cc.EaseExponentialInOut.create(action) | action.easing(cc.easeExponentialInOut()) | cc.EaseSineIn.create(action) | action.easing(cc.easeSineIn()) | cc.EaseSineOut.create(action) | action.easing(cc.easeSineOut()) | cc.EaseSineInOut.create(action) | action.easing(cc.easeSineInOut()) | cc.EaseElasticIn.create(action) | action.easing(cc.easeElasticIn()) | cc.EaseElasticOut.create(action) | action.easing(cc.easeElasticOut()) | cc.EaseElasticInOut.create(action, rate) | action.easing(cc.easeElasticInOut(rate)) | cc.EaseBounceIn.create(action) | action.easing(cc.easeBounceIn()) | cc.EaseBounceOut.create(action) | action.easing(cc.easeBounceOut()) | cc.EaseBounceInOut.create(action) | action.easing(cc.easeBounceInOut()) | cc.EaseBackIn.create(action) | action.easing(cc.easeBackIn()) cc.EaseBackOut.create(action) | cc.EaseBackInOut.create(action) action.easing(cc.easeBackOut()) | action.easing(cc.easeBackInOut()) | 13.[Beta新变动]修改setText,getText为统一的API SetString, getString ccui.Text : setText --> setStringgetStringValue --> getString ccui.TextAtlas : getStringValue ==> getString ccui.TextBMFont : setText --> setStringgetStringValue --> getString ccui.TextField : setText --> setStringgetStringValue --> getString cc.EditBox : setText --> setStringgetText --> getString 其他详细文档列表: cc.log cc.spriteFrameCache cc.FileUtils 如何在JSB项目中使用extension more
Unity中制作游戏的快照游戏支持玩家拍快照 有些游戏支持玩家“拍快照”,也就是将游戏的精彩瞬间以图片的形式记录下来的功能。这个功能比较有趣,而且以后的用途也会很广,为此本节打算介绍:截取矩形区域内游戏视图,并将其显示在视图其它区域的方法。具体的操作步骤如下本文选自 Unity游戏开发技巧集锦 : ( 1 )在 Project 视图里,创建一个 C# 脚本文件,并命名为 ScreenTexture 。在此脚本中编写如下的代码: 01 using UnityEngine; 02 using System.Collections; 03 04 public class ScreenTexture : MonoBehaviour 05 { 06 // 公有成员 07 public int photoWidth = 50; // 矩形的宽度 08 public int photoHeight = 50; // 矩形的高度 09 public int thumbProportion = 25; // 截图的显示比例 10 public Color borderColor = Color.white; // 矩形框架的颜色 11 public int borderWidth = 2; // 矩形框的宽度 12 // 私有成员 13 private Texture2D texture; 14 private Texture2D border; 15 private int screenWidth; 16 private int screenHeight; 17 private int frameWidth; 18 private int frameHeight; 19 private bool shoot = false; 20 // 脚本初始化时,调用此函数 21 void Start () 22 { 23 screenWidth = Screen.width; 24 screenHeight = Screen.height; 25 frameWidth = Mathf.RoundToInt(screenWidth * photoWidth * 0.01f); 26 frameHeight = Mathf.RoundToInt(screenHeight * photoHeight * 0.01f); 27 texture = new Texture2D (frameWidth,frameHeight,TextureFormat.RGB24,false); 28 border = new Texture2D (1,1,TextureFormat.ARGB32, false); 29 border.SetPixel(0,0,borderColor); 30 border.Apply(); 31 } 32 // 运行游戏时,每帧都调用此函数 33 void Update () 34 { 35 // 鼠标左键按下的时候 36 if (Input.GetKeyUp(KeyCode.Mouse0)) 37 StartCoroutine(CaptureScreen()); 38 } 39 // 在 Game 视图上,绘制纹理 40 void OnGUI () 41 { 42 // 绘制矩形框的四个边 43 GUI.DrawTexture( 44 new Rect( 45 (screenWidth*0.5f)-(frameWidth*0.5f) - borderWidth*2, 46 ((screenHeight*0.5f)-(frameHeight*0.5f)) - borderWidth, 47 frameWidth + borderWidth*2, 48 borderWidth), 49 border,ScaleMode.StretchToFill); 50 GUI.DrawTexture( 51 new Rect( 52 (screenWidth*0.5f)-(frameWidth*0.5f) - borderWidth*2, 53 (screenHeight*0.5f)+(frameHeight*0.5f), 54 frameWidth + borderWidth*2, 55 borderWidth), 56 border,ScaleMode.StretchToFill); 57 GUI.DrawTexture( 58 new Rect( 59 (screenWidth*0.5f)-(frameWidth*0.5f)- borderWidth*2, 60 (screenHeight*0.5f)-(frameHeight*0.5f), 61 borderWidth, 62 frameHeight), 63 border,ScaleMode.StretchToFill); 64 GUI.DrawTexture( 65 new Rect( 66 (screenWidth*0.5f)+(frameWidth*0.5f), 67 (screenHeight*0.5f)-(frameHeight*0.5f), 68 borderWidth, 69 frameHeight), 70 border,ScaleMode.StretchToFill); 71 // 绘制矩形框中截取到的 Game 视图 72 if(shoot) 73 { 74 GUI.DrawTexture( 75 new Rect ( 76 10, 77 10, 78 frameWidth*thumbProportion*0.01f, 79 frameHeight*thumbProportion* 0.01f), 80 texture,ScaleMode.StretchToFill); 81 } 82 } 83 // 截取矩形框里的 Game 视图 84 IEnumerator CaptureScreen () 85 { 86 yield return new WaitForEndOfFrame(); 87 texture.ReadPixels( 88 new Rect( 89 (screenWidth*0.5f)-(frameWidth*0.5f), 90 (screenHeight*0.5f)-(frameHeight*0.5f), 91 frameWidth, 92 frameHeight), 93 0,0); 94 texture.Apply(); 95 shoot = true; 96 } 97 } 脚本代码中, 40 行的 OnGUI() 函数,使用 GUI.DrawTexture() 绘制了矩形框,以及矩形框中截取到的游戏视图; 84 行的 CaptureScreen() 函数,使用 texture.ReadPixels() 读取矩形框中的所有像素点,然后存储到 texture 中。触发“拍照”功能的操作是,在 Game 视图中的任意位置,单击鼠标左键,即 36 行代码实现的功能。 ( 2 )将脚本 ScreenTexture 赋予 Main Camera ,然后选中 Main Camera ,在 Inspector 视图里可以设置脚本组件的一些属性,如图 2-19 所示 本文选自 Unity游戏开发技巧集锦 。 图 2-19 Main Camera 上 ScreenTexture 脚本组件的各属性 图 2-20 当前的 Scene 视图 ( 3 )为游戏的场景添加一些几何体,并调整它们各自的位置,如图 2-20 所示。 ( 4 )运行游戏,当在 Game 视图中的任意位置,单击鼠标左键的时候,可在视图的左上角看到矩形框中截取到的游戏视图,如图 2-21 所示 本文选自 Unity游戏开发技巧集锦 。 图 2-21 运行游戏,查看截图的效果
[root @localhost petrify]# ./configure bash: ./configure: 没有那个文件或目录 没有./configure 是不支持C编译,装机的时候,没有装C语言 则安装以下rpm包 yum -y install ntp vim- enhanced gcc gcc-c++ gcc-g77 flex bison autoconf automake bzip2-devel \ ncurses-devel openssl-devel libtool* zlib-devel libxml2-devel libjpeg-devel libpng-devel libtiff-devel \ fontconfig-devel freetype-devel libXpm-devel gettext-devel curl curl-devel pam-devel \ e2fsprogs-devel krb5-devel libidn libidn-devel 当然也不全是这样的,像mysqli中.... http://blog.chinaunix.net/u3/117528/showart_2287937.html
原理介绍:使用nstd工具进行进程崩溃时内存和堆栈转储。 编译Release版本时打开调试选项,将exe和pdb文件一起发布。 2.使用批处理命令设置Windows系统在进程崩溃时调用的调试器为ntsd @reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /v "Auto" /t REG_SZ /d "1" /f 该批处理指令,设置AeDebug调用前是否需要弹消息框确认?默认为0,设置1表示自动处理不弹确认框。如果大家安装过Visual Studio,可能都遇到过下列弹框:
这就是VS设置了AeDebug调试器后,遇到进程崩溃,然后弹框确认是否要附加到该进程进行调试的过程。 然后设置ntsd的调试转储指令: @reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug" /v "Debugger" /t REG_SZ /d "D:\Dump\ntsd.exe -p %%ld -e %%ld -g -c \".dump /ma /u D:\Dump\dump.dmp; .logopen /t D:\Dump\dump.txt; .time; .echo Process Status:; ^|; .echo Thread Status:; ^~; .echo Stack Status:; kpn; .logclose; q\"" /f 我把的ntsd程序拷贝到d:\dump目录。 -p %%ld 传入进程ID,-c 执行dump指令:echo 打印线程信息,线程堆栈,最后再退出。 批处理安装脚本和ntsd程序我都已经打好包了,可以到 这里下载 。 3.下面通过一个实例来演示下效果: #include void test2() { int a = 1; int b = 0; int c = a/b; } void test1() { test2(); } int main(int argc, char** argv) { test1(); return 0; } 通过除0错误来构造一次崩溃,test1和test2是为了演示调用堆栈。 通过本方法抓取的堆栈文本如下: Opened log file 'D:\Dump\dump_22d4_2014-09-30_15-15-33-062.txt' Debug session time: Tue Sep 30 15:15:33.063 2014 (GMT+8) System Uptime: 2 days 3:35:54.545 Process Uptime: 0 days 0:00:00.923 Kernel time: 0 days 0:00:00.015 User time: 0 days 0:00:00.000 Process Status: . 0 id: 3854 attach name: D:\test\CoreDump\DumpExampleNormalStack.exe Thread Status: . 0 Id: 3854.3138 Suspend: 1 Teb: 7ffdf000 Unfrozen Stack Status: *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\SYSTEM32\ntdll.dll - # ChildEBP RetAddr 00 002dfb2c 01321038 DumpExampleNormalStack!test2(void)+0x18 01 002dfb34 01321048 DumpExampleNormalStack!test1(void)+0x8 02 002dfb3c 01321159 DumpExampleNormalStack!main(int argc = 1, char ** argv = 0x003ea488)+0x8 *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\system32\kernel32.dll - 03 002dfb84 76e2ee1c DumpExampleNormalStack!__tmainCRTStartup(void)+0xfe WARNING: Stack unwind information not available. Following frames may be wrong. 04 002dfb90 77ba37eb kernel32!BaseThreadInitThunk+0x12 05 002dfbd0 77ba37be ntdll!RtlInitializeExceptionChain+0xef 06 002dfbe8 00000000 ntdll!RtlInitializeExceptionChain+0xc2 Closing open log file D:\Dump\dump_22d4_2014-09-30_15-15-33-062.txt 切记:在Release版本中需要把调试选项打开,而且生成的pdb文件和exe要放在同一目录下。 批处理安装脚本和ntsd程序我都已经打好包了,可以到 这里下载 。 如果是查找内存泄漏问题,可以参考本人另一篇 博文 。如果需要用谷歌查询技术问题,可以使用 这里 。
unity中 一般都用coroutine(协同程序,协程)实现定时任务,自己写Timer and Invoke 也可以实现,主要分析unity中的coroutine的实现原理, coroutine 比如WaitForSeconds 内部都是迭代后,添加到CallDelay的 中 给DelayedCallManager管理,内部存储结构是一个multiset(讲道理为什么不用map),该定时器的触发条件是CallBack的时间到了,通过长时间线(时间戳)来处理,而不是每一帧Tick一次,排序值就是CallBack的time,这种非顺序容器(物理排列)的一个好处就是在遍历的时候可以动态删除添加,而不影响整体排序值,删除和添加代价都在很小范围内,而不会像vector那样数据前移,基于稳定排序后,在multiset中的排序值始终是按照添加顺序排序(同一个时间戳情况下)。如果排序插入的结果不是稳定 的那么会出BUG,coroutine的调用顺序 一定情况下不会按照StartCoroutine的顺序执行。 即StartCoroutine来做定时任务 并没有性能优势。更多的是写法上的优雅,因此不建议大量使用 TestCode
内部再对WaitForSeconds 添加到定时器任务,达到协同程序的目的 发起添加一个定时器CallBack,coroutine内部IEnumerator后 也是发起calldelayed 如果是0.0f的话,当前Update不处理,下一次Update才处理time=-1f calback update coroutine内部获得 IEnumerator后的处理
从零开始开发一款H5小游戏(一) 重温canvas的基础用法 https://segmentfault.com/a/1190000005892330 canvas自适应屏幕大小 http://www.cnblogs.com/mihoutaoguniang/p/5998511.html [Canvas前端游戏开发]——FlappyBird详解 http://web.jobbole.com/84771/ 用Phaser来制作一个html5游戏——flappy bird (一) UGUI的优点新UI系统四 开源 新UI系统是开源的,所以开发者可以看到新UI系统实现的源码,并加以修改和使用。 开源授权协议——MIT/X11 Unity所搭载的新UI系统,是在开源授权协议MIT/X11之下被公开的!所以开发者可以查看、修改其中的源码,来为己所用!提示:MIT/X11开源授权协议的查看网址是:http://opensource.org/licenses/MIT。 源代码托管网站——BitBucket 新UI系统的源代码被托管在BitBucket上,读者可以从此网站上下载源码,网址如下,打开的页面所示。https://bitbucket.org/Unity-Technologies/ui 单击页面左侧列表中的Downloads选项以后,进入的页面,单击Download repository链接即可开始源代码的下载,下载到的源码压缩包,及其中的文件和文件夹。 查看源代码项目 读者可以使用Visual Studio(微软提供的代码编辑器)或者MonoDevelop(Unity自带的代码编辑器),打开新UI系统源代码项目。以MonoDevelop为例,选中从源码压缩包中解压出来的文件UISystem.sln,右击鼠标从打开方式中选择MonoDevelop。 在MonoDevelop中,被打开的项目结构如图1-11所示。此项目中就包含了新UI系统的所有源代码,开发者可以任意查看和修改。 提示:有关此源代码项目的更多介绍,读者可以查看源代码压缩包解压出来的文件README.md。此文件是以md为后缀的文本文件,在Windows平台上,推荐使用MarkdownPad对其进行查看和编辑(使用免费的版本),其官方软件的下载网址如下,页面如图1-12所示。另外,主页上也显示了此软件打开md文件的效果图。 http://www.markdownpad.com/ 图1-12 MarkdownPad编辑器官网主页 加密主要包含通信数据和存储数据加密,目的都是为了保证其传送和储存的隐秘性,从而保证数据的安全。目前常见的加密方式有对称加密、非对称加密、hash加密、hash加盐加密等,这些在游戏中都会用的,我们会对其用途以及缺陷一一说明,当然了,为了保证其加密算法的安全以及高效,我们也会介绍几种自定义的加密算法,看看加密如何来维护我们的数据安全。 1、对称加密 对称加密算法是应用较早的加密算法,技术成熟。主要就是对密钥的一个维护,发送方把数据和密钥通过一定的加密算法处理后,发送给接收方,接受方接到之后在使用相同密钥及算法的逆算法对密文进行解密。这就是一般的对称加密算法过程。常见的对称加密算法有AES、 DES , 3DES ,TDEA, Blowfish , RC5 , IDEA 等,建议用AES,速度快,安全性也可以。 对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。缺点主要就是密钥需要双方都有,如果密钥被窃取,那么加密就会比第三方破解,特别是游戏中,密钥如果存放在客户端中,容易被破解反编译到。 我们可以采取登陆消息和逻辑消息采用不同的密钥,登陆验证通过之后,服务器为每个用户分配不同的密钥,然后把逻辑密钥传送给客户端,以此保证密钥的不确定性,从而增加游戏的安全。 2、非对称加密 非对称加密算法使用两把完全不同但又是完全匹配的一对钥匙— 公钥 和 私钥 。在使用不对称加密算法加密文件时,只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。这对于对称加密算法来说,又安全了一步,也是目前https常用的加密方式,公钥可以分配和暴露给所有想要访问的请求者,但密钥一定牢牢的掌握在服务器这边,如此对通信来说,安全性有保证。常用的加密算法,RSA,DSA,ECC。 非对称加密算法,优点就是安全,但缺点就是不够快,比较耗费cpu,如果在游戏中每一次消息都有其加密,对cpu的损耗还是挺高的,所以游戏中一般不用这种加密方式,当然了也看游戏类型,如果对这方面的性能要求不高,安全性要求有很高,采用业务科厚非(那个游戏这么傻啊)。 3、hash加密 hash加密,就是常见的使用MD5、SHA1等单向HASH算法保护密码,使用这些算法后,无法通过计算还原出原始密码,而且实现比较简单也高效,因此很多互联网公司都采用这种方式保存用户密码。 但安全性越来越担忧了,因为随着彩虹表技术的兴起,可以建立彩虹表进行查表破解,目前这种方式已经很不安全了。 4、hash 加盐加密 hash加密既然容易被彩虹表破解,那么可以采用加盐、多次HASH等扩展,这样可以在一定程度上增加破解难度。常见的方式也是发送方和接受方,维护一个盐池,加密和解密的时候加上这一段盐池来进行hash。 不过这种算法又回到了对称加密中对密钥的保护问题了,如果盐池泄露,别人依然会破解。 怎么办?有人又想出了,让盐池随机的方式,比如PBKDF2算法,原理大致相当于在HASH算法基础上增加随机盐,并进行多次HASH运算,随机盐使得彩虹表的建表难度大幅增加,而多次HASH也使得建表和破解的难度都大幅增加。一次密码验证过程进行1000次HASH运算,对服务器来说可能只需要1ms,但对于破解者来说计算成本增加了1000倍,而至少8字节随机盐,更是把建表难度提升了N个数量级,使得大批量的破解密码几乎不可行,该算法也是美国国家标准与技术研究院推荐使用的算法。 5、自定义加密 终于到这个了,以上那么多高大上的加密算法,都是业界比较成熟的算法,好处是处处有API支持也有人实现,拿来就用,坏处也是,算法格式规整透明,除了非对称算法,都有其对应的破解方式。游戏的加密要怎样?安全、安全,高效、高效,你不能一个加密算法就耗费我100ms的cpu吧,太浪费了。 我们可以尝试一种动态加密的方式,就是每一次请求保证用不同的密钥,这样即便一个消息被截取破解了,下一次密钥又不一样,如此破解者会比较崩溃。怎么做?我简单说下思想。 每个消息必须有唯一id,一个是防止消息重放,一个可以用来做我们的加密。比如我们初始的时候有一个密码池 A=【1,2,3,4,5】,每次消息从服务器发送出去的时候,消息ID都+1, 当前密钥=A.index(消息ID%A.length),如此就能保证每次密钥不一样,具体拿到密钥如何加密,完全可以用自己的加密方式,比如把二进制一部分截取通过密钥移位操作,或者算法运算都可以。 我们的目的一个保证密钥动态,一个就是保证算法足够高效。 算法 | 特点 | 有效破解方式 | 破解难度 | 其它 | 算法名字 |
---|
对称加密 | 可以解密出明文 | 获取密钥 | 中 | 需要确保密钥不泄露 | AES,3DES 非对称加密 | HASH加密 | 加盐HASH | Pbkdf2 | 自定义算法 一对钥匙— 公钥 和 私钥 | 简单,高效 | 对hash加盐处理 | 对hash的盐池进行随机处理 | 非标准,高效,安全 获取私钥 | 碰撞、彩虹表 | 碰撞、彩虹表 | 无 | 无 高 | 中 | 中 | 难 | 难 效率低,安全性高 | | 需要确保“盐”不泄露 | 随机盐池不能太大,8个字节比较合适 | 算法的灵活性 RSA,DSA,ECC,DH | MD5,SHA1,SHA1256 | 同上 | 同上 | 动态密钥 | ----------------------------------------------------------------------------- 想看更多有趣原创的技术文章,扫描关注公众号。 关注个人成长和游戏研发,推动国内游戏社区的成长与进步。 此类工具搜索过一些,都不要好用,于是决定自己实现一个。 大图集拆开为小图片,由于是工具,于此效率不太重要,直接用Cocos2dx随手写了一个。 基本思想是直接读取,然后把该SpriteFrame输出为文件即可 #include "HelloWorldScene.h" #include "cocostudio/CocoStudio.h" #include "ui/CocosGUI.h" #include #include #include #include #include #include #include USING_NS_CC; using namespace std; using namespace cocostudio::timeline; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { // 1. super init first if (!Layer::init()) { return false; } vector files; const char *TEM_WORK_FILE_NAME = "filelist.txt"; string path = "res"; string cmd_txt = "cmd.exe /c DIR " + path + " /S /B > "; cmd_txt += TEM_WORK_FILE_NAME; system(cmd_txt.c_str()); fstream f; f.open(TEM_WORK_FILE_NAME, ios::in); vector _queue; string buf; while (getline(f, buf)) { // cout << buf << " ... " << endl; // cout<WriteToFile(); f.close(); //FileUtils::getInstance()->removeFile(TEM_WORK_FILE_NAME); //system("pause"); //return 0; //开始转换 // vector files; // //files.push_back("game_1_1.plist"); //files.push_back("game_1_2.plist"); //files.push_back("game_1_3.plist"); /*files.clear(); files.push_back("ui/awake.plist"); files.push_back("ui/yingxiongfuben_1.plist"); files.push_back("ui/yuanbaobiaoche.plist"); files.push_back("ui/xingkong2.plist"); files.push_back("ui/synthesis_equipment_4.plist"); files.push_back("ui/updateRecommend3.plist"); files.push_back("ui/shenmishangcheng.plist"); */ for (auto & name : files) { string dir = name.substr(0, name.size() - strlen(".plist")); //log((FileUtils::getInstance()->getWritablePath() + "/" + dir).c_str()); FileUtils::getInstance()->removeDirectory(FileUtils::getInstance()->getWritablePath() + "/" + dir); FileUtils::getInstance()->createDirectory(FileUtils::getInstance()->getWritablePath() + "/" + dir); SpriteFrameCache::getInstance()->addSpriteFramesWithFile(name); auto mapp = SpriteFrameCache::getInstance()->_spriteFrames; for (auto & cp : mapp) { auto sp = Sprite::createWithSpriteFrameName(cp.first.c_str());// Sprite::createWithSpriteFrameName("accomplishTitle.png"); sp->setPosition(sp->getTextureRect().size.width / 2, sp->getTextureRect().size.height / 2 ); this->addChild(sp); if (sp->getTextureRect().size.width <= 0 || sp->getTextureRect().size.height <= 0) {//invalid sprite continue;; } log((" out:" + dir + "/" + cp.first).c_str()); auto re = RenderTexture::create(sp->getTextureRect().size.width, sp->getTextureRect().size.height); re->begin(); sp->visit(Director::getInstance()->getRenderer(), Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_TEXTURE), 0); re->end(); string path = dir + "/" + cp.first; re->saveToFile(path); } SpriteFrameCache::getInstance()->removeSpriteFramesFromFile(name); TextureCache::getInstance()->removeAllTextures(); SpriteFrameCache::getInstance()->removeUnusedSpriteFrames(); } //Director::getInstance()->end(); return true; } 通过公式改变材质Color属性,实现黑白图片效果。 Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _GrayImage ("ChangeGray",float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; half4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float2 texcoord : TEXCOORD0; half4 color : COLOR; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float _GrayImage; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.color = v.color; o.texcoord = v.texcoord; return o; } fixed4 frag (v2f i) : COLOR { fixed4 col; if (_GrayImage == 1) { col = tex2D(_MainTex, i.texcoord); float grey = dot(col.rgb, float3(0.299, 0.587, 0.114)); col.rgb = float3(grey, grey, grey); } else { col = tex2D(_MainTex, i.texcoord) * i.color; } return col; } ENDCG } } } #####一、步骤 1.新建一个场景(命名为:005_textTween) 2.创建一个text 3.创建一个脚本(myText) 4.之前对游戏物体做一个动画 是通过Rect Transform 5.使用Dotween里面的一个方法DOText进行一个文本的动画 (如果原来的text有文字,在动画过程中把原有的文字替换掉) #####二、code using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 引用UI的命名空间 using DG.Tweening; public class myText : MonoBehaviour { private Text text; //文本 // Use this for initialization void Start () { text = this.GetComponent (); // 直接获取游戏物体 text.DOText("DOText是用来动画显示text的,接下来,开始动画了,效果是一个字一个字显示的",4,);//richtextEnabled 第三个参数是一个富文本 } // Update is called once per frame void Update () { } }
A tween's life When you create a tween it will play automatically (unless you change the global defaultAutoPlay behaviour) until it completes all its loops. When a tween is complete it is automatically killed (unless you change the global defaultAutoKill behaviour), which means you won't be able to use it anymore. If you want to reuse the same tween, just set its autoKill behaviour to FALSE (either by changing the global autoKill settings for all tweens, or by chaining SetAutoKill(false) to your tween). If your tween's target becomes NULL while a tween is playing errors might happen. You'll have to either be careful or activate the safe mode #####一、补间的生活 ######当您创建补间时,它将自动播放(除非您更改全局 defaultAutoPlay 行为),直到它完成所有循环。 ######当补间完成时,它会自动被杀死(除非您更改全局 defaultAutoKill 为),这意味着您将无法再使用它。 ######如果要重复使用相同的补间,只需将其autoKill行为设置为FALSE(通过更改所有tweens 的 全局autoKill 设置,或将 SetAutoKill(false) 链接到补间)。 ######如果补间的目标在补间的时候变为空,可能会发生错误。您必须小心或激活 安全模式 #####二、 动画的声明周期 Chained callbacks 常用--- OnComplete(TweenCallback callback) 设置一个回调,在tween到达完成时触发,所有循环都包含在内。 OnKill(TweenCallback callback) 设置一个回调,在tween被杀死的那一刻被触发。 OnPlay(TweenCallback callback) 设置回调,当补间设置为播放状态时,在任何最终延迟之后将被触发。每次补间从暂停状态恢复播放时也称为。 OnPause(TweenCallback callback) 设置回调,当补间状态从播放状态更改为暂停时将被触发。如果补间程序的autoKill设置为FALSE,则在补间程序完成时也会调用此函数。 OnRewind(TweenCallback callback) 设置一个回调,Rewind通过在向后播放时通过调用或达到开始位置来重新播放补间即将触发。 注意:重新卷绕已被重绕的补间不会触发此回调。 OnStart(TweenCallback callback) 设置一个回调,当补间开始时将被触发(这意味着当补间设置在第一次,在任何最终延迟之后被设置为播放状态时)。 OnStepComplete(TweenCallback callback) 设置一个回调,每次补间完成一个循环循环后将被触发。 OnUpdate(TweenCallback callback) 设置将在每次补间更新时触发的回调。 OnWaypointChange(TweenCallback callback)设置一个回调,当路径补间的当前航点更改时将被触发。 这是一个特殊的回调,与其他回调相反,需要接受一个类型的参数int(这将是新更改的航点索引)。 先说这本书的第8章,是讲矩阵的。很明显,这一章里说的矩阵,可以理解为一种运动过程。将一个向量与这个矩阵相乘时,就代表对这个向量执行这个运动过程。 然后跳到10.6节,看标题是【表达形式之间的转换】。明显是说“一种事物”有多种描述形式、表达形式,这一节呢,就是要根据其中一种描述形式,求出其他等价的描述形式。那么这里的“一种事物”是说啥呢?看它第一段的最后一句:本节将讨论怎样将角位移从一种形式转换到另一种形式。嗯哼,我很自然的认为“一种事物”指的就是角位移,也可以认为就是第8章说的变换矩阵。结果呢,这一节余下的内容,求的矩阵,并不是角位移,即不是第8章说的运动过程,而是:同一个点在不同坐标系下的坐标值之间的对应关系,即同一个点,在不同的坐标系下有不同的坐标值,这些不同的值描述的是同一个点,这个矩阵就是让你能够从一个值求出这另一个对应的值,而不是让你将一个点执行一个运动过程,求出这个点现在到了什么地方。这两种理解表达的内涵是完全不一样的,尽管可能从矩阵字面值来看,两种理解所对应的矩阵是个互逆关系而已。但造成的混乱十分明显,我觉得这是这本书最大的bug。这个bug也清楚的解释了为什么h、p、b前面都要加个负号,而不是其他文献中的h、p、b矩阵直接连乘。 所以,最后再强调一下,书里10.6求的那几个M矩阵,是表示同一个点的在不同坐标系下的不同表述之间的对应关系,不是表示将一个点在一个坐标系下执行运动过程。 https://www.codeproject.com/kb/game/autotiles_algorithm.aspx#_comments 这篇文章的js实现 演示和具体代码请看这里 http://jsdo.it/Acans/qRex 实际上个算法很简单,实现起来比rpg maker的模式简单很多 图1 图2 算法核心 地块区域如图2,由1~9个tile组成,需要在5号目标地方放入图块时,只需要改变红色区域的bit块为1 ,重新计算每个tile的二进制下标,对应显示图1的图块即可。 if (x > 0) { if (y > 0) tile[x - 1][y - 1] |= 0x8; // 1000 tile[x - 1][y] |= 0xA; // 1010 if (y < tile_width - 1) tile[x - 1][y + 1] |= 0x2; // 0010 } if (y > 0) tile[x][y - 1] |= 0xC; // 1100 tile[x][y] |= 0xF; // 1111 if (y < tile_height - 1) tile[x][y + 1] |= 0x3; // 0011 if (x < tile_width - 1) { if (y > 0) tile[x + 1][y - 1] |= 0x4; // 0100 tile[x + 1][y] |= 0x5; // 0101 if (y < tile_height - 1) tile[x + 1][y + 1] |= 0x1; // 0001 } 这个算法是根据tile计算的。 还有个算法可以根据顶点来计算 图3 需要在红色区域的中心放置图块时,只需要设置红色区域bit=1 ,重新计算下标对应到图1的图块即可。 if (x > 0) { if (y > 0) tile[x - 1][y - 1] |= 0x8; // 1000 if (y < tile_height) tile[x - 1][y] |= 0x2; // 0010 } if (x < tile_width) { if (y > 0) tile[x][y - 1] |= 0x4; // 0100 if (y < tile_height) tile[x][y] |= 0x1; // 0001 } 效果图
我平常自己写点小东西都是用的 GLM(OpenGL Mathematics)数学库。GLM 功能很强大,也很方便用,直接包含在项目中编译即可。但是文件太多,有时候想写个小例子只用到其中个别函数,而不得不把整个库的代码都拉过来,而且最重要的是我个人更喜欢 c ,很多时候因为用 GLM 不得不采用 cpp 语法。所以就从网上搜索了一下,找了三个 c 代码的数学库。 linmath linmath 功能相对很多,我当时搜索时是在 stackoverflow 上找到的,作者在回答时推荐了自己的这个库,还说有奇怪的 bug ,所以我没有用,不过我蛮喜欢这个库中对于 c macro 的使用。 kazmath kazmath 功能很全面,作者也是大名鼎鼎。看介绍说 Cocos2d 也参考了这个库。 math3d_h math3d STB style 。单个头文件即可使用。我用的就是这个库。这个库代码超级简洁。而且包含了完整的单元测试。下面是简单的代码片段。这个文件中只包含了两个类型 vec3_t 和 mat4_t 。矩阵与 vector 相乘时有函数 m4_mul_pos 和 m4_mul_dir ,分别对应点坐标和矢量坐标,矢量坐标会忽略 w 分量而点坐标不会,具体可以查看实现。 mat4_t viewmat = m4_look_at(vec3((float)sin(t) * radius, 25.0f, (float)cos(t) * radius), vec3(0, -50.0f, 0), vec3(0, 1.0f, 0)); mat4_t persmat = m4_perspective(45.0f, (float)w / (float)h, 0.1f, 1000.0f); |