Skip to content

Cocos2D v4 Alpha Notes

Scott Lembcke edited this page Apr 17, 2015 · 2 revisions

Cocos2D v4.0-alpha Notes

First and foremost, this is an alpha release. Not all features have been completed, there will still be some API changes, and there will be bugs.

This is a release for developers that are interested in testing out the new features and giving feedback on them. Since the API and code isn't guaranteed to be stable, it's probably not a good idea to start a new long term project or port an existing project to v4 just yet. (Soon!)

Completed Features:

  • Automatic Image Scaling: Instead of keeping a handful of files of different sizes (-hd, -ipadhd), keep just the highest resolution version and have Cocos2D rescale it if it's loaded on a lower resolution device. It's fast, easy, and makes your app bundle smaller.
  • Explicit File Resolutions: Instead of expanding an ever increasing list of hardware specific file suffixes to support, files are now tagged with their actual resolution (-hd becomes -2x, etc).
  • More Flexible Texture Loading: Load textures with custom texture filter and wrapping modes. Set the default loading options for cached textures. (Ex: Set nearest neighbor mode for all textures if you are making a pixel art game.)
  • Sprite Sheets Work Like Directories: Sprite sheets can now be treated as if it was a directory. For example, if you have a sprite sheet named Sprites/Hero.png and it has a frame inside of it named Head.png, you can access that sprite frame as Sprites/Hero/Head.png. This also means that you can replace a directory with a sprite sheet without needing to change any code. Previously this was a feature of sprite sheets created by SpriteBuilder, but now it will work with any sprite sheet.
  • Automatic Sprite Sheet Loading: Sprite sheets no longer need to be explicitly registered if you access the frames in them using the sprite sheet/directory feature. When locating Sprites/Hero/Head.png, it will first look for an image named. Next it will look for a sprite sheet named Sprites/Hero.plist with a frame named Head.png.
  • Viewports: Viewports support rendering to a section of the screen with a custom projection. They also finally add a camera feature to Cocos2D so you can easily pan or zoom in a game. Combining the camera feature with custom projections makes it easy to implement proper perspective or parallax in a 2D game.
  • Improved Metal Support: The Metal renderer now supports PVR files and CCEffects.
  • Improved Action Performance: Performance for scenes with a lot of actions should be greatly improved.
  • Simpler Cross-Platform Setup: The iOS specific CCAppDelegate class is being replaced with CCSetup. Simpler to use, more flexible, and avoids duplicating setup code for all platforms. (See transition guide below)
  • More UIKit (or AppKit) Friendly: Cocos2D no longer hijacks the app delegate, and can now support multiple Cocos2D views in a single app. Embedding Cocos2D in an existing UIKit application is as simple as creating a Cocos2D view and assigning a scene to it. This was very difficult to do in all past versions of Cocos2D.

What Is Not Done Yet:

  • We will be adding private delegates to CCNode to help improve visit/transform performance. There will be some changes to the "positionType" methods on CCNode in an attempt to clean up the code related to them.
  • The new CCRenderTexture class hasn't been implemented yet.
  • Viewports:
    • Viewports will support a render-to-texture mode, but this hasn't been implemented yet.
    • Viewports that are clipped by the edge of the screen don't work correctly with Metal.
  • The replacement for v3's fixed screen mode has not been implemented yet.
  • Thread safety. Vastly improved threading support is planned for v4, but this isn't done yet. It's still not safe to call any Cocos2D methods except on the main thread.
  • Currently only RGBA8 PVR files can be loaded when using the Metal renderer. Packed formats should be supported for the final release. PVRTC compressed textures may also be supported.
  • The threaded renderer still only supports iOS.
  • You still have to enable the Metal renderer at compile time as in v3.
  • The Metal renderer still doesn't work with the threaded renderer.
  • Frame statistics are currently unimplemented.
  • Encryption support for CCFile.
  • Content scales for files are currently limited to 1x, 2x and 4x. This is not a final limitation.
  • Auto-rotation doesn't work yet.

API Changes:

This is not an exhaustive list. I skimmed through the header diffs, but there are a lot of them to go through. In general, I've tried to keep the number of changes people will need to make to their code low, but it's not always possible to make a backwards compatible API. Sometimes an API was changed simply because it's name was ambiguous or misspelled (ex: CCConfiguration or CCRendererCheckVisbility). Those are easy to make backwards compatible. Other APIs have changed because the implementation they were built on needed to be completely rewritten to improve them (ex: CCFileUtils or CCAppDelegate).

