Using Cocos2d-x SEL_CallFunc - c++

I'm trying to make a custom sprite, which could receive touch and handle the function as callback.
Okay, first step, receive the touch, easy, we can search it online everywhere.
The one I couldn't do is, I want to make it receive SOMETHING in the class the sprite is created, a function that will be called when the sprite is touched.
I was searching on internet and I think (not really sure) that SEL_Callfunc can do what I want, but I couldn't understand how this one work, so can you guys give me an example please?
For example, my custom class is BSprite, so when I create new object in HelloWorld.cpp, it should be
BSprite* sprite = BSprite::create("HelloWorld.png",HelloWorld::TouchCallback);
Thanks for reading :)

sprite->addTouchEventListener(CC_CALLBACK_0(HelloWorld::onTouchSprite, this));
void HelloWorld::onTouchSprite() {
}
Note: onTouchSprite method should not have any parameters

Related

Implementing "begin contact" in box2d

I am working on a game in box2d. I have the following code:
for (int contact_num = 0; contact_num<contact_count; ++contact_num)
{
if (contact->IsTouching())
{
// get the colliding bodies
b2Body* bodyA = contact->GetFixtureA()->GetBody();
b2Body* bodyB = contact->GetFixtureB()->GetBody();
// check if one of the colliding objects is a censor
bool sensorA = contact->GetFixtureA()->IsSensor();
bool sensorB = contact->GetFixtureB()->IsSensor();
// do stuff, mainly handling variables
}
}
// Get next contact point
contact = contact->GetNext();
}
All of this is being called in the update function of my main class (which also contains most of the games variables). The problem is that I want the code to only be called when the two objects first collide, because otherwise something like score++ will end up skyrocketing in value as it gets updated for the collisions duration. I am aware of a "contact listener" class in box2d with the function "begin contact", but there is no good documentation that could help a beginer learn how to implement it. For example, if I add a contact listener to my main class, how do I get it to handle my score, for example, if the contact listener doesn't have access to those variables? Or where do I call "begin contact" in the first place? Sorry if these are obvious questions, but i was hoping someone could clarify these. Thank you in advance.
Here's a couple suggestions which hopefully will answer your question:
Take a look at Box2D C++ tutorials - Collision callbacks. Personally, I think it's a great tutorial on using the b2ContactListener class.
Just make your class which contains the score information inherit from b2ContactListener. That way your BeginContact method will have direct access to the score data. Presumably that'll be your "main" class. Be sure to also notify your b2World instance to use this by calling your world instance's SetContactListener method with a pointer to the score containing instance (that you'd subclassed from b2ContactListener).
If you still need more help with this, please add a comment to that effect or update your question to reflect what remains unclear.

Change image on StaticBitmap wxWidgets

I would like to have a window, in which a picture changes depending on what is happening during an infinite loop.
Imagine someone walking around and when he leaves a given track, the program should display an arrow towards the direction of the track. Therefore I have a program, which determines the distance between user and track, but I have no idea on how to update the image.
I use code::blocks with wxWidgets and think I have to use the wxStaticBitmap class. (If there is a better way, please tell me.)
I tried with:
while(true)
{
updatePosition();
if(userNotOnTrack)
{
if(trackRightOfUser)
{
StaticDirectionBitmap->SetBitmap("D:\\WindowsDgps\\WindowsDgpsGraphic\\arrow_right.png");
}
}
}
(Note that this snippet is mostly pseudocode, except the StaticDirectionBitmap part.)
On default the Bitmap has a "no_arrow" image. With this I get an error: error: no matching function for call to 'wxStaticBitmap::SetBitmap(const char [51])'|. I see from the documentation that this cannot work, but I have no idea what could.
If anyone knows how to handle this, I would be happy to hear. I remember a few years back, when I tried something similar in C# and failed completely because of thread safety... I hope it is not this hard in C++ with wxWidgets.
SetBitmap takes a wxBitmap parameter not a string. So the call should look something like:
SetBitmap(wxBitmap( "D:\\WindowsDgps\\WindowsDgpsGraphic\\arrow_right.png", wxBITMAP_TYPE_PNG) );
Make sure prior to making this call that the png handler has been added with a call like one of the following:
wxImage::AddHandler(new wxPNGHandler);
or
::wxInitAllImageHandlers();
The easiest place to do this is in the applications OnInit() method.
If you want update the static bitmap from a worker thread, you should throw a wxThreadEvent and then make the call to SetBitmap in the event handler. The sample here shows how to generate and handle these events.

How to use Accelerometer in cocos2dx

I've been trying to get the acceleromter to work in cocos2d-x c++.
I tried to add this function to my scene which a lot of my Google search results said I should:
virtual void didAccelerate(Acceleration *acceleration);
That does however give me an error saying I'm overriding a final function.
Then I found how I could use the EventDispatcher thing for it.
auto accListener = EventListenerAcceleration::create(CC_CALLBACK_2(MainScene::accelerated, this));
getEventDispatcher()->addEventListenerWithSceneGraphPriority(accListener, this);
In both of these I had called this function earlier in my scene's init function:
setAccelerometerEnabled(true);
I'm all out of ideas and I need help. On the second "approach" it compiled, but my accelerated function was never called.
Thank you in advance!
I'm using Android so maybe I need to edit something in the AndroidManifest?
The guys at the cocos forums linked me to this:
Cocos docs
As you can see the correct way to go is to use the EventListener approach as described earlier. However you need to call
Device::setAccelerometerEnabled(true);
Calling
setAccelerometerEnabled(true);
From the scene's init doesn't work, you need to call the static method on 'Device'.
So here's how you do it.
Device::setAccelerometerEnabled(true);
auto accListener = EventListenerAcceleration::create(CC_CALLBACK_2(MainScene::accelerated, this));
getEventDispatcher()->addEventListenerWithSceneGraphPriority(accListener, this);
Where accelerated is takes these parameters:
void accelerated(Acceleration *acceleration, Event *event);
Of course this function can be called anything as the EventListener takes a function pointer.
Tritzium answered it right. Just wanted point out:
You wont get accelerator events in simulator, you need a device.

Touch Event on Sprite with Cocos2d-x 3.x?

In my scene I have a vector with multiple custom sprites. When I tap on one of them, I want an action to be fired on another element on the scene, can be another sprite in the vector, or another node. I have been researching the best way to do this, but I'm not quite sure how to implement it. The options are:
Add a touch listener to the scene, and verify if it was tapped inside the bounds of the sprite with rect. containsPoint(point). And after that, I have to get the sprite that was tapped to do the action I want. For me, it doesn't seems very clean to do it this way. And if two sprites are overlaped, I have to verify if the sprite is behind or in the front in order to retrieve the desired sprite. I followed this example: Touch Event example
Add a touch listener in the subclass of the sprite (my custom sprite). And add onTouchBegan and onTouchEnded inside it. But this way, I don't know how to modify an attribute of another sprite, or another element in the scene (Is it possible to use Delegates like Objective-C does?). I followed this example: Subclass Sprite Example
My main problem is that I don't understand very well how to make a node interact with another node in the scene. I have seen a lot of tutorials, but in all of them, when you interact with a node, it only changes its attributes, not other nodes' attributes.
Thanks in advance.
I shall propose "EventCustom" way :)
You can add in your touchBegan / touchEnded methods (wherever you put them... you got the point...) additional code for passing an EventCusto to the _eventDispatcher and get it announced to the world ;)
EventCustom *e = new EventCustom("MyAwesomeEvent");
e->setUserData(ptrMyFantasticData); //This function takes a void pointer. cheers :)
_eventDispatcher->dispatchEvent(e);
You may subclass the EventCustom class but that is hardly necessary. You can always hang an object to it with setUserData().
Now the objects which need to react to the event can listen to it by
_myCustomListener = EventListenerCustom::create(
"MyAwesomeEvent",
CC_CALLBACK_1(
ListeningClass::onMyAwesomeEvent,
this
)
);
_eventDispatcher->addEventListenerWithXXXXXPriority(_myCustomListener, XXX);
//ScreenGraphPriority / FixedPriority depends on situation. Either should work.
It's always a good practice to remove your listeners when you go off, so somewhere, perhaps in onExit(), where you removed touch listeners remove this listener too, as
_eventDispatcher->removeEventListener(_myCustomListener);
Going a bit off the track, a clarification:
CC_CALLBACK_X are a bit tricky names. The X indicates the no. of args the target function will get. Here, event dispatcher will pass 1 arg i.e. ptr to object of EventCustom you handed it, so we use CC_CALLBACK_1. The next arg - here "this" - is the object on which the method will be invoked.
In short, we may say that this callback is going to result into a function call this->onMyAwesomeEvent(e);
For CC_CALLBACK_2 onwards, we can specify additional args, 3rd arg onwards.
Coming back to the issue at hand, ListeningClass::onMyAwesomeEvent will look something like
void ListeningClass::onMyAwesomeEvent(EventCustom *e)
{
MyFantasticData *d = (MyFantasticData *) e->getUserData();
CCLOG("[ListeningClass::onMyAwesomeEvent] %d", d->getMyPreciousInt());
}
Hope it helps :)
Set your elements tags or names with setTag and setName. Then if element x is touched, get them with getChildByTag or getChildByName and do what you need to do.
With the second option you list above.
To make a node interact with another node in the scene you can add touch callback function to your custom sprite object like that:
https://github.com/Longpc/RTS/tree/master/Classes/base/dialogBase
and in main scene you can define function to handle this callback. So you can do every thing to unit in you scene

C++ cocos2d-x pointer

I've just used cocos2d-x for creating some games. When I read the HelloWorld.cpp, I saw this line
Scene* HelloWorld::createScene()
That's strange for me. How does it work? A method named creatScene that takes no parameters and returns a pointer to a Scene ?
In different libraries, there are different methods to initialize library or some part of that. So, in this case, it maybe create a new context inside library and return it without any argument. It maybe needs no arguments (use defaults) it this step of get them from somewhere else like configuration file. And note that this is convenient to use this type of initializing. Like this:
rc = redis.Redis() #uses default values for server address
It is really an easy question even it cannot be called as question when you check the source code.
In cocos2d-x, CCScene always create this way.
1. create a Layer, which coded by yourself with a lot of other widgets.
2. create a Scene
3. add the layer to the scene
4. return the scene you create.