How can i use void ContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) method in our application? - iphone

I dont know how to use this metnod in my application
void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {
b2WorldManifold worldManifold;
contact->GetWorldManifold(&worldManifold);
b2PointState state1[2], state2[2];
b2GetPointStates(state1, state2, oldManifold, contact->GetManifold());
//NSLog(#"Presolving");
if (state2[0] == b2_addState)
{
const b2Body* bodyA = contact->GetFixtureA()->GetBody();
const b2Body* bodyB = contact->GetFixtureB()->GetBody();
b2Vec2 point = worldManifold.points[0];
b2Vec2 vA = bodyA->GetLinearVelocityFromWorldPoint(point);
b2Vec2 vB = bodyB->GetLinearVelocityFromWorldPoint(point);
b2Vec2 rV = vB - vA;
float32 approachVelocity = b2Dot(rV, worldManifold.normal);
if (-1.5f < approachVelocity && approachVelocity < 0.0f)
{
//MyPlayCollisionSound();
NSLog(#"Not Playing Sound");
}
else
{
NSLog(#"playing the sound");
}
}
}
How can I use this code in my HelloWorldLayer.mm Please help me...
I have a problem here, I have a scene where some bodies falls and hit a static body, edges alike, I implemented the b2ContactListener, and in my tick method Im checking for contacts and play the sound, the problem with this approach is that when a body is constantly in contact with the static body, the sound plays indefinitely overlaying the previous one, so at the end I have huge noise..
What can I do to avoid this situation?
Please help me thanks......

You just used following method into your update method and declare its object before schedule update method call.
Like in HelloWorldLayer.h
MyContactListener *contactListener;
And in HelloworldLayer.mm
Before
[self scheduleupdate];
contactListener=new MyContactListener();
world->setContactListener(contactListener);
Than this type of error not occur.

When two bodies collide, the b2ContactListener methods are called in the following sequence:
BeginContact
PreSolve
PostSolve
PreSolve
PostSolve
...etc
EndContact
So if you want to detect collision between the bodies once for each collision, use BeginContact or EndContact instead. These methods only take a single b2Contact parameter though so you might need to do away with using the oldManifold value in your calculation.

Related

How can I make a simple automatic shoot function for a gun in Unity?

I am trying to create a procedural gun controller, but I can't find why my gun behaves so weird when I change the fire mod to automatic. To understand this better, I will give an example: when I try to shoot by pressing the "Mouse0" key, on semi auto mod it works fine, it behaves like I want it to (the bolt kicks back when I shoot, the front barrel kicks back - I animate them with code instead of frame animations from Unity or a 3rd party soft like Blender), but..., when I change to automatic, the problem is not that I get errors, The animations of the moving pieces don't work as they should and are not triggered correctly.
I tried to use different methods for shooting(using the WaitForSeconds() and WaitForSecondsRealtime() while using coroutines). It didn't work. I tried using the time function with scaled and unscaled time in the update function. I still got the same results.
What should I do to?
This is the shoot function untill now:
void GunFireManagement()
{
if (fireType == fireMethod.single)
{
foreach (BlowBack anim in animations)
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
anim.piece.transform.position = anim.kickbackState.transform.position;
}
if (anim.piece.transform.position != anim.initialPosition.transform.position)
{
anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
}
Destroy(gunSoundClone, 0.5f);
}
}
if (fireType == fireMethod.auto)
{
foreach (BlowBack anim in animations)
{
if (Input.GetKey(KeyCode.Mouse0) && Time.time - lastFired > 1f/autoFireRate)
{
lastFired = Time.time;
gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
anim.piece.transform.position = anim.kickbackState.transform.position;
}
if (anim.piece.transform.position != anim.initialPosition.transform.position)
{
anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
}
Destroy(gunSoundClone, 0.5f);
}
}
}
The issue is how you are using Vector3.Lerp. The first two arguments you pass to the method are supposed to be the start and end positions of the animation, and the third one, t, is supposed to be the progress of the animation from the start towards the end, as a value between 0 and 1.
You can calculate the value of t by dividing the time since the shot started with the duration of the animation. For example if the length of the animation is 2 seconds, and the short started 1 second ago, then t should be 0.5.
if(isFiring)
{
float timeSinceShotStart = Time.deltatime - lastFired;
// t = s / v
float animationDuration = 1f / anim.speed;
UpdateBlockBackAnimationState(timeSinceShotStart / animationDuration);
}
}
private void SetBlowBackAnimationState(float progress01)
{
foreach(BlowBack anim in animations)
{
Vector3 initialPosition = anim.initialPosition.transform.position;
Vector3 finalPosition = anim.finalPosition.transform.position;
anim.piece.transform.position = Vector3.Lerp(initialPosition, finalPosition, progress01);
}
}
I recommend you try to split up your code into smaller methods that are easier to understand. You are trying to do so many things in one generic "GunFireManagement" method that it becomes pretty difficult to keep track of all the different pieces :)
I also recommend considering using a tweening framework such as DOTween to make it easier to animate things over time.

