Moving a physics object within the conditional of a collision event

Moving a physics object within the conditional of a collision event
0

#1

I have, without any api reference to an actual working model, been attempting to recreate a slingshot, but with limited ammo.

The ball’s sprite and physics body were defined in the header as:

// ball physics body (meaning physicsBallBody)
    cocos2d::PhysicsBody *physicsBBody = nullptr;

// ball sprite
    cocos2d::Sprite *DEL1BALL = nullptr;

It is connected to an invisible non-dynamic sprite by a spring joint, and when the touch is released that non-dynamic sprite is removed, launching the ball.

I set a collision method for when the ball collides with the ground, a method which will decrease the integer “AMMO” by 1 each floor collision(this is not what the end result will be like, only experimental to understand behavior trees), Once AMMO, which begins as 4, reaches 0, the game is over, as you have lost all your ammo. I have set up the win and lose actions, but my issue is the ammo. Observe the video:

The ball is a global child, The joint can easily be redeclared (not a current issue), and the sprite which the ball launches from is global. You can see I can easily remove the ball on a collision, but I can’t call it back in the conditional. How do I call back the ball (with it’s physics components) in the if statement?
Here is the init code in which the ball, joint and other sprite(“SLINGDOT”, using background.png) is defined:

DEL1BALL = Sprite::create("ballo.png");

		physicsBBody = PhysicsBody::createCircle(178);
		
		physicsBBody->setCollisionBitmask(2);
		physicsBBody->setContactTestBitmask(true);
			PhysicsMaterial(8.9f, 0.2f, 0.4f);
			physicsBBody->setDynamic(true);
			physicsBBody->setGravityEnable(true);
			
			DEL1BALL->setScale(0.13);
	
		                                         
			DEL1BALL->addComponent(physicsBBody);
			DEL1BALL->setPosition(Point(194, 450));
	
    DEL1SLINGDOT = Sprite::create("Background.png");
	SpringBody = PhysicsBody::createBox(Size(40, 60)),
	PhysicsMaterial(8.9f, 0.2f, 9.4f);

	SpringBody->setCollisionBitmask(8);
	SpringBody->setContactTestBitmask(true);
	DEL1SLINGDOT->setScale(0.1);
	DEL1SLINGDOT->setOpacity(1);
	DEL1SLINGDOT->setPosition(Point(194, 450));
	SpringBody->setDynamic(false);

	DEL1SLINGDOT->addComponent(SpringBody);
	
	PhysicsJointSpring* joint = PhysicsJointSpring::construct(SpringBody, physicsBBody, Point::ZERO, Point::ZERO, 1800.6f, 0.8f);
	getPhysicsWorld()->addJoint(joint);

	
		addChild(DEL1BALL);
        addChild(DEL1SLINGDOT);

and the collision method

bool DEL1::onContactBegin(cocos2d::PhysicsContact &contact)
{
	PhysicsBody *a = contact.getShapeA()->getBody();
    PhysicsBody *b = contact.getShapeB()->getBody();

	if ((1 == a->getCollisionBitmask() && 2 == b->getCollisionBitmask()) || (2 == a->getCollisionBitmask() && 1 == b->getCollisionBitmask()))
	{
	   CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("Ball collision.mp3");
	   AMMO -= 1;

	   
	   
	   //removeChild(DEL1BALL);
	   if (AMMO == 1)
	   {
		AMMO1 = Sprite::create("AMMO STATUS 0.png");
		addChild(AMMO1);

		CCLOG("1 circle remaining");
		AMMO1->setPosition(Point(120, 540));

		AMMO1->setScale(0.3);
	    }


	else if (AMMO == 2)
	{
		AMMO2 = Sprite::create("AMMO STATUS 1.png");
		addChild(AMMO2);


		CCLOG("2 circles remaining");
		AMMO2->setPosition(Point(120, 540));

		AMMO2->setScale(0.3);
	}


	else if (AMMO == 3)
	{
		AMMO3 = Sprite::create("AMMO STATUS 2.png");
		addChild(AMMO3);
		removeChild(AMMO4);
		CCLOG("3 circles remaining");
		AMMO3->setPosition(Point(120, 540));
        AMMO3->setScale(0.3);
		/*
		addChild(DEL1BALL);
		DEL1BALL->setScale(0.13);

		
		DEL1BALL->addComponent(physicsBBody);
		DEL1BALL->setPosition(Point(194, 450)); */
	   }




	else
	{

			DEL1LOS = Sprite::create("LOS DE.png");
			this->addChild(DEL1LOS);
			DEL1LOS->setPosition(Point(740, -1390));
			DEL1LOS->setScale(1.9f);
		



			// create a MoveBy Action to where we want the sprite to drop from.
			auto move = MoveBy::create(2, Point(0, 1830));

			// create a BounceIn Ease Action
			auto move_ease_in = EaseBounceIn::create(move->clone());


			// create a delay that is run in between sequence events
			auto delay = DelayTime::create(0.25f);

			// create the sequence of actions, in the order we want to run them
			auto seq1 = Sequence::create(move_ease_in, delay,
				delay->clone(), nullptr);

			// run the sequence and repeat forever.
			DEL1LOS->runAction(seq1);

			CCLOG("gameover");
		



		DEL1_EXILEV = MenuItemImage::create("EXITLEVELBUTTON.png", "EXITLEVELBUTTON.png", CC_CALLBACK_1(DEL1::DEL1EXILE, this));
		DEL1_RESLEV = MenuItemImage::create("RESTARTLEVELBUTTON.png", "RESTARTLEVELBUTTON.png", CC_CALLBACK_1(DEL1::DEL1RESLE, this));


		DEL1_EXILEV->setPosition(Point(-50, 620));
		DEL1_RESLEV->setPosition(Point(1680, 620));

		Jtion = MoveBy::create(2, Point(650, 0));
		DEL1_EXILEV->runAction(Jtion);
		Ktion = MoveBy::create(2, Point(-840, 0));
		DEL1_RESLEV->runAction(Ktion);

		DEL1_EXILEV->setScale(1.8);
		DEL1_RESLEV->setScale(1.8);

		auto *DEL1meu = Menu::create(DEL1_EXILEV, DEL1_RESLEV, NULL);
		DEL1meu->setPosition(Point(0, 0));
		this->addChild(DEL1meu);
		CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("Ball collision.mp3");
		physicsBBody->setEnabled(false);
	}
	}

	return true;
}

