Cocos2d Cheat Sheet
Overview
Cocos2d is a family of open-source game development frameworks, with Cocos Creator being the modern flagship product. Originally started as a Python framework, the ecosystem evolved through Cocos2d-x (C++) and Cocos2d-js (JavaScript) into Cocos Creator, a complete game engine with a visual editor, component-based architecture, and support for both 2D and 3D game development. Cocos Creator uses TypeScript/JavaScript as its primary scripting language and provides a workflow similar to Unity, with scene editing, animation timelines, and visual asset management.
Cocos Creator excels at mobile 2D game development and has strong adoption in the Asian gaming market, particularly for casual games, card games, and social games. It exports to iOS, Android, HTML5, Facebook Instant Games, WeChat Mini Games, and native desktop platforms. The engine includes a physics system (Box2D for 2D, Bullet/cannon.js for 3D), UI system, animation editor, particle effects, tilemaps, and a robust resource management pipeline with asset bundling for optimized loading.
Installation
# Download Cocos Creator from:
# https://www.cocos.com/en/creator/download
# macOS: Install Cocos Dashboard via DMG
# Windows: Install Cocos Dashboard via installer
# Linux: Use AppImage from official download
# Command-line project creation (Cocos Creator 3.x)
# After installing Cocos Dashboard, create project from UI
# Or clone a template:
git clone https://github.com/nicholasbailey/cocos-creator-template.git my-game
cd my-game
npm install
# Build from command line
npx cocos-creator build --platform web-desktop
npx cocos-creator build --platform android
npx cocos-creator build --platform ios
# For Cocos2d-x (legacy C++ framework)
# Clone and setup
git clone https://github.com/cocos2d/cocos2d-x.git
cd cocos2d-x
python setup.py
source ~/.bash_profile
# Create cocos2d-x project
cocos new MyGame -p com.example.mygame -l cpp -d ~/projects
cd ~/projects/MyGame
cocos run -p linux
Project Structure (Cocos Creator)
my-game/
├── assets/ # Game assets
│ ├── scenes/ # Scene files (.scene)
│ ├── scripts/ # TypeScript/JavaScript
│ ├── prefabs/ # Reusable node templates
│ ├── textures/ # Images and sprite sheets
│ ├── animations/ # Animation clips
│ ├── audio/ # Sound files
│ └── fonts/ # Font files
├── settings/ # Project settings
│ └── project.json
├── native/ # Native platform configs
├── build/ # Build output
├── temp/ # Temporary files
├── package.json
└── tsconfig.json
Component Scripting (TypeScript)
import { _decorator, Component, Node, Vec3, input, Input, EventKeyboard, KeyCode } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('PlayerController')
export class PlayerController extends Component {
@property
speed: number = 200;
@property
jumpForce: number = 500;
@property(Node)
scoreLabel: Node = null;
private _velocity: Vec3 = new Vec3();
private _isGrounded: boolean = true;
start() {
input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
}
update(deltaTime: number) {
const pos = this.node.position;
this.node.setPosition(
pos.x + this._velocity.x * deltaTime,
pos.y + this._velocity.y * deltaTime,
pos.z
);
}
onKeyDown(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.ARROW_LEFT:
this._velocity.x = -this.speed;
break;
case KeyCode.ARROW_RIGHT:
this._velocity.x = this.speed;
break;
case KeyCode.SPACE:
if (this._isGrounded) {
this._velocity.y = this.jumpForce;
this._isGrounded = false;
}
break;
}
}
onKeyUp(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.ARROW_LEFT:
case KeyCode.ARROW_RIGHT:
this._velocity.x = 0;
break;
}
}
onDestroy() {
input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
}
}
Node and Component System
import { _decorator, Component, Node, Sprite, Label, SpriteFrame,
instantiate, Prefab, director, find } from 'cc';
@ccclass('GameManager')
export class GameManager extends Component {
@property(Prefab)
enemyPrefab: Prefab = null;
// Node operations
createEnemy() {
const enemy = instantiate(this.enemyPrefab);
enemy.setPosition(400, 300, 0);
enemy.setScale(2, 2, 1);
enemy.setRotationFromEuler(0, 0, 45);
this.node.addChild(enemy);
}
// Find nodes
findNodes() {
const player = find('Canvas/Player');
const label = this.node.getChildByName('ScoreLabel');
const allEnemies = this.node.getComponentsInChildren(EnemyController);
}
// Component operations
setupSprite() {
const sprite = this.node.getComponent(Sprite);
const label = this.node.addComponent(Label);
label.string = "Hello World";
label.fontSize = 24;
}
// Scene management
loadScene() {
director.loadScene('GameScene');
}
// Scheduling
start() {
this.schedule(this.spawnEnemy, 2.0); // Every 2 seconds
this.scheduleOnce(this.startGame, 1.0); // Once after 1 second
}
spawnEnemy() {
this.createEnemy();
}
// Remove node
destroyEnemy(enemy: Node) {
enemy.removeFromParent();
enemy.destroy();
}
}
Common Components
| Component | Description |
|---|---|
Sprite | 2D image rendering |
Label | Text display |
Button | Interactive button |
Layout | Auto-layout container |
ScrollView | Scrollable container |
EditBox | Text input field |
ProgressBar | Progress indicator |
Toggle | Checkbox/radio button |
Animation | Keyframe animation |
RigidBody2D | 2D physics body |
BoxCollider2D | Box collision shape |
CircleCollider2D | Circle collision shape |
AudioSource | Sound playback |
ParticleSystem2D | 2D particle effects |
TiledMap | Tiled map renderer |
Camera | Scene camera |
Touch and Input
import { _decorator, Component, EventTouch, Node, UITransform, Vec2, Vec3 } from 'cc';
@ccclass('TouchHandler')
export class TouchHandler extends Component {
start() {
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
}
onTouchStart(event: EventTouch) {
const location = event.getUILocation();
console.log(`Touch start: ${location.x}, ${location.y}`);
}
onTouchMove(event: EventTouch) {
const delta = event.getUIDelta();
const pos = this.node.position;
this.node.setPosition(pos.x + delta.x, pos.y + delta.y, pos.z);
}
onTouchEnd(event: EventTouch) {
console.log('Touch ended');
}
}
Animation
import { _decorator, Component, Animation, tween, Vec3, Node } from 'cc';
@ccclass('AnimController')
export class AnimController extends Component {
// Component animation
playAnimation() {
const anim = this.getComponent(Animation);
anim.play('walk');
anim.on(Animation.EventType.FINISHED, this.onAnimFinished, this);
}
// Tween animation
tweenExample() {
tween(this.node)
.to(1, { position: new Vec3(300, 200, 0) }, { easing: 'sineOut' })
.to(0.5, { scale: new Vec3(2, 2, 1) })
.call(() => { console.log('Tween complete'); })
.start();
// Repeat and yoyo
tween(this.node)
.to(0.5, { position: new Vec3(0, 50, 0) })
.to(0.5, { position: new Vec3(0, 0, 0) })
.union()
.repeatForever()
.start();
}
// Sequence
sequenceAnimation() {
tween(this.node)
.parallel(
tween().to(1, { position: new Vec3(500, 0, 0) }),
tween().to(1, { angle: 360 })
)
.delay(0.5)
.to(0.3, { scale: new Vec3(0, 0, 0) })
.call(() => this.node.destroy())
.start();
}
}
Physics 2D
import { _decorator, Component, RigidBody2D, BoxCollider2D, Contact2DType,
Collider2D, IPhysics2DContact, ERigidBody2DType, Vec2 } from 'cc';
@ccclass('PhysicsPlayer')
export class PhysicsPlayer extends Component {
start() {
const collider = this.getComponent(BoxCollider2D);
if (collider) {
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
}
}
onBeginContact(self: Collider2D, other: Collider2D, contact: IPhysics2DContact | null) {
console.log(`Collided with: ${other.node.name}`);
if (other.node.name === 'Coin') {
other.node.destroy();
}
}
jump() {
const rb = this.getComponent(RigidBody2D);
rb.linearVelocity = new Vec2(rb.linearVelocity.x, 10);
}
move(direction: number) {
const rb = this.getComponent(RigidBody2D);
rb.linearVelocity = new Vec2(direction * 5, rb.linearVelocity.y);
}
}
Configuration
// tsconfig.json
{
"compilerOptions": {
"target": "ES2015",
"module": "ES2015",
"strict": true,
"types": ["cc/global"]
}
}
Build and Deploy
# Build for web
npx cocos-creator build --platform web-desktop
npx cocos-creator build --platform web-mobile
# Build for native
npx cocos-creator build --platform android --android-studio
npx cocos-creator build --platform ios
# Build for mini games
npx cocos-creator build --platform wechatgame
npx cocos-creator build --platform bytedance-mini-game
npx cocos-creator build --platform facebook-instant-games
# Debug build
npx cocos-creator build --platform web-desktop --debug
Advanced Usage
// Resource loading
import { resources, SpriteFrame, Texture2D, JsonAsset } from 'cc';
resources.load('textures/hero/spriteFrame', SpriteFrame, (err, spriteFrame) => {
if (!err) {
this.getComponent(Sprite).spriteFrame = spriteFrame;
}
});
// Load bundle
import { assetManager } from 'cc';
assetManager.loadBundle('level1', (err, bundle) => {
bundle.load('map', TiledMapAsset, (err, asset) => {
// Use asset
});
});
// Event system
import { EventTarget } from 'cc';
const gameEvents = new EventTarget();
gameEvents.emit('score-changed', 100);
gameEvents.on('score-changed', (score: number) => {
console.log(`Score: ${score}`);
});
// Object pooling
import { NodePool, instantiate } from 'cc';
const bulletPool = new NodePool();
function getBullet(): Node {
let bullet = bulletPool.get();
if (!bullet) {
bullet = instantiate(bulletPrefab);
}
return bullet;
}
function recycleBullet(bullet: Node) {
bulletPool.put(bullet);
}
Troubleshooting
| Issue | Solution |
|---|---|
| Script not attaching to node | Ensure @ccclass decorator is present with correct name |
| Property not showing in editor | Use @property decorator with correct type annotation |
| Touch events not firing | Check node has a UITransform component with proper size |
| Build fails for Android | Verify Android SDK/NDK paths in Cocos Dashboard preferences |
| Assets not loading | Check path is relative to assets/resources/; use correct loader |
| Physics not working | Enable physics in Project Settings; add RigidBody and Collider |
| Performance issues on mobile | Reduce draw calls; use texture atlases; limit particle count |
| TypeScript errors | Run tsc to check; ensure tsconfig.json is correct |
| Animation not playing | Verify clip is assigned; check default clip and play-on-load settings |
| Scene transition blank | Preload scene with director.preloadScene() before switching |