Is it possible to copy a CCLayer instance in cocos2x? - cocos2d-x

I created a CCLayer instance, and then I want to create the same layer.
Is it possible to copy a CCLayer instance in cocos2-x?

AFAIK, there is no such possibility in cocos2dx now. So just place creation of your layer to the method that will return result layer and call this method twice.

Copying/deep-copying objects in cocos2d-x is not an option.
The best way is to create a custom class for your layer, and then call the ::create() method twice to have two instances of the same layer, sharing all the initial configuration.
In MyLayer.h:
USING_NS_CC;
class MyLayer : public CCLayer {
public:
CREATE_FUNC(MyLayer);
virtual bool init();
};
In MyLayer.cpp:
bool MyLayer::init() {
if (!CCLayer::init())
return false;
// Insert here all custom initialization logic
return true;
}
Then you can easily do:
MyLayer *layer1 = MyLayer::create();
MyLayer *layer2 = MyLayer::create();
and both layers will share the same initial aspect/configuration/whatelse.

Related

AS3 Super Class Issue

I have a problem and I'm not too sure the best way to resolve it.
Scenario:
I have a Super Class called 'food' and I have 20 different foods and extends 'food' like Pizza, Curry, Fish and Chip etc.
When I remove a 'food' I keep a record of it so I can reuse (for performance purposes). Can I make a new Pizza class that uses an old 'food'?
E.g.
public class Pizza extends food
{
public function Pizza()
{
super = FOOD.returnUsedFoodClass();
}
}
Is this possible or would I need to save the extending Class as well?
Hope this all make sense.
EDIT:
When I say remove I mean I no longer need it - so I would normally remove all references to it. But instead, I have placed all 'food' classes that I no longer need in a static vector so I can reuse them later.
You misunderstand the basic OOP principles here.
First: a constructor runs only once and only when the object is created so any attempt to stop the creation of the object or replace the object from within its constructor is illogical and cannot succeed since the object at that moment is already created.
Second: Classic misunderstanding of the super keyword. No super doesn't point to any other instance of any other object, super in constructor points to the super class implementation of the constructor. Trying to assign an object to super cannot work and is also illogical. I'm guessing you meant to use 'this' which would also not work anyway.
What you are trying to achieve cannot be done that way and this in any OOP language. There's no way to run a constructor (meaning creating the object) and make this object point to something else within its own constructor. What you are looking for is a classic object pooling system via static methods like this:
var pizza:Pizza = Food.getFood("pizza") as Pizza;
Where the static method checks if any Pizza instance (from the pool) is available and if it is it returns it and if it's not it creates a new one and returns it.
Pooling can be implemented loosely or explicitly, I prefer the more solid and flexible explicit version. Here's an example:
Food class pooling additions:
static private var recycledInstances:Vector.<Food> = new Vector.<Food>();
//hold our reclycled instances
public function recycle():void
{
var index:int = recycledInstances.indexOf(this);
if(index >= 0)
{
return;
}
recycledInstances.push(this);
}
//explicitly add this instance to recycle
private function reset():void
{
}
//to run in constructor and when the instance is retreived from recycle
//this method purpose is to reset all values to default.
Now when an instance is no longer used you call the instance recycle() method to place it in recycle. Then when you need a new instance you do:
var food:Food = Food.getFood();
And this is implemented that way in Food class:
static public function getFood():Food
{
if(recycledInstances.length)
{
var totalInstances:uint = recycledInstances.length;
var instance:Food = recycledInstances[totalInstances - 1];
instance.reset();
recycledInstances.length -= 1;//faster than splice
return instance;
}
return new Food();
}
You can extend this easily to descendant of food class by adding a type member variable to Food for example and check the type of recycled instances before returning them.

cocos2d-x-3.0 draw vs onDraw