Checking CCDeprecated.h is a good place to start. If there was something that was removed that you think should be deprecated instead, let us know!

  • A lot of deprecated functionality from v3 has been removed.
  • CCFileUtils: This has been removed and replaced with the new and mostly comparable CCFileLocator class.
  • CCDirector:
    • The director is no longer a singleton. Instead you can create multiple Cocos2D views, each with it's own director. Instead of a shared director, you can get the currently active director.
    • The animation rate property has been replaced by a frame skip property instead since that's how the default Mac/iOS implementations work anyway.
  • CCSprite:
    • Sprite texture rects are now expressed in regular points. Their coordinate system was not really defined in the past.
  • CCSpriteFrame:
    • Sprite frame coordinates are now in regular points. Their coordinate system was not really defined in the past and differed by property/method. (Yikes!)
    • Most of the constructors for sprite frames have been removed due to changes in coordinates.
  • CCSpriteFrameCache:
    • CCSpriteFrameCache has been made private. The [CCSpriteFrame frameNamed:] method is the thread safe replacement.
    • You can still access the cache if you import the header, but it's API will never be thread safe.
    • Some of the stranger methods have been removed, but I don't think anybody will miss them. (Ex: Add frames from an NSDictionary and an existing texture)
  • CCConfiguration: This class was renamed to CCDeviceInfo to better reflect it's function.
  • CCParallaxNode: This has been removed. It was really problematic and rarely worked the way people expected. We might add it back as a deprecated class.
  • CCNodeMultiplexer: This has been removed. It was weird, awkward to use and nearly useless.

Known Issues:

This is not an exhaustive list. Let us know what we are missing!

  • In some rare cases, scheduled methods don't seem to be called. This was caused by some fixes added to CCScheduler, but it's not clear what causes it yet.
  • Tile map support for the new asset resolution handling scheme is sort of flaky. Using auto-scaled images will save you a lot of headaches for now.
  • Android:
    • Scroll views often go crazy the first time they are touched.
    • Tile maps and particles with embedded textures don't work. (Missing base 64 support)
    • Crashes when creating a CCTextField.

What You Need To Know:

File Naming Conventions:

V4 has changed the way that images, and other graphical assets with a content scale associated with them, are located and loaded. We were trying to fix several big problems with Cocos2D that have been getting worse over time. The first problem is that ,ver the years, Cocos2D has accumulated a lot of special purpose file suffixes. (-hd, -ipad, -mac, -iphone5, iphone5hd, -ipadhd, and -machd) This has been unsustainable for a long time, but the iPhone 6 and 6 Plus made the need to improve much more urgent. The second problem is that if you supplied all of these files, most of them would be duplicate. Very few people are actually interested in making device specific art (good luck to you!). Most people just pick a subset of the files, for example -hd and -ipadhd, and rely on their favorite hacks or configuration tweaks to get them to load on all devices. That's the third problem, people rarely use the system "as designed" and it's barely comprehensible. Pop quiz: How do you convince a Mac to load -ipadhd images? The last problem is that having multiple copies of you images at several resolutions wastes precious bytes in your app bundle. The solution has two parts: automatic image rescaling, and files tagged with explicit resolutions.

Automatic image rescaling is the recommended way to load most of your images. The basic idea is that you provide images at a specific content scale (which defaults to 4x), and Cocos2D will scale the image down when loading it on a device with a lower content scale. Just name your image like normal without any suffixes, for example Hero.png. If you use the default configuration, a Retina iPad is a 4x device, so when you load Hero.png on it, the image will be loaded at it's normal size into a 4x texture. An iPhone 5 is 2x device (again, defaults), so when you load Hero.png on it, the image will be halved in size and loaded as a 2x texture. Easy right?

Not all files should be rescaled, so you can still provide images with specific content scales. You might have a special effect texture for a shader that should always be loaded at it's regular size, you might want to trade disk space for loading speed, or maybe you just prefer to rescale them yourself. You do this by appending -1x, -2x, etc on the filename. This works like the old file suffixes, but there is no question what content scale the file has, and you don't need tricks to share the files between device types.

When you ask Cocos2D to load an image, it will do the following:

  1. Round [CCSetup sharedSetup].assetScale up to the next power of two and use that as the starting resolution.
  2. Try to find a file with that content scale suffix. (Ex: Hero-4x.png)
  3. If that failed, try to find a file without a tag and rescale it if needed. (Ex: Hero.png)
  4. If that fails, then try and find files with smaller content scales. (Ex: Hero-2x.png, Hero-1x.png)

This means that it will prefer a file with an explicit content scale that closely matches the device's, but will fall back on automatic scaling or lower resolution files.

v4FileRenamer.rb:

Renaming existing files is tedious, so I made a ruby script to help. It takes a single directory as an argument, and searches for Cocos2D graphics related files inside of it. For each one, it asks what to do.

