cocos2d / cocos2d-js__old__

cocos2d in JavaScript central repository
14 stars 9 forks source link

Cocos2d JS - Controller object as delegate to CCNode #10

Open vlidholt opened 11 years ago

vlidholt commented 11 years ago

Make it possible to have the controller object act as a delegate to CCNode. Events (such as touches, onUpdate etc) should be automatically forwarded to the delegate (controller). This would very much simplify the process of integrating CocosBuilder files with JS code.

vlidholt commented 11 years ago

To clarify this issue. Right now, if you want to use a controller object to control a CCNode (or subclass) you will need to write code that forwards the events that the CCNode receives.

Events include:

The code you currently have to write looks something like the following (copied from CocosDragonJS):

// Forward relevant touch events to controller (this)
this.rootNode.onTouchesBegan = function( touches, event) {
    this.controller.onTouchesBegan(touches, event);
    return true;
};
this.rootNode.onTouchesMoved = function( touches, event) {
    this.controller.onTouchesMoved(touches, event);
    return true;
};
this.rootNode.onMouseDragged = function( event) {
    this.controller.onMouseDragged(event);
    return true;
};

this.rootNode.onAccelerometer = function( event) {
    this.controller.onAccelerometer(event);
};

// Schedule callback
this.rootNode.onUpdate = function(dt) {
    this.controller.onUpdate();
};
this.rootNode.schedule(this.rootNode.onUpdate);

This code is complicated and hard to understand. Coming up with a better solution for forwarding these events would be great, and simplify things for everyone using a controller object to control a CCNode (or subclass). This is especially important if someone uses CocosBuilder, as it will use controller objects instead of subclasses. (Subclasses cannot be used as the parent class is loaded in native code.)

One solution would be to add the controller object as a delegate to CCNode and have the node forward all the events to the delegate (if such a delegate is attached). Other better solutions may exist, so please add thoughts below!

ricardoquesada commented 11 years ago

context: CCNode should be a simple as possible. No extra logic should be added there. It is a dumb object with basic properties that might know how to render itself and nothing more.

What cocos2d needs is a much better event handler.

something like:

// Pseudo code, trying to clarify the idea

// Subscribes to scene-workflow events like: "onEnter", "onExit"
var handler = cc.EventDispatcher.subscribe( cc.EVENT_SCENE_ALL, this );

// Subscribes only to "onKeyUp" event:
var handler = cc.EventDispatcher.subscribe( cc.EVENT_KEYBOARD_KEYUP );

// Subscribes to window events like "onResize", "onMinify", "onMaximize", etc:
var handler = cc.EventDispatcher.subscribe( cc.EVENT_WINDOW_ALL, this );

Scheduler is not an event, and it is already controlled by the cc.Scheduler object.

And MVC model could be easily be implemented with:

The Controller object, which is going to be the controller of the game, should:

CCLayer should not be used as the controller, or should not have a controller.

The controller object, should be the controller of the game (or director) if you want.


Additionally, by adding a good event dispatcher object, objects could comunicate between them by using events. eg:

cc.EventDispatcher.emit("game_over", optional_data);

// will generate the "game_over", and will be consumed by:

var consumeEvent = function( event, data ) {
    if( event == "game_over" ) {
        do_something_data( data );
    }
};
ricardoquesada commented 11 years ago

To keep in mind: Should we use an MVC pattern ? (like Cocoa and other UI stuff ) or an Entity system pattern ? (like Unity and other game engines )

minggo commented 11 years ago

I like Entity system pattern.

jandujar commented 11 years ago

I like Entity System too.

ricardoquesada commented 11 years ago

references for entity systems:

Any other ?

ricardoquesada commented 11 years ago

Another approach: issue #64

walzer commented 11 years ago

@vlidholt I agree with you:

One solution would be to add the controller object as a delegate to CCNode and have the node forward all the events to the delegate (if such a delegate is attached).

In issue #64, CCNode CAN NOT GET and SHOULD NOT HANDLER events. Events are only sent to CCNode's component: ControllerComponent (or named as EventsComponent, EventsReceiverComponent, EventsHandlerComponent) instead. ControllerComponent can communicate with its owner node and other components. I wrote same pseudo code there.