update function of Component not called anymore - cocos2d-x

The update function of Component is not called anymore in Cocos2dx v3 while it was called fine in v2.x
I noticed the CCScheduler is completely different in both versions and that Node::update in v2 is called from CCScheduler::update function but in v3 it is called from Scene::update - which is never called.
Anybody have an idea what is the best way to migrate this from v2 to v3.
My code is as follows
In game scene
layerMoveLeft = ParallaxNode::create();
layerMoveLeft->addComponent(new MoveLeft() );
this->addChild(layerMoveLeft);
In MoveLeft class -
class MoveLeft : public Component
...
void MoveLeft::onEnter()
{
log("- MoveLeft::onEnter");
}
void MoveLeft::update(float delta) {
log("- MoveLeft::update");
}
The update function in v3 is never called

in V 3+ you can call update method on Node class using ScheduleUpdate() function call.
virtual void update(float dt);
I don't know why you want Component class in V 3.0

Make the following changes and i hope that it will work.
MoveLeft.h
void update(float delta);
MoveLeft.cpp
this->scheduleUpdate();
You can add the above code anywhere you want in the class (preferably in the init() method)
Now create the function as you did before:
void MoveLeft::update(float delta) {
log("- MoveLeft::update");
}
P.S: I haven't used it with Component, i have used it with Layer.
class Quizzes: public cocos2d::Layer{
public:
virtual bool init();
}

in V 3+, you can add code above to class parent of component.
this->scheduleUpdate();

Related

Adobe/Apache Flex: Modify View in an ActionScript class

I have a WindowedApplication in Apache/Adobe Flex 4 which currently consists of one view (the view defined in the WindowedApplication MXML).
In that application I have an object which listens to data coming from a network. When data is available a method is called on that object and it shall update my view by changing the text of a label.
I do not have a reference to the view in the network listener object though. How can I get it?
This is part of my MXML where I define my view.
<fx:Script source="./ViewCodeBehind.as"/>
<!-- ommited stuff -->
<s:Label id="errorLabel"
text=""
fontSize="14"/>
<!-- Stuff in between -->
<s:Button label="Get Status"
click="getStatus();"/>
The code which is called when the button is clicked:
public function getStatus(): void
{
var networkGateway: NetworkGateway = new NetworkGatewayImpl();
networkGateway.getConnectionStatus();
}
And the NetworkGatewayImpl
public class NetworkGatewayImpl implements NetworkGateway
{
public function NetworkGatewayImpl()
{
}
public function getConnectionStatus(): void
{
// Start asynchronous network call
// when error occurs onNetworkError() is called
}
private function onNetworkError(): void
{
// Set "errorLabel" here: How?
}
}
Essentially I want to know some ways to update "errorLabel" from the NetworkGatewayImpl.
Based on your code, there could be multiple ways to solve this. Easiest way (as per me) would be to dispatch an event from the NetworkGatewayImpl class and listen to it on the instance you have created in the view class. So sample code would look like this:
public function getStatus(): void
{
var networkGateway: NetworkGateway = new NetworkGatewayImpl();
networkGateway.addEventListener("networkError", onNetworkError);
networkGateway.getConnectionStatus();
}
private function onNetworkError(e:Event):void
{
networkGateway.removeEventListener("networkError", onNetworkError);
this.errorLabel.text = "Your Text Here";
}
Dispatch your event like this from your NetworkGatewayImpl class:
private function onNetworkError(): void
{
this.dispatchEvent("networkError");
}
You will have to ensure that your NetworkGatewayImpl also implements the IEventDispatcher interface to be able to dispatch events.
Also, best practice would be to create a custom Event class (extending the Event class) and use constants instead of the literal 'networkError'
Hope this helps.

Is it possible in LibGDX's `scene2d` API to have the same Actor instance in multiple Stages?

