8802Fermer8804
BrunniLe 10/04/2016 à 05:45
En parlant de chinois (dans l'autre topic), tenez vous à carreau de Cocos2D-X. Presque jamais quoi que ce soit dans ma vie ne m'a provoqué autant de frustration. Il y a une ligne de code pour faire tout ce que vous voulez, mais si vous n'avez pas écrit la bonne vous êtes bons pour tout refactorer. Les libs, un énorme pavé monolithique fait 80 Meg de code source plein de macros que vous avez intérêt à avoir le meilleur IDE au monde pour avoir une autocompletion qui marche et met 8 min à compiler sur un i7 quad-core à 3.2 GHz (comptez 30 sur un portable), plus 5 secondes de temps de compil à chaque fichier qui #include la lib. Et dans ce cas ne vous attendez pas à une BDD de symboles de moins de 120 Mo, et moins d'une seconde de réponse pour que le popup apparaisse.

J'ai voulu faire un tout bête :
label1 = cocos2d::Label::createWithBMFont("Fonts/Menu.fnt", text, cocos2d::TextHAlignment::CENTER);
label1->setPosition(Vec2(visibleSize.width / 2 + origin.x, origin.y + 50));
label1->setScale(scale);
node->addChild(label1, 1);

Mais maintenant si je veux détecter un clic dessus ? Ben je peux pas. Juste pas, donc je dois utiliser un MenuItemLabel, qui requiert d'avoir un Menu, avec un autre type de container, et surtout n'a pas de constructeur avec un BMFont. A noter d'ailleurs que les constructeurs sont des méthodes statiques qui font toutes ce genre de choses :

Label* Label::createWithTTF(const std::string& text, const std::string& fontFile, float fontSize, const Size& dimensions /* = Size::ZERO */, TextHAlignment hAlignment /* = TextHAlignment::LEFT */, TextVAlignment vAlignment /* = TextVAlignment::TOP */)
{
    auto ret = new (std::nothrow) Label(hAlignment,vAlignment);

    if (ret && ret->initWithTTF(text, fontFile, fontSize, dimensions, hAlignment, vAlignment))
    {
        ret->autorelease();
        return ret;
    }

    CC_SAFE_DELETE(ret);
    return nullptr;
}

Ca signifie qu'après tu dois implémenter une initWithTTF qui a la même signature et fait presque la même chose, et surtout ça signifie que si tu veux surclasser cette merde ben tu dois réimplémenter tous les constructeurs statiques. How things could have gone so wrong, et surtout si longtemps ? Comment peut-on bosser sur un tel projet si longtemps et ne pas se rendre compte qu'on… fait de la merde ?

Man, putain je veux simplement détecter un foutu clic qqpart sur l'écran et c'est pas possible. Ils ont un callback sur certains éléments… tu peux savoir que le touch a été démarré, bougé ou cancellé mais t'as même pas un argument pour te dire la position !!! Voilà ce que tu dois faire, sur ta scène principale, donc sans gérer la notion d'UI et d'élément, pour simplement détecter un foutu clic qqpart. Je m'occuperai ensuite de router à mano parce que c'est trop compliqué sinon. Alors voilà ce que, juste pour un minuscule test de clic pour faire passer à la prochaine scène, je dois écrire, après près d'une demie heure de lecture de doc & code source :

Header :
class PendantSelectorScene : public cocos2d::Layer {
	cocos2d::Vec2 startTouchPosition;

	bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
	void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);
	void onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event);
	void onTouchCancelled(cocos2d::Touch* touch, cocos2d::Event* event);
Dans le init:
	auto touchListener = EventListenerTouchOneByOne::create();
	touchListener->onTouchBegan = CC_CALLBACK_2(PendantSelectorScene::onTouchBegan, this);
	touchListener->onTouchEnded = CC_CALLBACK_2(PendantSelectorScene::onTouchEnded, this);
	touchListener->onTouchMoved = CC_CALLBACK_2(PendantSelectorScene::onTouchMoved, this);
	touchListener->onTouchCancelled = CC_CALLBACK_2(PendantSelectorScene::onTouchCancelled, this);

	_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
Puis implémenter évidemment :
bool PendantSelectorScene::onTouchBegan(Touch* touch, Event* event) {
	startTouchPosition = touch->getLocationInView();
	return true;
}

void PendantSelectorScene::onTouchEnded(Touch* touch, Event* event) {
	if (startTouchPosition.distance(touch->getLocationInView()) < 5) {
		// Ok we fucking clicked here
		proceedToNextScene();
	}
}

void PendantSelectorScene::onTouchMoved(Touch* touch, Event* event) {
}

void PendantSelectorScene::onTouchCancelled(Touch* touch, Event* event) {
	onTouchEnded(touch, event);
}
Et au passage ça marche même pas alors je suis bon pour lire encore plus de merde pour comprendre pourquoi.

[Edit] 40 min plus tard on dirait que juste ce n'est pas possible de mettre un event listener à une scène. Enfin si, c'est possible dans une autre scène, avec exactement le même code mais va comprendre. J'ai assez passé de temps à déboguer. Alors je vais me créer un container transparent auquel je l'ajoute.

[Edit] Encore plus tard voilà la merde que j'ai écrite à la place :
	auto touchStart = [=](Vec2 pos) {
		startTouchPosition = pos;
	};
	auto touchEnd = [=](Vec2 pos) {
		if (startTouchPosition.distance(pos) < 10) {
			TEMP("Next scene");
		}
	};

	//Create a "one by one" touch event listener (processes one touch at a time)
	auto touchListener = EventListenerTouchOneByOne::create();
	// When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
	touchListener->setSwallowTouches(true);

	// Example of using a lambda expression to implement onTouchBegan event callback function
	touchListener->onTouchBegan = [=](Touch* touch, Event* event) {
		touchStart(touch->getLocationInView());
		return false;
	};
	//Process the touch end event
	touchListener->onTouchEnded = [=](Touch* touch, Event* event) {
		touchEnd(touch->getLocationInView());
	};

	auto mouseListener = EventListenerMouse::create();
	mouseListener->onMouseDown = [=](EventMouse *event) {
		touchStart(event->getLocationInView());
	};
	mouseListener->onMouseUp = [=](EventMouse *event) {
		touchEnd(event->getLocationInView());
	};

	_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, scrollView);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener, scrollView);
Inefficace au possible, dégueulasse (je ne fais même plus de classes, j'ai tellement refactoré et pris des heures entières que ça ne vaut même plus la peine, je fais tout dans une méthode et les fonctions sont factorisées sous la forme de lambda, bref je fais du Javascript++).