Here is the topic on Difference between CCNode::init() and CCNode::onEnter(). However I followed the advice they gave.
void MyLayer::onEnter() {
CCLayer::onEnter();
//your code goes here
}
I got the Assertion failed! error!
MyLayer code:
class MyLayer : public CCLayerColor
Should I add CCLayerColor::onEnter() in my MyLayer::onEnter() code? And what is the difference between CCLayer::init() and CCLayer::onEnter(). Which part of code should I put into init() and which part should put into onEnter()?
Cocos2d-x has its memory allocation model as a two-step process, like objective-c. Each object has memory allocated (usually using a "create" method) and then has its state initialized (usually using a method called "init"). So in the create/init methods, you allocate the memory and do any object initialization necessary for it to run.
When the object starts to be put onto the display, or when it is added to another container, its "onEnter" method is called. This gets called when a CCScene/CCLayer (either of which may be containing your CCNode derived object) is displayed by the framework itself.
There are at least 2 patterns for memory allocation and object creation, I tend to follow the pattern of having a class contain a static factory method and a private constructor so that it is unambiguous that you must create the objects through the factory and cannot create one yourself.
For example, I am currently working on this "button" class:
class ActionButton;
class ActionButtonTarget
{
public:
virtual void ActionButtonActivated(ActionButton* button) = 0;
};
class ActionButton : public CCNode, public CCTargetedTouchDelegate
{
private:
ActionButton();
CCNode* _node; // Weak Reference
CCRect _testRect;
ActionButtonTarget* _target;
bool init(ActionButtonTarget* target, CCNode* node, CCRect rect);
bool IsTouchInside(CCTouch* touch);
void NotifyTarget();
protected:
virtual CCAction* CreateAction();
public:
virtual ~ActionButton();
// The class registers/unregisters on entry
// or exit of the layer. This
virtual void onEnterTransitionDidFinish();
virtual void onExitTransitionDidStart();
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
static ActionButton* create(ActionButtonTarget* target, CCNode* node, CCRect rect);
};
Note that the "create" method is the only way to create it. In this case, it takes arguments for parameters of the button. Other CCNode derived objects (e.g. CCScene) usually do not.
Internally:
ActionButton::ActionButton()
{
}
ActionButton::~ActionButton()
{
}
// The class registers/unregisters on entry
// or exit of the layer. This
void ActionButton::onEnterTransitionDidFinish()
{
CCNode::onEnterTransitionDidFinish();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
void ActionButton::onExitTransitionDidStart()
{
CCNode::onExitTransitionDidStart();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool ActionButton::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
if(IsTouchInside(pTouch))
{
return true;
}
return false;
}
void ActionButton::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
// Nothing to do here.
}
void ActionButton::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
NotifyTarget();
}
bool ActionButton::IsTouchInside(CCTouch* touch)
{
CCPoint point = touch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
return _testRect.containsPoint(point);
}
void ActionButton::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
{
_target->ActionButtonActivated(this);
}
ActionButton* ActionButton::create(ActionButtonTarget* target, CCNode* node, CCRect rect)
{
ActionButton *pRet = new ActionButton();
if (pRet && pRet->init(target,node,rect))
{
pRet->autorelease();
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
return NULL;
}
}
CCAction* ActionButton::CreateAction()
{
return NULL;
}
void ActionButton::NotifyTarget()
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(Constants::SOUND_EFFECT_BUTTON_CLICK());
_target->ActionButtonActivated(this);
}
bool ActionButton::init(ActionButtonTarget* target, CCNode* node, CCRect rect)
{
assert(target != NULL);
assert(node != NULL);
assert(dynamic_cast<ActionButtonTarget*>(target) != NULL);
_target = target;
_node = node;
_testRect = rect;
addChild(_node);
return true;
}
Note the OnEnterXXX and onExitXXX methods call the parent class method. YOU MUST DO THIS or it will not work as expected.
This class is a button that will run an action on the node (maybe make it grow/shrink to indicate it got pressed). It takes touches from the user. I cannot add it to the touch manager before it has entered the scene. So I use the onEnterTransitionDidFinish method to add it and also use the onExitTransitionDidStart to remove it so it will not continue to receive touches after the scene has been removed. I don't know if the container will be destroyed or not, so I must remove it when the button exits the display.
Was this helpful?
Ist Part
Check out OnEnter method of base class(CCLayer),if some serious stuff is going on ,then you should have called it.
IInd Part
As in the topic... OnEnter is called when "viewDidAppear" and init during initialisation.
Suppose you create layer by this
MyLayer *newLayer=MyLayer::create(); //...init is called before OnEnter..
After that you add it to some scene
X->addChild(newLayer); // ...*Now onEnter Method is called
*X must be added to some scene or parent and so on.
IIIrd Part
In some case you just create multiple objects stored in array,but didn't add them. You are waiting for right time for adding them.This might be case when object enter/add to screen ,you want it to perform specific task.
Ex. In a game you have to attack someone and have 30 troops.All the troops are created in loading scene but none of them add to layer.
When battle begins, the deployed troop by user appear on the screen.Troop on enter has a task to go to target building and that method can be called through onEnter.
You call onEnter() if you want to do something the moment it appears on the screen.
The init() method will be called even without the layer being on the screen.
Something like this:
void FirstScene::methodInit()
{
customlayer = new CustomLayer();
customlayer -> init();
customlayer-> retain();
// At this point,customlayer (which is a CustomLayer object that is a subclass of CCLayer)
// is still not on the screen, hence, CustomLayer::onEnter() is still not called
}
void FirstScene::methodEnter
{
this -> addChild( customLayer, customIndex, customTag );
customLayer -> release();
// At this point, CustomLayer::onEnter() is called, because customLayer is being rendered
}
Related
How can I create a custom action for an actor in libgdx? If I can't, than is there at least an action to run a custom piece of code (eg. call a method action)? Thanks.
EDIT:
I created this class :
class GapSizeAction extends TemporalAction {
private float newSize;
private Blocker blocker;
public static GapSizeAction getRotateAction(float newSize, float duration) {
return new GapSizeAction(newSize, duration);
}
public GapSizeAction(float newSize, float duration) {
super(duration);
System.out.println("Construct");
this.blocker = (Blocker)target;
this.newSize = newSize;
}
private float start, end;
protected void begin() {
System.out.println("Begin");
start = blocker.gap;
}
protected void update(float percent) {
blocker.gap = (start + (end - start) * percent);
}
}
The problem is that I am using a custom actor with a gap member (float). I try to cast the target to a blocker so that I can access the gap member variable, but gap ends up being null. I can confirm that gap is not null, I initialize it in the constructor. The blocker (Custom actor) is not null either. Am I going about this wrong?
Your problem is the line this.blocker = (Blocker)target; in your constructor. When the constructor is called, the action hasn't been set on a target yet, so target is null (and so will be blocker). Also, since you're changing a single float, you can extend FloatAction and save yourself some code. I would write your class as below. The constructor should be empty to support easy pooling, and you can set it up in your static factory method.
class GapSizeAction extends FloatAction {
public static GapSizeAction getRotateAction(float newSize, float duration){
GapSizeAction action = Actions.action(GapSizeAction.class);
action.setEnd(newSize);
action.setDuration(duration);
return action;
}
protected void begin () {
if (target instanceof Blocker)
setStart(((Blocker)target).gap);
else
Gdx.app.logError("Target is not a blocker: " + target.toString());
super.begin();
}
protected void update (float percent) {
super.update(percent);
if (target instanceof Blocker)
((Blocker)target).gap = getValue();
}
}
Fade In Action for example :
actor.AddAction(Actions.fadeIn(2.0f));
My game has a class named Enemy which extends Actor. Additionally, I have an EnemyAffector class which has methods that affect Enemies, roughly like this:
class EnemyAffector {
public void affect(Enemy enemy) { ... }
}
In my Stage, in the act method, I want to iterate over all Enemies and apply an EnemyAffector to them. The obvious way is by casting:
#Override
public void act() {
super.act();
for (Actor actor: getActors()) {
if (actor instanceof Enemy) {
enemyAffector.affect((Enemy)actor);
}
}
...
}
However, legend has it that using instanceof should be avoided. So, I considered keeping an additional Array to which I will add Enemies as they are added to the Stage, i.e., by overloading my Stage with another addActor method:
public void addActor(EnemyProjectile pEnemyProjectile) { // add to Enemy Array }
So now my act method looks like this:
#Override
public void act() {
super.act();
for (Enemy enemy: enemyArray) {
enemyAffector.affect(enemy);
}
...
}
Yay! No instanceof!
However, the problem with this solution is that I will always need to synchronize between the Enemy Array, and the standard Actor Array because Enemies in the Enemy Array may have been removed from the Stage.
My question is, is there a different, cleaner, approach which can I take here?
You could either use the UserObject that you can add to an actor:
public enum ActorType
{
PLAYER, ENEMY, ETC;
}
//...
Enemy enemy = new Enemy();
// Or set this in the constructor
enemy.setUserObject(ActorType.ENEMY);
for (Actor actor : actors)
{
if (actor.getUserObject() == ActorType.ENEMY)
{
// Do stuff...
}
}
Or put your two arrays in an extra class and add methods for adding/removing:
public class ActorManager
{
private Array<Actor> actors = new Array<>();
private Array<Enemy> enemies = new Array<>();
public void add(Actor actor)
{
actors.add(actor);
}
public void add(Enemy enemy)
{
actors.add(enemy);
enemies.add(enemy);
}
public void remove(Actor actor)
{
actors.removeValue(actor, true);
}
public void remove(Enemy enemy)
{
actors.removeValue(enemy, true);
enemies.removeValue(enemy, true);
}
// To make sure our backing arrays are not modified:
public Array<Actor> getAll()
{
return new Array<>(actors);
}
public Array<Actor> getEnemies()
{
return new Array<>(enemies);
}
}
I quickly encountered a similar situation with LibGDX with both the Actor and Stage class. I created my own sub-class extending Actor, which I was going to use as the "base Actor" Object for all my Actors.
That way, you can set up methods which will be called by all your Actors on certain situations.
class MyStage extends Stage
{
public void addActor(MyActor pEnemyProjectile) { // call onAdd }
//override other methods as necessary,
//possibly getActors() to return Actors as MyActors, etc
}
class MyActor extends Actor
{
public void update(double delta)
{
//I find it easiest to have "removal" code happen in the Actor's update method, then I can call onRemove()
//This could happen by finding death conditions or just checking a "isDead" boolean.
}
public void onAdd()
{
//can set up a default behavior, or just override on other subclasses
}
public void onRemove()
{
//call for every Actor that gets removed - can extend and remove Enemies from an Enemy list if desired
}
//maybe it would be better to check if the Object can be Affected here?
//rather than keeping and maintaining a separate list
public boolean isAffected()
{
return false; //return true by Enemies
}
}
class Enemy extends MyActor
{
//implement onRemove, onAdd, etc..
}
If it works better, MyActor could also be created as an interface instead - and then you could just as easily create sub-classes for Label or other LibGdx classes which inherit from Actor.
I personally chose to make it a sub-class, just because I could create helper-methods which were easier to type and call - such as my "movement" and "rotation" code, which don't use the Action classes which LibGdx comes with.
The easiest and in my opinion generating least lines of code is to use UserObject Actor field like:
Actor actor = new Actor(); //or its children ofc
actor.setUserObject("enemy");
//...
if( actor.getUserObject().equals("enemy") )
{
//yup this is enemy
}
Of course it is not the best solution due to OOP and can be not very flexible in some cases but to be honest in a case like this handling additional arrays etc etc only complicates things.
Notice that UserObject is object type so if you want to push there something that Java cannot cast itself you will have to cast it on your own.
However if you would want to be super ok here's another more elegant solution:
You are overriding the Actor class with your own MyActor class with some customAction() method which do nothing. You will be inheriting from this class not from Actor now
In every child class the method do nothing but in your Enemy class you are implementing the funcionality
In a loop you are casting to (MyActor) and calling customAction method
for (Actor actor: getActors()) {
((MyActor)actor).customAction();
}
The customAction method has a logic from EnemyEffector
This would generate some problems if you are inheriting classes that inherits from Actor (like Label class) and also will be a problem if the EnemyEffector logic is using data that Actor instance should not know because they are global for example and shouldn't be redundant (of course you can also pass the information as a parameter of customAction method)
I realize the question may be confusing and the word "better" may be problematic, but I could not think of a, well, better way to ask.
Let's say you are writing an application that has a single entry point, like Main, which also serves as the composition root for IoC:
From outside, run application
Main or equivalent
var container = new AwesomeContainer();
container.Install(new CompositionRootInstaller(startArgs));
container.Register( ... );
ApplicationMiddleware = container.Resolve<IMiddleware>();
ApplicationMiddleware.SignalStart();
Here, ApplicationMiddleware might be a ControllerFactory in a web application, for instance.
Now, of course we will have lots of other services located by the container at the appropriate time (per request, for instance).
Sometimes we will run into situations where we don't feel like it's so bad to just assign, say, a default value to a field. But, in my view, this breaks IoC a little bit.
So, is it a true statement that (regardless of the marginal value of doing so) it is always better to avoid calling constructors or factories that call constructors or otherwise get components without calling the container once we leave the entry point?
Example: WinForms program
Here is the setup. It is a contrived example but I'm trying to focus on the issue at hand...
static class Program
{
[STAThread]
static void Main(string[] args)
{
using (var root = new AppCompositionRoot())
{
}
}
}
class AppCompositionRoot : IDisposable
{
private IWindsorContainer _container;
public AppCompositionRoot(IWindsorContainer container = null)
{
_container = container ?? new WindsorContainer();
}
public void Run()
{
var formFactory = _container.Resolve<DefaultFormFactory>();
Application.Idle += delegate
{
formFactory.ApplicationIsIdle();
};
Application.Run();
}
public void Dispose()
{
_container?.Dispose();
}
}
public interface IFormFactory
{
System.Windows.Forms.Form Create();
}
public class DefaultFormFactory : IFormFactory
{
private readonly IWindsorContainer _container;
private Form _lastForm;
public DefaultFormFactory(IWindsorContainer container)
{
_container = container;
}
public Form Create()
{
return _container.Resolve<AppForm>();
}
public void ApplicationIsIdle()
{
_lastForm = _lastForm ?? Create();
_lastForm.Show();
}
}
public class AppForm : Form
{
private readonly string _big; // sensible default is "Welcome!"
private readonly string _little; // sensible default is a string varying by form, time of day, factory
private readonly IList<object> _watched; // sensible default is list empty.
public AppForm(string bigMessage, string littleMessage, IList<object> watched)
{
_big = bigMessage;
_little = littleMessage;
_watched = watched;
}
public void Initialize()
{
// do something with bigMesaage, littleMessage, etc.
}
}
So let's start with concrete AppForm. It needs two strings and a List<object>.
Let's say for all of them there is a natural default that makes sense like 95% of the time, as in something that would be a const string on the class.
Regardless my question is - to really do IoC in the ideal sense, wouldn't it be true that you should always see constructors like these (clean constructors) and any defaults should be injected as well?
Inversion of Control simply states that control (whatever that is) is inverted. It doesn't mean that you have to invert everything; you should invert that which you want to vary.
If you're writing a Hello world application, and you don't want to vary anything, you can create the string within the implementation:
Console.WriteLine("Hello, world!");
On the other hand, if you want to be able to vary the message, you can pass it in as a Primitive Dependency:
public class Helo
{
private readonly string message;
public Helo(string message)
{
this.message = message;
}
public void SayHello()
{
Console.WriteLine(this.message);
}
}
If it helps, Miško Hevery makes the distinction between newables and injectables. On a different note, in my book, I've attempted to make a distinction between stable and volatile dependencies.
You can new up values that you don't need to be able to control from the outside. If you need to control them from the outside (Inversion of Control, remember), then you need to inject them.
I'm new at Libgdx and one aspect that blocks me to continue with my Libgdx learning is the fact that a I don't know how to use the GestureListener. It's seems there's a user with the same doubt if you see in this link LibGdx: Utilizing a Gesture Listener, but it didn't help me much. So my question is: how do I use my own GestureListener class to process my player moviments? I wanna use the pan function to make it jump, but I don't know how to put my player object inside the method. If you see my gesture detector class:
public class GestureHandler implements GestureListener {
// Main Game class
private ClimbUp mainGame;
public GestureHandler(ClimbUp game) {
this.mainGame = game;
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean longPress(float x, float y) {
// TODO Auto-generated method stub
return false;
}
...
Then I followed what they told the user what to do: in the main class I passed the fallowing instruction:
Gdx.input.setInputProcessor(new GestureDetector(new GestureHandler(this)));
Now in my splash screen, I don't know how to use. How to make my GestureHandler object works for all project? I'll be very grateful with an answer!
So, you have some you class which need GestureListener "services" - you want to be informed when some gesture event happens and you want to have information of gesture properties.
Then, as you did, make your class implement GestureListener interface.
After that your IDE (Eclipse or Android Studio or something else) will complain that you didn't implemented all GestureListener methods, but it can also do that for you. If you (in eclipse) hover the error in the code IDE will offer you to create missing methods.
I would say you are at about that step. But now your methods have to do something useful. Like, if you want to do something when player taps the screen add your code inside that method. Do something there. Inside GestureListener methods you have some info available, as method parameters like x & y coordinates, button (left, middle, right) and something like that.
So, when you call that setInputProcessor with object created in you class that implemented G.L. interface libGDX will know to call your methods when some event occurs.
Every method IDE generated has that "todo" mark - that's where you have to put your code instead. The code that will handle that event, move your space ship, fire the bullet or what ever. You don't have to do something for every event, but only for those you are interested in. You can leave other empty, but your class must have them.
Here is some example:
// importing interface
import com.badlogic.gdx.input.GestureDetector.GestureListener;
// defining my class that implements that interface
public class TouchController implements GestureListener{
// constructor - just storing objects passed to it.
public TouchController(Playground pg, Army army, Hud hud){
super();
this.pg = pg;
this.army = army;
this.hud = hud;
initialZoom = pg.zoom;
}
// Adding some action to touchDown method - I'm just calling my hud object's method and passing coords I get
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
hud.pressedAt(x, pg.camera.viewportHeight-y); // opposite Y axis
// TODO Auto-generated method stub
return false;
}
// Similar thing. I unproject coords I get.
#Override
public boolean tap(float x, float y, int count, int button) {
if (!hud.buttonPressed){
Vector3 touchPos = new Vector3();
touchPos.set(x, y, 0);
pg.camera.unproject(touchPos);
army.add(touchPos.x, touchPos.y, SoldierSide.RED);
}else hud.released();
return false;
}
// Again similar stuff, but this pan methods is getting also delta value (difference from last reading x and y values) which can be useful
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
if (hud.aimDrag) hud.aimDragged((int)deltaX, (int)deltaY);
else if (hud.sliderDrag) hud.sliderDragged((int)deltaX, (int)deltaY);
else if (!hud.buttonPressed) pg.panned((int)deltaX, (int)deltaY);
return false;
}
...
I have done the LoadState and SaveState and all works fine.
I just want to check in the page's constructor if I came from suspension or not...
I can do a global bool variable and when I enter to the LoadState to change it's value:
bool suspended;
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
...
if (pageState != null)
{
suspended = true;
...
}
}
public MainPage()
{
this.InitializeComponent();
if (!suspended)
{
...
}
}
This works fine, but is there something build in? I think I can check it without global variable...
In App.xaml.cs OnLaunched(LaunchActivatedEventArgs args) event can provide you that details. You just have to pass args while navigating to particular page. args has property called PreviousExecutionState