I need to create a controller of the BGM volume and I select to use the slider bar.
What I want is to play a sound effect when the value changed.
Here is my code:
auto bgm = Slider::create();
bgm->loadBarTexture("data/menu/config/MaterBlack.png");
bgm->loadProgressBarTexture("data/menu/config/Mater.png");
bgm->setPosition(Vec2(400, 297.7));
bgm->setMaxPercent(20);
bgm->setPercent(20);
bgm->addEventListener([&](Ref* sender, Slider::EventType type) {
if (type == Slider::EventType::ON_PERCENTAGE_CHANGED) {
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("data/se/039.wav");
}
});
Confusingly, every time when I moved my finger on the slider bar(I didn’t change the value), it would always play the SE.
Then I added a log function to the event to display the value of EventType.
I found that the value of EventType is always among 0, 1, 2, as touch_move, touch_down, touch_up.
Is this a bug of cocos2dx? So how can I modify the source code to fix this problem?
I’m using the cocos2dx v3.10 and Xcode to develop my game.I debugged on iOS emulator.
I’ve found the resolution.
I think it’s a bug of cocos2dx.
In my opinion, percentage changing doesn’t mean that your finger has moved.
So I modified the code in UISlider.cpp and UISlider.h
I added a new item in enum EventType called ON_TOUCH_MOVE at UISlider.h
enum class EventType
{
ON_PERCENTAGE_CHANGED,
//@since v3.7
ON_SLIDEBALL_DOWN,
ON_SLIDEBALL_UP,
ON_SLIDEBALL_CANCEL,
ON_TOUCH_MOVE
};
And I changed the way the callback functions work.
bool Slider::onTouchBegan(Touch *touch, Event *unusedEvent)
{
bool pass = Widget::onTouchBegan(touch, unusedEvent);
if (_hitted)
{
int percent_old = getPercent();
int percent_new = getPercentWithBallPos(_touchBeganPosition);
if (percent_old != percent_new && percent_new >= 0 && percent_new <= getMaxPercent()) {
setPercent(percent_new);
percentChangedEvent(EventType::ON_SLIDEBALL_DOWN);
percentChangedEvent(EventType::ON_PERCENTAGE_CHANGED);
} else {
setPercent(percent_new);
percentChangedEvent(EventType::ON_SLIDEBALL_DOWN);
}
}
return pass;
}
void Slider::onTouchMoved(Touch *touch, Event *unusedEvent)
{
_touchMovePosition = touch->getLocation();
int percent_old = getPercent();
int percent_new = getPercentWithBallPos(_touchMovePosition);
if (percent_old != percent_new && percent_new >= 0 && percent_new <= getMaxPercent()) {
setPercent(percent_new);
percentChangedEvent(EventType::ON_PERCENTAGE_CHANGED);
} else {
setPercent(percent_new);
percentChangedEvent(EventType::ON_TOUCH_MOVE);
}
}
void Slider::onTouchEnded(Touch *touch, Event *unusedEvent)
{
Widget::onTouchEnded(touch, unusedEvent);
percentChangedEvent(EventType::ON_TOUCH_MOVE);
percentChangedEvent(EventType::ON_SLIDEBALL_UP);
}
Then it works as I wish.
1 Like