The only focus is

else if (AMMO == 3)
	{
		AMMO3 = Sprite::create("AMMO STATUS 2.png");
		addChild(AMMO3);
		removeChild(AMMO4);
		CCLOG("3 circles remaining");
		AMMO3->setPosition(Point(120, 540));
        AMMO3->setScale(0.3);
		/*
		addChild(DEL1BALL);
		DEL1BALL->setScale(0.13);

		
		DEL1BALL->addComponent(physicsBBody);
		DEL1BALL->setPosition(Point(194, 450)); */
	   }

and the aim is to, on it’s call, position the ball, with it’s physical components, on the point (I can sort out the rest from here)


#2

With extensive trial and error I have partly made progress. when the ball collides I can make a sprite go to the wanted position. But when I simply give it a physics body it doesn’t appear in the set position


#3

What do yo mean by this? You have a sprite with a physics body attached?


#4
DEL1SLINGDOT = Sprite::create("Background.png");
SpringBody = PhysicsBody::createBox(Size(40, 60)),
PhysicsMaterial(8.9f, 0.2f, 9.4f);

SpringBody->setCollisionBitmask(8);
SpringBody->setContactTestBitmask(true);
DEL1SLINGDOT->setScale(0.1);
DEL1SLINGDOT->setOpacity(1);
DEL1SLINGDOT->setPosition(Point(194, 450));
SpringBody->setDynamic(false);

DEL1SLINGDOT->addComponent(SpringBody);

    addChild(DEL1SLINGDOT);

all my physical assets are sprites with physics bodies attached, but otherwise i really need to fix this bug, I simply want to reload a global physics body AFTER a collision, by removechilding it and adding it again to a specific position,


#5

I guess I don’t understand your problem.

What do you mean simply give it a physics body? Are you just adding a physics body without a sprite?

Also, no spaces in your file names. This may cause you issues down the road


#6

Sorry for the confusion, If you see the video, when the ball collides (final scene) it lags. That is partly fixed. On collision the ball reloads and goes back to position in the form of a sprite. But Ofcourse I want it to go back in the form of a physics body. So I did this in the collision method:

(made a new ball sprite (called DEL1ALL) go there)

if ((1 == a->getCollisionBitmask() && 2 == b->getCollisionBitmask()) || (2 == a->getCollisionBitmask() && 1 == b->getCollisionBitmask()))
	{
		CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("Ball collision.mp3");
		removeChild(DEL1BALL);

		auto DEL1ALL = Sprite::create("ball.png");


		DEL1ALL->setPosition(Point(194, 450));

		auto physicsody = PhysicsBody::createCircle(178);

		addChild(DEL1ALL);
		//PhysicsMaterial(0.1f, 0.1f, 0.1f);
		//physicsody->setDynamic(false);
		//physicsody->setGravityEnable(false);
		


		//DEL1ALL->addComponent(physicsody);

		DEL1ALL->setScale(0.13);

without the commenting, on collision, it looks like this (still image)

with the commenting removed, for some reason the ball vanishes on collision to point (0, 0), Which is the problem.
LOOK2


#7

Sure, the ball is going back to Point(0,0) because you don’t issue a setPosition() call like you did before.

But why remove and then add again? Why not just reset the position of DEL1ALL Sprite?


#8

That didn’t do anything, even when i set dynamic to false.

sorry, but I don’t follow, I generally do not see another way of positioning the ball (other than with actions)


#9

What? You must know because you issued this above but you didn’t after you removed and re-added it


#10

What did you do to try?


#11

in the method:
set the ball’s position to the preferred one, and set it to non-dynamic. But it just didn’t do anything


#12

Really, I do not recall using anything but setposition. I even looked at the edits


#13

Yes use set position. That is what I mean.

Remove.

Set position

Add again.

Although I disagree with making sprites where you did. But that’s another topic.


#14
 if ((1 == a->getCollisionBitmask() && 2 == b->getCollisionBitmask()) || (2 == a->getCollisionBitmask() && 1 == b->getCollisionBitmask()))
	{
		CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("Ball collision.mp3");
		removeChild(DEL1BALL);
{
		DEL1ALL = Sprite::create("ballo.png");
		DEL1ALL->setPosition(Point(194, 450));

		physicsody = PhysicsBody::createCircle(178);


		PhysicsMaterial(0.1f, 0.1f, 0.9f);
		physicsody->setDynamic(false);
		physicsody->setGravityEnable(false);



		DEL1ALL->addComponent(physicsody);

		DEL1ALL->setScale(0.13);
			this->addChild(DEL1ALL);
	}

but then i get the (0, 0) error

All over, I just used a moveto action to save time.


#15

Don’t you get a compiler error with the duplicate { you have? Are you trying to namespace something locally in a function?


#16

setPosition last? Wild guess without debugging, some function in there is setting some positions after you set position.

Also: You can store Point(194, 450) as a variable or definition somewhere, Point startPoint = Point(194, 450), can remove magic numbers and easier to change in one place if you decide to later on.
DEL1ALL->setPosition(startPoint);