I am making a program using the amazing libGDX+scene2d API and I structured it as follows:
I have a single MyGame instance, holding a single PolygonSpriteBatch instance.
There is an abstract MyScreen class, holding a MyStage class (see below)
Then there are lots of different screen classes that inherit from MyScreen, and instantiate each other at will.
(in all cases, removing the "My" gives you the name of the respective library class that it extends)
This model worked fine, until I encountered some problems to perform actions between screens using the Action system. I decided then that it would be a good idea to have a single OmnipresentActor belonging to MyGame that, as the name says, is present in every scene. So I modified MyStage to look more or less like this:
public class MyStage extends Stage {
public MyStage(MyGame g) {
super(new FitViewport(MyGame.WIDTH, MyGame.HEIGHT), g.batch);
addActor(game.omnipresentInvisibleActor);
}
#Override
public void clear() {
unfocusAll();
getRoot().clearActions();
getRoot().clearListeners();
removeActorsButNotListenersNorActions();
}
public void removeActorsButNotListenersNorActions() {
for (Actor a : getActors()) if (a.getClass()!= OmnipresentInvisibleActor.class) a.remove();
}
It followed a painful debugging phase, until I found out the following:
public PresentationScreen(MyGame g) {
// super() call and other irrelevant/already debugged code
System.out.println("PRINT_BEFORE: "+ stage.getActors().toString()); // OmnipresentActor is there
mainMenuScreen = new MainMenuScreen(game);
System.out.println("PRINT_AFTER: "+ stage.getActors().toString()); // OmnipresentActor is not there anymore, but was added to the mainMenuScreen
the "PRINT_BEFORE" statement shows that the stage holds the omnipresentActor. In "PRINT_AFTER" it isn't there anymore, whereas mainMenuScreen is indeed holding it. So my question, now more precise:
does scene2d prevent this to happen, or am I doing something wrong here?
Answers much appreciated! Cheers
An actor can only be a member of one stage: Thanks to #Tenfour04 for confirming that. The explanation is quite clear after doing a little research:
Stage.addActor() looks like this:
(here the github code of Stage.java)
/** Adds an actor to the root of the stage.
* #see Group#addActor(Actor) */
public void addActor (Actor actor) {
root.addActor(actor);
}
whereas root is simply initialized as a group in the Stage constructor: root = new Group();.
And Group.addActor() looks like this:
(here the github code of Group.java)
/** Adds an actor as a child of this group. The actor is first removed from its parent group, if any. */
public void addActor (Actor actor) {
if (actor.parent != null) actor.parent.removeActor(actor, false);
children.add(actor);
actor.setParent(this);
actor.setStage(getStage());
childrenChanged();
}
So in the tree first lines is the answer: when creating the new stage, if the actor to add already has a parent, it is removed from its current parent. So, There are two possible solutions to the problem I enounced:
SOLUTION 1: Override addActor removing the if statement, or any other alteration of the library, which I'm not sure if it would work. I rather think this could be very problematic, for instance it could prevent the stages from disposing correctly
SOLUTION 2: Change the design so you don't need an omnipresent actor, nor changing/reimplementing the libraries. For the moment this is what I've done based on this answer, it isn't very clean but it works so far:
1) In the MyScreen class added the following fields:
private boolean watchingTemp;
private Actor watchActorTemp;
private Action actionTemp;
2) Then added this method:
public void addActionOnStageAfterActorEndsHisActions(Actor actor, Action action) {
watchActorTemp = actor;
actionTemp = action;
watchingTemp = true;
}
3) then in the render method, I added the following:
if (watchingTemp && !watchActorTemp.hasActions()) {
watchingTemp = false;
stage.addAction(actionTemp);
}
4) finally, when wishing to perform an action at a screen transition (and eventually disposing the first one), you can do something like this: I use something similar when clicking on a door between screens
public void movePlayerTHENgotoNewScreen(float xPos, float yPos, whatever else...) {
game.player.walkToAnyPoint(xPos, yPos);
yourFavoriteScreen.addActionOnStageAfterActorEndsHisActions(game.player, gotoNewScreen(wathever else...));
}
Hope it helps!

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);

Cocos2d-x : stop Previous action

how to stop the previous action in Cococs2d-x
my sprite have continous animation in init method
and recently i launched move action
i want to stop that move action only
that repeat animation still to be there only.
For action we can set Tag using setTag method. When you don't want that action remove that using CCNode method "removeActionByTag"
Hi bit late to the party.
Another solution is to call stopAction(currentAction) before calling runAction(newAction). This enables you to stop currentActionSave before you start newAction. You will need to store the currentAction somehow, probably a member var, so you can later call stopAction(currentAction).
Heres a code example:
Dog.h
#include "cocos2d.h"
class Dog : public cocos2d::Sprite
{
public:
....
private:
....
bool OnTouchEnded(cocos2d::Touch* touch, cocos2d::Event* /*event*/)
cocos2d::Action* m_currentAction = nullptr;
};
Dog.cpp
#include "Dog.h"
....
bool Dog::OnTouchEnded(cocos2d::Touch* touch, cocos2d::Event* /*event*/)
{
using namespace cocos2d;
....
MoveTo* moveTo = MoveTo::create(time, pos);
if (m_currentAction)
{
stopAction(m_currentAction);
}
m_currentAction = runAction(moveTo);
return true;
}
Hope this helps someone.

function new or public static main

I am new to Haxe and probably this is a pretty basic question, which I can't really find an answer.
I see three ways to call main class:
1) use main()
//Entry point
public static main():void{
//do something...
}
2) use constructor new()
//Constructor
public function new(){
// init
}
3) use both main() and new()
static function main()
{
Lib.window.onload = function(e) new Main();
}
public function new()
{
//init
}
Is there a guideline or best practice to which one to use?
Thanks
Addressing all 3:
static function main() {} is the correct entry point. No matter which target, Haxe always begins execution at main().
The new() constructor isn't called automatically, if you want your main app to execute as an object rather than from a static function, you have to explicitly create the object: static function main() { new Main(); }
Some people prefer to keep their code in an object, rather than in static functions, which is where your 3rd example comes from. I usually do, and that's what you show in your 3rd example.
A few extra points:
The steps things are executed is explained here, basic summary:
All types/classes are registered
Boot.__init() runs platform specific initializations
Classes which have static function __init__() initialization methods are initialized
Static variables are intiailzed
Your main() function is executed
If you compile a class without a -main Main argument, but with the class path/name as an argument (eg haxe my.pack.MyClass) and with no public static function main(), the class is compiled, but it is not run automatically. This can be useful if you are creating a library or something similar - your class is there, but it needs to be called explicitly by some other Javascript etc.
In Javascript, the Haxe code starts running as soon as it is loaded, possibly before the DOM is ready. That is why it is a good idea to do:
static function main() {
js.Lib.window.onload = function(e) { runMyApp(); }
}
As you did in your example, this is a good idea if you want your code to run after the DOM is ready. Whether on load you call another static function, or instantiate a new MyApp() and run your app from there, that is up to you.