I'm using cocos2d-x v3.0 and in some test project I'm doing some custom drawing by overriding Node's draw method, but in the DrawPrimitives example provided they do something like this:
void DrawPrimitivesTest::draw()
{
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(DrawPrimitivesTest::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand);
}
void DrawPrimitivesTest::onDraw()
{
// drawing code here, why?
}
From reading the header and source files it seems like this may be some way of sending render commands straight to the renderer, is that correct?
Should I be using this method to do custom drawing? What's the difference between draw an onDraw?
EDIT:
As #Pedro Soares mentioned, since Cocos2D-X 3.0 you can't override draw() anymore. you have to use draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) instead.
There is sample on cocos2d-x RC0 package that shows how to use the DrawPrimitives on top of other layers.
On your Layer .h add the following:
private:
void onDrawPrimitives(const kmMat4 &transform, bool transformUpdated);
CustomCommand _customCommand;
Now in the cpp of the Layer, override the layer draw method and include the onDrawPrimitives method:
void MyLayer::onDrawPrimitives(const kmMat4 &transform, bool transformUpdated)
{
kmGLPushMatrix();
kmGLLoadMatrix(&transform);
//add your primitive drawing code here
DrawPrimitives::drawLine(ccp(0,0), ccp(100, 100));
}
void MyLayer::draw(Renderer *renderer, const kmMat4& transform, bool transformUpdated)
{
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(MyLayer::onDrawPrimitives, this, transform, transformUpdated);
renderer->addCommand(&_customCommand);
}
In future, cocos2d-x 3.x renderer will be multithreaded with command pool.
draw method called by visit method, to create new command. When command is performed by command pool, onDraw is called. At this moment, commands are performed in single thread, but in overloaded onDraw method you should assume, that it will be called in another thread to simplify future migration.
I use draw method for debugDraw Like this It may be helpful
void HelloWorld::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
Layer::draw(renderer, transform, flags);
Director* director = Director::getInstance();
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION );
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
world->DrawDebugData();
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
The draw() expression should be the same as the base class function.
The draw method of Node for cocos 3.3rc is:
virtual void draw(Renderer *renderer, const Mat4& transform, uint32_t flags);

Where do I store a function that acts on an array of objects?

