joint between ground body & dynamic bodies ( Rope ) - iphone

i am implementing a rope which is hanging from top of the screen , now i have use one dynamic body for creating ropes & i use Revolute joints for joining this all dynamic bodies to create a rope. i successfully created rope , Now when i tried to join my this rope on ground body then it's not getting fixed on it . i guess it's happening because of the dynamic body i used in my rope creation. i am trying to join this with Distance joint , but it's not working, i really stuck with this from couple of weeks .. please help .
ropes:
b2Body* link;
CGSize s = [CCDirector sharedDirector].winSize;
CGFloat linkHeight = 0.24;
CGFloat linkWidth = 0.1;
link = world->CreateBody( &bodyDef );
link->CreateFixture( &fixtureDef );
PhysicsSprite* segmentSprite = [PhysicsSprite spriteWithFile:#"rope_seg_new2.png"];
[self addChild:segmentSprite];
[segmentSprite setPhysicsBody:link];
//set up the common properties of the joint before entering the loop
revoluteJointDef.localAnchorA.Set( 0, linkHeight);
revoluteJointDef.localAnchorB.Set( 0, -linkHeight);
//use same definitions to create multiple bodies
for (int i = 0; i < 10 ; i++) {
newLink = world->CreateBody( &bodyDef );
newLink->CreateFixture( &fixtureDef );
PhysicsSprite* segmentSprite = [PhysicsSprite spriteWithFile:#"rope_seg_new2.png"];
[self addChild:segmentSprite];
[segmentSprite setPhysicsBody:link];
revoluteJointDef.bodyA = link;
revoluteJointDef.bodyB = newLink;
world->CreateJoint( &revoluteJointDef );
link = newLink; //prepare for next iteration
}
joint between GroundBody & Rope:
Distance joint :
b2DistanceJointDef jointDef;
jointDef.Initialize(referencebody, link, referencebody->GetWorldCenter(), link-
>GetWorldCenter());
world->CreateJoint( &jointDef );
here, referencebody : groundbody .. link : rope body

i got answer through Revolute joint ...
b2RevoluteJointDef revoluteJointDef;
revoluteJointDef.bodyA = referenceBody;
revoluteJointDef.bodyB = lastLink;
revoluteJointDef.localAnchorA = startPos;//world coords, because m_groundBody is at (0,0)
revoluteJointDef.localAnchorB.Set(0,0);//center of circle
world->CreateJoint( &revoluteJointDef );

Related

Using a Tilemap composite collider as a trigger, what is the best approach for getting hold of the subcollider that is actually being triggered?

This seems a lot less straight forward than perhaps it should be. I'm using a Tilemap with a composite collider set up as a trigger to draw ladders on the map, and want to lock the player to the central x point of the ladder when they're climbing it. However, I'm hitting a wall in that it seems very difficult to simply get ahold of the individual tile that is being collided with.
The method mentioned elsewhere only works for collisions (ie non-triggers), and even that seems somewhat convoluted for what I would've expected to be a routine task.
Does anyone have any suggestions how to do this? I need to either somehow get the contact point of the trigger (seems to be unsupported) in order to then fire a ray to get the collider, or otherwise add additional gameobjects to the scene that can act as anchors for the ladder, which seems to go against the point of using tilemaps.
Thanks for any help.
There is a way to create a separate collider at the tile location of the tile map to use that location.
It is more accurate than raycast.
Because it is an example script, please refactor and use it
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
[RequireComponent( typeof( Tilemap ) )]
public class TilemapCollider : MonoBehaviour
{
Tilemap t;
void Start()
{
t = GetComponent<Tilemap>();
BoundsInt bounds = t.cellBounds;
TileBase[] allTiles = t.GetTilesBlock( bounds );
var s = t.layoutGrid.cellSize / 2;
var availablePlaces = new List<Vector3>();
for( int n = t.cellBounds.xMin; n < t.cellBounds.xMax; n++ )
{
for( int p = t.cellBounds.yMin; p < t.cellBounds.yMax; p++ )
{
Vector3Int localPlace = ( new Vector3Int( n, p, (int)t.transform.position.y ) );
Vector3 place = t.CellToWorld( localPlace );
var tile = t.GetTile( localPlace );
if( tile )
{
availablePlaces.Add( place );
var c = new GameObject().AddComponent<BoxCollider2D>();
c.isTrigger = true;
c.transform.parent = t.transform;
c.transform.localPosition = t.CellToLocal( localPlace ) + s;
Debug.Log( "x:" + n + " y:" + p + " tile:" + tile.name );
}
}
}
}
}
TilemapCollider.cs
private void OnTriggerEnter2D( Collider2D collision )
{
var tilemap = GameObject.Find( "Grid/Tilemap" ).GetComponent<Tilemap>();
tilemap.SetTile( tilemap.WorldToCell( collision.transform.position ), null );
}
Example of finding a location on OnTriggerEnter2D

I want to get user's height by using kinect V2 and unity3D,this code can't work well what should I do?

Attempting to get the user's height in Unity using the xbox kinect.
Below is my code and I cannot get the height.
This uses the KinectV2 interface.
// get User's height by KinectV2 and unity3D `enter code here`
float GetUserHeightByLeft(long userid)
{`enter code here`
float uheight=0.0f;
int[] joints = new int[9];
int head = (int)KinectInterop.JointType.Head;
joints[0] = head;
joints[1] = (int)KinectInterop.JointType.Neck;
int shoudlderCenter = (int)KinectInterop.JointType.SpineShoulder;
joints[2] = shoudlderCenter;
joints[3] = (int)KinectInterop.JointType.SpineMid;
joints[4] = (int)KinectInterop.JointType.SpineBase;
joints[5] = (int)KinectInterop.JointType.HipLeft;
joints[6] = (int)KinectInterop.JointType.KneeLeft;
joints[7] = (int)KinectInterop.JointType.AnkleLeft;
joints[8] = (int)KinectInterop.JointType.FootLeft;
int trackedcount = 0;
for (int i = 0; i < joints.Length; ++i)
{
if (KinectManager.Instance.IsJointTracked(userid, joints[i]))
{
++trackedcount;
}
}
//if all joints that I need have been tracked ,compute user's height
if (trackedcount == joints.Length)
{
for (int i = 0; i < joints.Length-1;++i)
{
if (KinectManager.Instance.IsJointTracked(userid, joints[i]))
{
Vector3 start= 100*KinectManager.Instance.GetJointKinectPosition(userid,joints[i]);
Vector3 end = 100*KinectManager.Instance.GetJointKinectPosition(userid,joints[i+1]);
uheight += Mathf.Abs(Vector3.Magnitude(end-start));
}
}
//some height kinectV2 can't get so I add it
uheight += 8;
}
return uheight;
}
Given your code I do see a few issues
The summation to get the total height requires all joints to be tracked at that time.
Why do you need all joints to be tracked for the height to be tracked? You should only need the head and the feet
You double check if each joint is tracked
using the left for every foot/knee/hip joint is going to give you math errors. They are offset in one direction (because our feet aren't in the center of our body)
I would track both right and left foot/knee/hip and then find the center of the two on the x axis.
If you're using the magnitude of two vectors and one knee is far in front of your hip it's going to give it an inflated value.
I would only use the y positions of your kinect joints to calculate the height.

Collision group filter not working in Box2D

I'm working on a game in Cocos2d with Box2D. Currently I have a system set up where there are some boundaries. They are for a ball. I want meteors to come in from off the screen and smack the ball.
The boundaries are defined in my init method as follows:
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.type = b2_staticBody;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2PolygonShape groundBox;
// bottom
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
//Collision filter stuff here. Not working.
b2Filter filter;
filter.groupIndex = -2;
groundBody->GetFixtureList()[0].SetFilterData(filter);
My ball is defined as follows:
//Physics object.
b2BodyDef ballBodyDef;
ballBodyDef.position.Set(ball.position.x/PTM_RATIO, ball.position.y/PTM_RATIO);
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.userData = ball;
ballBodyDef.bullet = true;
ballBody = world->CreateBody(&ballBodyDef);
b2CircleShape ballShape;
ballShape.m_radius = 10.0/PTM_RATIO;
b2FixtureDef ballFix;
ballFix.restitution = 1.1f;
ballFix.density = 0.0f;
ballFix.shape = &ballShape;
ballBody->CreateFixture(&ballFix);
And the meteors are made using two methods, the shorter method places the meteors. The longer one actually creates them using the points given from the shorter one:
-(void)createMeteorAtPoint:(CGPoint)point {
//Create particle sprite representation.
CCParticleMeteor *meteor = [[CCParticleMeteor alloc] initWithTotalParticles:200];
meteor.gravity = ccp(-200,0);
meteor.life = 0.5;
meteor.lifeVar = 0.25;
meteor.position = point;
meteor.tag = 2;
meteor.startSize = 5.0;
meteor.startSizeVar = 3.0;
[self addChild:meteor];
//Make meteor physics body.
b2BodyDef meteorBodyDef;
meteorBodyDef.position.Set(point.x/PTM_RATIO, point.y/PTM_RATIO);
meteorBodyDef.type = b2_dynamicBody;
meteorBodyDef.userData = meteor;
b2Body *meteorBody = world->CreateBody(&meteorBodyDef);
meteorBody->SetBullet(true);
b2CircleShape meteorShape;
meteorShape.m_radius = 7.5/PTM_RATIO;
b2FixtureDef meteorFix;
meteorFix.shape = &meteorShape;
meteorFix.density = 1;
//Give it the same negative group index of the boundaries to prevent collision.
//Not working.
meteorFix.filter.groupIndex = -2;
meteorBody->CreateFixture(&meteorFix);
//Give it a motion.
b2Vec2 F;
F.Set(CCRANDOM_0_1()*2, 0);
meteorBody->SetLinearVelocity(F);
}
//Create a bunch of meteors that will sweep from left to right.
-(void)createMeteors {
for (int i = 0; i < 8*40; i += 20) {
[self createMeteorAtPoint:ccp(-40.0f, i + 2)];
}
NSLog(#"HERE");
}
I can see physics objects pile up on the side of the screen because I have debug flags set up. But one: They are not getting past the boundary despite being the same negative group index. And two: the ball decides it doesn't like the right wall, and goes through it.
If you believe I am missing something crucial please tell me.
Only one of the boundary fixtures is being given the group index of -2 (the bottom). You can loop over all fixtures of a body like this:
for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext())
{
//do something with the fixture 'f'
f->SetFilterData(...);
}
I'm not sure why the ball would be ignoring any walls though (unless you are moving it by creating a mouse joint between the ball and the ground body that the walls belong to, and the joint is set to not collide connected bodies... but in that case the ball would ignore all walls, and only while being moved).

Why doesn't gravity scale work in box2d

I am trying to turn off gravity on one of my bodies. I have used the bodyDef.gravityScale = 0.0f but I am having no luck. Here u can look at my code below. Please help.
b2BodyDef monkey1BodyDef;
monkey1BodyDef.position.Set(0, 200/PTM_RATIO);
monkey1BodyDef.type = b2_dynamicBody;
monkey1BodyDef.userData = monkey1;
monkey1BodyDef.bullet = true;
monkey1BodyDef.gravityScale = 0.0f; //Why doesn't this work I get an error that says no member named 'gravityScale' in 'b2BodyDef'
b2Body *monkey1Body = world->CreateBody(&monkey1BodyDef);
I've hit this problem too. After a little digging I've found that the stable Cocos2D builds don't include recent versions of Box2D, so gravityScale is missing from b2BodyDef. That explains the discrepancy with the Box2D documentation.
There are workarounds, but I've opted to update my Box2D to 2.2.1 (currently the latest). In doing that I encountered the following issues (with solutions):
The b2PolygonShape.SetAsEdge method no longer exists. If you're using that to define screen boundaries you'll need to use something like "myPolygonShape.Set(lowerLeftCorner, lowerRightCorner);" for each screen edge. There's an excellent discussion of this at Programmers' Goodies.
b2DebugDraw has been superseded by b2Draw. Just replace any calls to b2DebugDraw with b2Draw and you should be set. For example, if, like me, you're using the Cocos2D Box2D template, you'll need to replace this:
// Debug Draw functions
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
_world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2DebugDraw::e_shapeBit;
flags += b2DebugDraw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
with this:
// Debug Draw functions
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
_world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
flags += b2Draw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
b2Transform has different attribute names for position and rotation. For example, myTransform.position is now myTransform.p (but is still a b2Vec2). myTransform.R, which was defined as b2Mat22, has been replaced with myTransform.q, defined as b2Rot. Again, if you're using the Cocos2D Box2D template, replace the following in GLES-Render.mm:
void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
b2Vec2 p1 = xf.position, p2;
const float32 k_axisScale = 0.4f;
p2 = p1 + k_axisScale * xf.R.col1;
DrawSegment(p1,p2,b2Color(1,0,0));
p2 = p1 + k_axisScale * xf.R.col2;
DrawSegment(p1,p2,b2Color(0,1,0));
}
…with:
void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
b2Vec2 p1 = xf.p, p2;
const float32 k_axisScale = 0.4f;
p2 = p1 + k_axisScale * xf.q.GetXAxis();
DrawSegment(p1,p2,b2Color(1,0,0));
p2 = p1 + k_axisScale * xf.q.GetXAxis();
DrawSegment(p1,p2,b2Color(0,1,0));
}
I hope this helps!
Because no member named 'gravityScale' exists in 'b2BodyDef' :(
documentation is outdated compared with the code
Change gravity definition of world, coz it's world, that have gravity, As:
b2Vec2 gravity = b2Vec2(0.0f, -10.0f);
bool doSleep = false;
world = new b2World(gravity, doSleep);
World is b2World
If body.setGravityScale(0); doesn't work, you can use it with body.setAwake(false); at second line.

Magnitude Position

There is an cube wich scales with the distance.magnitude between the player and the enemy. I want to set this Scaling Cube in the middle between the hero and the enemy. So is it possible to use the mangitude between two objects as a position.
This is my script:
var hero : Transform;
var enemy : Transform;
var magDistance = 0.0;
var setPosition = 0.0;
function Update () {
var heDistance : Vector3 = (hero.position - enemy.position)/2;
magDistance = heDistance.magnitude;
setPosition = heDistance.magnitude/2;
transform.localScale = Vector3(1,1,magDistance);
}
Im using the heDistance.magnitude/2 to get the middle of the distance.
Help is much appreciated. Thanks in advance! :)
I hate to even ask, but can't you just do:
x = (hero.position.x+enemy.position.x)/2
y = (hero.position.y+enemy.position.y)/2
z = (hero.position.z+enemy.position.z)/2
to get the point between the two points? Or, if vector addition works in the usual way:
var cube_pos: Vector3 = (hero.position + enemy.position)/2;