You'll want to peek at its code. There are configuration options you'll probably want to fiddle with. It's also set up to make the proper git commands which is handy.

Check it out.

Automatic Image Rescaling:

Some users are very skeptical of the automatic rescaling feature because they expect to lose some control, image quality, or performance. So I'd first like to say you are covered. You can still manage images yourself by providing -1x, -2x, and -4x versions. I'd encourage you to try automatic rescaling anyway. I think you'll like it!

The implementation is pretty smart so that it's fast and doesn't waste a lot of memory. PNG files are loaded and rescaled one line of pixels at a time using a box filter. The full size image is never in memory all at once, and it doesn't use a lot of memory bandwidth. Image quality should be just as good as TexturePacker or SpriteBuilder. PVR files can only be rescaled if they contain mipmaps (check your export settings). Other image formats (like JPEG) are loaded using CoreGraphics and aren't as efficient.

Sprite Sheets:

Sprite sheets can be automatically scaled, but you need to adjust your packing settings to avoid sprites bleeding together when they are scaled down. If you are using 4x as your base resolution for untagged files (this is the Cocos2D default), then you should set your texture packing program to use 4 pixels of padding and a common divisor of 4 as well. This makes sure that when the sheet is rescaled that sprites stay within the correct pixel coordinates.

SpriteBuilder v2 will do this for you automatically.

Performance:

I don't have recent performance numbers yet! Expect loading a 4x PNG and rescaling it to 2x to take ~3 times longer than a 2x file. This means an iPad 2 will still load faster than an iPad 3, but not as fast as if it had 2x image files. Overall, don't worry about this if it isn't a problem.

Migrating to CCSetup:

CCSetup is the new, easy to use, optional, cross-platform Cocos2D initialization class.

Here is an example:

@interface MySetup : CCSetup @end
@implementation MySetup

// Optional
-(NSDictionary *)setupConfig
{
    return @{
        CCSetupTabletScale2X: @YES,
        CCSetupShowDebugStats: @YES,
    };
}

// Optional
- (void)setupApplication
{
    // Maybe you want to override the default scaling options?
    self.contentScale = ...;
    self.assetScale = ...;
    
    [super setupApplication];
}

// Required
- (CCScene*) createFirstScene
{
		CCScene * scene = ...
		
		return scene;
}

@end

@interface AppDelegate : NSObject <NSApplicationDelegate> @end
@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [[MySetup sharedSetup] setupApplication];
}

@end

At a minimum, you need to make a CCSetup subclass, implement the createFirstScene method, and call [[YourSubclass sharedSetup] setupApplication] from somewhere once you App has started up. Everything else is optional.

CCSetup and Content Scales:

CCSetup is where you set the content scale of the device you are running on, and what size of assets it should be loading. There are two values for this. The first is CCSetup.contentScale. This is the number of pixels that correspond to a Cocos2D "point". Veteran Cocos2D developers are hopefully very familiar with that. The second value is CCSetup.assetScale. This is the scale to load or create assets at. For things like render textures or TTF labels, the asset scale value is used as is. When loading for files, the asset scale is a hint. For example, when the asset scale is 3x, images will probably be loaded at 4x. Even if an asset doesn't have the same content scale as the device, it will still be drawn at the right size in points. It will simply be scaled up or down (in pixel size) by the GPU.

By default, the following scales are set for both the content scale and the asset scale:

Device Scale
iPhone 3Gs 1x
iPhone 4/5/6 2x
iPhone 6 Plus 3x
iPad 1x (2x if using the CCSetupTabletScale2X option)
iPad Retina 2x (4x if using the CCSetupTabletScale2X option)
Mac 1x
Retina Mac 2x
Android Based on the reported DPI of the screen and the CCSetupTabletScale2X option.

There are a million reasons why you might not like these defaults so we've made it easier than ever to override them. Maybe you want to change the scale so that iPhone 6 or 6 Plus screen is the same size in points as the iPhone 5. Maybe you want a 5k iMac to be a 12x device. If you want to do something custom, just override the scale values in your setupApplication method before calling super.

The reason for separating the content scale and the asset scale is mostly for the Mac version of Cocos2D. You don't really have to worry about running out of memory, and the user can resize the window. If you want to change the content scale when the user resizes the window instead of changing the size of the window in points, then you need to load high resolution assets to start with. Another use might be for pixel art games. Supply and load only 1x art using the asset scale value, and control the screen resolution using the content scale value.

Using Multiple Cocos2D Views:

Assuming that you are familiar with Cocoa, you should look at the following files. They set up the window/view from scratch: iOS / Mac

-- Scott Lembcke