I'm trying to create something like the following using c++:
I have a class called particle which will store the position, velocity of each particle. Additionally, a member function will update the particle's position using velocity data.
I'm also trying to write a function that will detect a collision between particles and the boundaries of the box. To do so, this function needs access to each particle's position and velocity. Thus, the function needs to take an entire array of particles as a parameter. However, this function can't exist as a member function of the particle class, because then it won't have access to all the particles.
Question: Where do I include the collision detection function, such that it is an extensible part of the particle class?
I thought about just writing this function inside my main.cpp file, but I haven't the slightest clue whether this adheres to the OOP guidelines. Ideally there might be other functions that also act on an array of particles.
Probably what you want is some sort of "ParticleContainer" object, that holds the array of particles, and performs operations on the particle system as a whole.
(That's also where you would put the code that runs down the array and calls the "Draw" functions.)
I guess that good idea will be to declare a detection function as a friend of class particle: it will have access to all members in class. Then you can fire this function in loop inside of some kind of manager function that will calculate the collision to all particles in array. In this
void CollisionMgr(particleClass *ParticleArrayPtr, int NumOfParticles)
{
while(NumOfParticles)
{
CollisionOfParticle(*ParticleArrayPtr, NumOfParticles);
NumOfParticles--;
}
}
I tend to use a pattern along these lines: Keep all the model state in a single class called Modelor Environment; have a separate class Renderer which knows how to draw the model state; have a System class which ties these together. The following is highly abbreviated, but hopefully gives the idea:
class Box {};
class Location {};
class Particle
{
public:
void updatePosition(double dt);
const Location& getLocation();
};
class Environment
{
public:
void checkForCollisions();
private:
Box box;
std::vector<Particle> particles;
};
class Renderer
{
public:
void render(Environment& environment);
};
class System
{
Environment environment;
Renderer renderer;
};

Managing Singletons in external swfs

I'm dealing with the scenario whereby my code might be included in other Flash content either included via import .as commands and then referenced as a Singleton, e.g.
import com.as3.Singleton;
...
...
Singleton.birth();
Singleton.getInstance().test();
...but also imported as a runtime library; with the Singleton class exported as a .swf beforehand (instead of pre-baking the class).
How should I reference the Singleton once Event.COMPLETE has fired off from the Loader that brings in the swf? Normally I'd code something like:
public function singletonCompleteHandler(event:Event):void {
var mySing:Singleton = _loader.contentLoaderInfo.content as Singleton;
}
...but I know I don't want to be referencing the singleton via a "var" reference. I'm not explaining very well, but basically once the singleton.swf has loaded in I need to use the code within it within a singleton model (i.e. ensure there's only one instance of it throughout my application).
Copy of the Singleton class included below (thanks for any thoughts on this by the way).
package
{
public class Singleton extends Sprite
{
private static var instance:Singleton;
public function Singleton() {
if (instance) {
throw new Error("Singleton can only be accessed through Singleton.getInstance()");
}
}
public static function birth() {
if (instance == null) {
instance = new Singleton();
}
}
public static function getInstance():Singleton {
return instance;
}
public function test():void {
trace("Testing our singleton.");
}
}
}
First of all, if you're loading it dynamically, then you don't want to have a reference to it in your loading SWF (otherwise it would defeat the point).
So I'm guessing you're looking to do something like this:
function completeHandler(event:Event):void
{
var singleton:Object = loader.contentLoaderInfo.content;
var instance:IMyObject = singleton.getInstance();
instance.test();
}
IMyObject is of course optional here. If you do it like this, your singleton instance will have to implement IMyObject.
interface IMyObject
{
function test():void;
}
This is all to avoid having to reference the actual class in your loading SWF. Like I said, the interface is optional: you can just use Object instead.
... and now on to the main point: load the singleton SWF into the loading SWF's own "application domain".
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/LoaderContext.html#applicationDomain
var lc:LoaderContext = new LoaderContext();
lc.applicationDomain = ApplicationDomain.currentDomain;
loader.load(new URLRequest("Singleton.swf"), lc);
You see, normally when you load a SWF, it gets loaded into its own application domain. But this makes it impossible to enforce the singleton pattern on the loaded SWF, because each instance of the class can live in its own application domain (hence you can end up with multiple instances). So if you want to enforce this across multiple SWF loads then you want to load it into the loading SWF's application domain.
If your question is "How should I reference the Singleton once Event.COMPLETE has fired off from the Loader that brings in the swf?", then you can do it with:
var Singleton:Object = _loader.contentLoaderInfo.applicationDomain.getDefinition('Singleton');
But, I'm not sure what you mean about not wanting to use a "var" reference.
On a side-note, there's a good chance a global variable would be a better option than a Singleton class for an API.
package myPackage
{
public var myGlobal:MyGlobal = new MyGlobal();
}
Which you can access with myPackage.myGlobal

Library design quandary

Ok so I am writing an open source library. A section of this library deals with moving an entity in a two and three dimensional space so it will have functions that manipulate the rotation, position etc.
Now ideally I would like my library to work well with other libraries, in particular things like Papervision3D and other Flash 3D engines, but not forgotting basic image objects like a Sprite or Movieclip.
So this is my quandary. The functions that will manipulate the entity will also need to modify the values of the underlying model data (so either a Sprite, Papervision object etc). What is the best way to make my library flexible so that it can support multiple data models. Performance is also important aspect too.
Currently I am thinking of something like this:
//this is the public function that I expose in my library
public function rotate(val:Number,func:Function,objData:*):void
{
func(val,objData);
}
//example of a function that could be passed in
//this one will rotate a MovieClip
private function modelFunction1(rot:Number,objData:*):void
{
var myMov:MovieClip = objData as MovieClip;
myMov.rotation = rot;
}
//second example of a function that could be pass in
//this one will rotate a point
private function modelFunction2(rot:Number,objData:*):void
{
//yes I know this piece of code makes no sense :P
var p:Point = objData as Point;
p.x = Math.cos(rot);
p.y = Math.sin(rot);
}
so then it could be used like:
rotate(4,modelFunction2,myPoint)
//or
rotate(4,modelFunction1,mySprite);
I should add that in reality I, as the client code, won't be able to directly call the rotate function. Instead the rotate function that I want to pass in would need to be stored somewhere as a class member and then be called by the rotate function. Its just less code for me to write it out like above.
This to me seems quite flexible although the performance implications of casting and passing functions concerns me (but might be ok). Can anyone else suggest an alternative or is what I have the most logical solution. Thanks :)
I suggest the adapter pattern.
In your case you could define interfaces which offer type safe definitions for what your library expects instead of having function arguments.
then you need to write adapter classes which implement your librarys interfaces and wrap for instance a papervision object and delegate the function calls to your interface methods to the papervision object.
interface IRotatatable {
function rotate(deg : Number) : void
}
class YourLibraryClass {
public function rotate(r : IRotatatable, val : Number):void {
r.rotate(val)
}
}
class P3DAdapter implements IRotatable {
public function P3DAdapter(p3d : SomePaperVisionObject) {
_p3d = p3d;
}
public function rotate(r :Number):void {
p3d.rot = r;
}
}
function someClientCode():void {
var adapter : IRotatable = new P3DAdapter(p3d)
new SomeLibraryClass().rotate(adapter, val));
}