How to find out who shot a projectile

So I am trying to make a multiplayer game with abilities sort of like Overwatch/Paladins. All in all, one ability should be a sort of projectile that moves across the ground and allows that player to teleport to its position at any time while it is alive. I can't find the solution to teleporting only the player that shot it since thus far in my tests, when one player activated their ability, all players would teleport. How can I solve this?
My code:
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
GetComponent<playerController>().heldAbility = "gateCrash";
if (GetComponent<playerController>().heldAbility == "gateCrash")
holding = true;
else
holding = false;
if (holding && Input.GetMouseButtonDown(0))
PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "GateCrashModel"), spawnPos, transform.rotation, 0);
}
This code is attached to the projectile:
public float speed = 10;
PhotonView pv;
private void Awake()
{
pv = transform.GetComponent<PhotonView>();
}
private void FixedUpdate()
{
transform.Translate(transform.forward * speed * Time.fixedDeltaTime);
}
I guess that I should make have something as instatntiation parameter but idk what.
A simple approach would be to add a shotOwner property to each of your projectiles. Every time a projectile is fired, update shotOwner to point to the player object that fired the shot. (This will also let you implement "Player_X killed Player_Y" functionality, among other things.)

Call function from another script

I'm programming a simple game (the first one I do on my own) in which basically there are two scoring goals, and when a player scores, I want to reset the position for all players to some coordinates.
I have a script attached to the goals, which detects collision with the ball, as follows:
Goal.js
#pragma strict
function OnTriggerEnter2D (hitInfo : Collider2D) {
if (hitInfo.name == "Ball")
{
var wallName = transform.name;
GameManager.Score (wallName);
hitInfo.gameObject.SendMessage ("ResetBall");
//Here I need to call the ResetPlayer function
PlayerControlHS.ResetPlayer();
}
}
The following script is attached to the players
PlayerControlHS.js
#pragma strict
var resetPosX : float;
var resetPosY : float;
//keys
var moveUp : KeyCode;
var moveLeft : KeyCode;
var moveRight : KeyCode;
var speed : int = 4;
function Update () {
if (Input.GetKey(moveUp)) {
rigidbody2D.velocity.y = speed;
}
if (Input.GetKey(moveLeft)) {
rigidbody2D.velocity.x = -speed;
}
else if (Input.GetKey(moveRight)) {
rigidbody2D.velocity.x = speed;
}
else {
rigidbody2D.velocity.x = 0;
}
}
function ResetPlayer () {
Debug.Log("I'm being called");
}
Both the goals and the players have a RigidBody 2D and a collider of some kind, as well as the ball.
I've gotten to get the function called as it is right now, but if I try to modify the position coordinates of a player, I enter a loop of death errors that when I fix one, I get another one.
That happens when I put this code in ResetPlayer():
rigidbody2D.position.x = resetPosX;
rigidbody2D.position.y = resetPosY;
Mostly, the errors are because I need an object of type PlayerControlHS to access those fields. I've tried adding a variable of that type (and referencing it to each player) but it doesn't work because it tells me I need an object to access that variable... I don't know how to initialize it if I make it static.
How could I get it working?
EDIT: I'm thinking the best approach would be sending a message just like the ResetBall one, but it doesn't work (I think because the function is called from ball, object of another type and it can't find the function). This way, the function ResetPlayer could stop being static. But I'm not sure if this is right, since I can't get it without compile errors.
EDIT2: It worked, even though I had to put it one liner
hitInfo.gameObject.GetComponent(PlayerControlHS).ResetPlayer();
Because Unity was telling me that I needed to put a semicolon here (I don't understand :S):
PlayerControlHS playerScript ; = hitInfo.gameObject.getComponent(PlayerControlHS);
But I still can't get to modify the variables of the position...
I have tried fixing it but I get an error saying that "I need an instance of type UnityEngine.Component to access non static member 'rigidBody2D' in a variable declaration I made
static var test : PlayerControlHS = rigidbody2D.GetComponent(PlayerControlHS);
And the code I'm trying in ResetPlayer:
test.GetComponent(PlayerControlHS).rigidbody2D.position.x = test.GetComponent(PlayerControlHS).resetPosX;
test.GetComponent(PlayerControlHS).rigidbody2D.position.y = test.GetComponent(PlayerControlHS).resetPosY;
Try changing this line:
PlayerControlHS.ResetPlayer();
To this:
PlayerControlHS playerScript = hitInfo.gameObject.getComponent(PlayerControlHS);
playerScript.ResetPlayer();
That is how you call a function from another script.
EDIT 1:
Sorry I got mixed up with C# even though you are using javascript, I figured out why you got that error. There's a slight difference in variable declaration.
Change the above code to this:
var playerScript:PlayerControlHS = hitInfo.gameObject.GetComponent(PlayerControlHS);
playerScript.ResetPlayer();
As for resetting the player's position, the script is inside the player game object is it not? Then you can just simplify it like this:
function ResetPlayer () {
rigidbody2D.position.x = resetPosX;
rigidbody2D.position.y = resetPosY;
}
Really sorry for that :(

Detecting if Sprites are in Rect?

i have a tower and a monster. The tower has a SkShapeNode around it, acting as its range. And i want to check if the monster is still inside the range of the tower( i.e inside the skshape node) every frame.
i have this method which i think checks if there is anything still inside the towers' range:
-(void)update
{
[self.currentScene.physicsWorld enumerateBodiesInRect:self.towerRangeNode.frame usingBlock:^(SKPhysicsBody *body, BOOL *stop) {
if (body == nil) {
[self lostSightOfMonster];
}
}];
}
however, the [self lostSightOfMonster] method never runs.
for additional understanding, i call this method in the update method of the scene:
[self enumerateChildNodesWithName:#"Tower" usingBlock:^(SKNode *node, BOOL *stop) {
Tower *tower = (Tower *) node;
[tower update];
if (tower.hasChosenEnemy) {
[tower updateRotation];
}
}];
}
i suspect its something to do with the enumerating bodies in rect method, however i am not sure.
thanks in advance
I would suggest a different approach. Rather than checking if it is in contact with the sprite I would check its distance to the origin of the tower using Pythagorean theorem. I think the code would be more simple and there would be the added bonus of not having the range sprite to be visible at all times.
here is some concept code to show what I mean:
double distance;
distance = pow(enemySprite.position.x-towerSprite.position.x, 2);
distance += pow(enemySprite.position.y-towerSprite.position.y, 2);
distance = sqrt(distance);
if (distance < towerRange) {
//shoot at ememy
}
You could hypothetically put this in a for loop to check for multiple enemies as well.
Use this code to check for frame intersection of 2 nodes:
if(CGRectIntersectsRect(towerNode.frame, enemyNode.frame))
{
// do your thing
}
If you have more than one tower and one enemy you would use this code:
for(SKNode *towerNode in towerNodeArray)
{
for(SKNode *enemyNode in enemyNodeArray)
{
if(CGRectIntersectsRect(towerNode.frame, enemyNode.frame))
{
// do your thing
}
}
}
The above assumes you are using the physics body of the tower to check for range. Alternately you can also use some simple x and y coordinate checking like this:
if(((towerNode.position.y <= enemyNode.position.y+100) && (towerNode.position.y >= enemyNode.position.y-100)) &&
((towerNode.position.x <= enemyNode.position.x+100) && (towerNode.position.x > enemyNode.position.x+100)))
{
// do your thing
}

b2contactlistener issues

I am making an iphone app with cocos2d and box2d and I am having trouble, I followed this tutorial on how to use the b2ContactListener because I need it very badly for my app... http://www.raywenderlich.com/505/how-to-create-a-simple-breakout-game-with-box2d-and-cocos2d-tutorial-part-22 I am trying to detect when two objects collide
It has been one of the hardest things for me to figure out... not nessecarally what he is doing in the game but how to use the b2contactlistener... However, I want to use what he did in that tutorial within my code
this is how I updated my tick method so it would check for collisions every time
-(void) update: (ccTime) dt
{
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if ((contact.fixtureA == _bottomFixture && contact.fixtureB == _ballFixture) ||
(contact.fixtureA == _ballFixture && contact.fixtureB == _bottomFixture)) {
NSLog(#"Ball hit bottom!");
}
}
}
However, I don't know how to change it to work with my two b2Bodies, eggBody and locations.platform...
I believe it is these few lines I must change...
if ((contact.fixtureA == _bottomFixture && contact.fixtureB == _ballFixture) ||
(contact.fixtureA == _ballFixture && contact.fixtureB == _bottomFixture)) {
NSLog(#"Ball hit bottom!");
}
where it says _bottomFixture and _ballFixture I thought I would plug in my b2Bodies... but now I feel like _bottomFixture isn't even a b2body
:) any help would be great sorry if I confused anybody just post any questions and I will clarify thankyou
_bottomFixture is a b2Fixture object.
It is created when you create the fixturedef of the body by
bottomBody->CreateFixture(&_fixturedef);
the above line returns a b2Fixture.
so you can write
b2Fixture *_bottomFixture = bottomBody->CreateFixture(&_fixturedef);
normally we don't track this b2Fixture object. But in collision detection, we need to use it.