I have make a game (pong) using a kinect, I can recognize one skeleton and I can make gestures to control the left stick, but when I try to play with two players donĀ“t recognize the skeleton of other player. This is what I do so far:
private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
Skeleton[] skeletons = new Skeleton[0];
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
}
if (skeletons.Length != 0)
{
foreach (Skeleton skel in skeletons)
{
if (skel.TrackingState == SkeletonTrackingState.Tracked)
{
this.tracked(skel);
this.trackedLeft(skel);
}
}
}
}
}
public void tracked(Skeleton skeleton)
{
Joint jHandRight = skeleton.Joints[JointType.HandRight];
Joint jHipCenter = skeleton.Joints[JointType.HipCenter];
if ((jHipCenter.Position.Z - jHandRight.Position.Z) > 0.2)
{
//Consider hand raised in front of them
//System.Diagnostics.Debug.WriteLine("Hand: Raised");
//MessageBox.Show("POR FAVORRRRRRRR");
//movement[0] = false;
movement[0] = true;
movement[1] = false;
}
else
{
//Hand is lowered by the users side
//System.Diagnostics.Debug.WriteLine("Hand: Lowered");
//MessageBox.Show("A SERRRRIIIIIOOOOOOOOOOOOOO");
//movement[1] = false;
movement[1] = true;
movement[0] = false;
}
}
Someone could help me.
You need a way to distinguish between skeleton one and two. See Kinect user Detection for how to do this. You can then pass the skeleton for player one and two to your two different methods. I use the player ID because if a skeleton is lost for a frame or two, their ID remains the same
int id1 = 0, id2 = 0;
...
if (skeletons.Length != 0)
{
foreach (Skeleton skel in skeletons)
{
if (skel.TrackingState == SkeletonTrackingState.Tracked)
{
if (skel.TrackingID == id1)
this.tracked(skel);
else if (skel.TrackingID == id2)
this.trackedLeft(skel);
else
{
if (id1 != 0 && id2 == 0)
id2 = skel.TrackingID;
else if (id2 != 0 && id1 == 0)
id1 = skel.TrackingID;
}
}
}
}
Related
I'm developing a Train Valley game, just like 2D. The construction of the railway is different. I have a grid and I can take a rail and put it somewhere in the grid and so the railway is built. The main problem I am facing is that I do not know how to create the way for the train to follow .... each sine has a point, this point I add in a Vector3 type list, but if I jump over a cell and put there sine , then go back to the skipped cell and put the rail there, then the list will no longer be sorted.
I'm attaching code, but it's a lot. In general, if anyone has any idea how to build this path, the train will run correctly by all means.
void Start()
{
foreach (TrainCell cell in Grid)
cell.gameObject.AddComponent<TrainCellMouseEvent>().MouseEvent += OnCellClickEvent;
MouseEventProccessor.Instance.captureMouseMouveEvents = true;
StartCoroutine(SpawnStations());
}
private void OnCellClickEvent(TrainCell target, MouseEventType type)
{
if (type == MouseEventType.CLICK)
{
if (canDestroy)
{
if ((int)target.CurrentChildIndex != 0)
{
target.CurrentChild.GetComponent<PolygonCollider2D>().enabled = false;
target.setCurrentChildIndex(0);
Instantiate(BoomFX, target.transform.position, Quaternion.identity);
target.used = false;
WayPoints.Remove(target.transform.position);
if (BuildDone != null)
BuildDone(price, false);
}
foreach (TrainCell cell in Grid)
{
if (!cell.underBuilding)
{
if (cell.CurrentChildIndex == 0 && cell.used)
cell.used = false;
}
}
return;
}
if (rail.SelectedRail == null || target.used || outOfGridBounds)
return;
int railIndex = (int)rail.SelectedRail.GetComponent<ObjectSequence>().CurrentChildIndex;
target.setCurrentChildIndex(railIndex + 1);
target.CurrentChild.GetComponent<PolygonCollider2D>().enabled = true;
MouseEventProccessor.Instance.captureMouseMouveEvents = true;
SpriteRenderer render = target.CurrentChild.GetComponent<SpriteRenderer>();
render.color = Vector4.one;
target.used = true;
if (BuildDone != null)
BuildDone(price, true);
if (target.CurrentChild.transform.childCount == 0)
WayPoints.Add(target.transform.position);
else
{
for (int i = 0; i < target.CurrentChild.transform.childCount; i++)
WayPoints.Add(target.CurrentChild.transform.GetChild(i).transform.position);
}
}
else if (type == MouseEventType.OVER)
{
if (mainLevel.isHammer)
{
if (target.CurrentChildIndex != 0)
target.CurrentChild.GetComponent<SpriteRenderer>().color = Color.red;
return;
}
if (rail.SelectedRail == null || target.used)
return;
foreach (TrainCell cell in Grid)
{
if (cell.CurrentChildIndex != 0)
{
if (cell != target)
{
if (cell.CurrentChild.GetComponent<SpriteRenderer>().color != Color.white && !cell.used && !cell.underBuilding)
{
if (cell.GetComponentInChildren<ObjectSequenceNumberDisplay>() != null)
Destroy(GetComponentInChildren<ObjectSequenceNumberDisplay>().gameObject);
cell.setCurrentChildIndex(0);
}
}
}
}
int railIndex = (int)rail.SelectedRail.GetComponent<ObjectSequence>().CurrentChildIndex;
target.setCurrentChildIndex(railIndex + 1);
RenderColor(target);
}
else if (type == MouseEventType.EXIT)
{
if (target.CurrentChildIndex != 0)
target.CurrentChild.GetComponent<SpriteRenderer>().color = Color.white;
if (shapePrice != null)
Destroy(shapePrice.gameObject);
if (target.used)
return;
target.setCurrentChildIndex(0);
}
}
As far as I suppose based on your code I'll try to answer your question based on the following statements:
You have a station where you generate the train
You define a direction for the train to follow from the station (left, right, up, down) depending on the railway design
Having that statements I propose the following solution:
Create a method that takes the station point as the origin and the starting direction from that point. Having that you start following the railway, first on that direction and after that you search in 4 directions for more rails, adding all of them to the Vector3 array. This way you will have the array sorted.
Example:
private void SortedRailway(Vector2 origin, Vector2? direction = null, Vector2? lastDirection = null){
if(direction.HasValue){
if(origin + direction is TrainCell){
WayPoints.add(origin + direction);
SortedRailway(origin + direction, null, direction);
}
//(else will be used if direction (just used for the initial one) is wrong, so error there)
}else{
if(origin + Vector2.up is TrainCell && Vector2.up != lastDirection){
WayPoints.add(origin + Vector2.up);
SortedRailway(origin + Vector2.up, null, Vector2.down); //lastDirection is always the opposite to the matching one
}
//... (Repeat for all 4 directions. If none fits, then we asume is the end of the railway)
}
}
Hope this helps you!
I am trying to draw a line from camera to a instantiated object.I am using the scene UnityARHitTest Example.When I touch on a vertical plane the object gets instantiated and i want to draw a line from camera to the object.When I move my device the line should show from the centre of my camera.For some reason line renderer is not showing when I call it in the Late update.
LineRenderer lins;
public GameObject Lineprefab;
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
if (hitResults.Count > 0 && check==true)
{
foreach (var hitResult in hitResults)
{
Debug.Log ("Got hit!");
if (Select == 0)
{
Debug.Log("hit-zero!");
Instantiate(Instaobj[0], ForSelect);
check = false;
}
if (Select == 1)
{
Debug.Log("hit-one!");
Instantiate(Instaobj[1], ForSelect);
check = false;
}
if (Select == 2)
{
Debug.Log("hit-two!");
Instantiate(Instaobj[2], ForSelect);
check = false;
}
if (Select == 3)
{
Debug.Log("hit-three!");
Instantiate(Instaobj[3], ForSelect);
check = false;
}
if (Select == 4)
{
Debug.Log("hit-four!");
Instantiate(Instaobj[4], ForSelect);
check = false;
}
if (Select == 5)
{
Debug.Log("hit-five!");
Instantiate(Instaobj[5], ForSelect);
check = false;
}
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
obj.StopPlaneTracking();
if (GameObject.Find("debugPlanePrefab(Clone)"))
GameObject.Find("debugPlanePrefab(Clone)").SetActive(false);
else
Debug.Log("no prefab");
//lins.SetPosition(0, m_HitTransform.position);
//lins.SetPosition(1, obj.m_camera.transform.position);
return true;
}
}
return false;
}
When I use lins.setposition() in the above method(which is commented) a line is shown in the output.When I use lins.setposition() in the below LateUpdate() the output is not shown nothing comes.
private void Start()
{
spawngenerator();
}
void spawngenerator()
{
GameObject newline = Instantiate(Lineprefab);
lins = newline.GetComponent<LineRenderer>();
//lins.SetPosition(0, m_HitTransform.position);
//lins.SetPosition(1, obj.m_camera.transform.position);
}
private void LateUpdate()
{
lins.SetPosition(0,obj.m_camera.transform.position );
lins.SetPosition(1,m_HitTransform.position );
}
I want to detect hand state if it gripped or released using Kinect SDK v1.7 implemented with C#, but I'm tired from this an exception:
Exception thrown: 'System.InvalidOperationException' in
Microsoft.Kinect.Toolkit.Interaction.dll
The code:
private void InteractionStreamOnInteractionFrameReady(object sender,InteractionFrameReadyEventArgs e)
{
using (InteractionFrame frame = e.OpenInteractionFrame())
{
if (frame != null)
{
if (this.userInfos == null)
{
this.userInfos = new UserInfo[InteractionFrame.UserInfoArrayLength];
}
frame.CopyInteractionDataTo(this.userInfos);
}
else
{ return;}
}
foreach (UserInfo userInfo in this.userInfos)
{
foreach (InteractionHandPointer handPointer in userInfo.HandPointers)
{
string action = null;
switch (handPointer.HandEventType)
{
case InteractionHandEventType.Grip:
action = "gripped";
break;
case InteractionHandEventType.GripRelease:
action = "released";
break;
}
if (action != null)
{
string handSide = "unknown";
switch (handPointer.HandType)
{
case InteractionHandType.Left:
handSide = "left";
break;
case InteractionHandType.Right:
handSide = "right";
break;
}
if (handSide == "left")
{
if (action == "released")
{
// left hand released code here
//MessageBox.Show("left hand released");
System.Console.WriteLine("left hand released");
}
else
{
// left hand gripped code here
System.Console.WriteLine("left hand gripped");
}
}
else
{
if (action == "released")
{
// right hand released code here
System.Console.WriteLine("right hand released");
}
else
{
// right hand gripped code here
System.Console.WriteLine("right hand gripped");
}
}
}
}
}
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// Create the drawing group we'll use for drawing
this.drawingGroup = new DrawingGroup();
// Create an image source that we can use in our image control
this.imageSource = new DrawingImage(this.drawingGroup);
// Display the drawing using our image control
Image.Source = this.imageSource;
sensor = KinectSensor.KinectSensors.FirstOrDefault();
if (null != this.sensor )
{
System.Console.WriteLine("Start streaming");
skeletons = new
Skeleton[sensor.SkeletonStream.FrameSkeletonArrayLength];
userInfos = new
UserInfo[InteractionFrame.UserInfoArrayLength];
this.sensor.SkeletonStream.Enable();
this.interactionStream = new InteractionStream(this.sensor,
new
DummyInteractionClient());
this.interactionStream.InteractionFrameReady +=
InteractionStreamOnInteractionFrameReady;
sensor.SkeletonFrameReady += SensorSkeletonFrameReady;
// Start the sensor !
try
{
this.sensor.Start();
}
catch (IOException)
{
//////// this.sensor = null;
}
}
if (null == this.sensor)
{
System.Console.WriteLine("NoKinectReady");
}
}
The swipe gestures Left,Right, Up and Down are not optimized. If a task has to be performed with an upward swipe, it would get confused with a left swipe and still perform it.Please suggest me the parameters to be optimized for differentiating swipes.Or commands for perfect swipe recognition
Also it gets confused with a circle and a swipe.
I have added my code. In one single frame only one gesture should be detected.How do i limit this here.
public MainWindow()
{
InitializeComponent();
this.controller = new Controller();
this.listener = new LeapListener(this);
controller.AddListener(listener);
for (int iCount = 1; iCount < 23; iCount++)
{
images[iCount] = new BitmapImage();
images[iCount].BeginInit();
images[iCount].UriSource = new Uri("Images/" + iCount + ".png", UriKind.Relative);
images[iCount].EndInit();
}
image.Source = images[1];
}
delegate void LeapEventDelegate(string EventName);
public void LeapEventNotification(string EventName)
{
if (this.CheckAccess())
{
switch (EventName)
{
case "onInit":
break;
case "onConnect":
this.connectHandler();
break;
case "onFrame":
this.checkGestures(this.controller.Frame());
break;
}
}
else
{
Dispatcher.Invoke(new LeapEventDelegate(LeapEventNotification
), new object[] { EventName });
}
}
public void connectHandler()
{
controller.EnableGesture(Gesture.GestureType.TYPE_SWIPE);
this.controller.EnableGesture(Gesture.GestureType.TYPE_CIRCLE);
this.controller.EnableGesture(Gesture.GestureType.TYPE_KEY_TAP);
this.controller.EnableGesture(Gesture.GestureType.TYPE_SCREEN_TAP);
// controller.Config.SetFloat("Gesture.Swipe.Speed", 4000.0f);
controller.Config.SetFloat("Gesture.Swipe.MinVelocity", 750f);
controller.Config.SetFloat("Gesture.Swipe.MinLength", 200f);
controller.Config.SetFloat("Gesture.KeyTap.MinDownVelocity", 40.0f);
controller.Config.SetFloat("Gesture.KeyTap.HistorySeconds", .2f);
controller.Config.SetFloat("Gesture.KeyTap.MinDistance", 40.0f);
controller.Config.SetFloat("Gesture.Circle.MinRadius", 15.0f);
controller.Config.SetFloat("Gesture.Circle.MinArc", 15f);
controller.Config.SetFloat("InteractionBox.Width", 1600.0f);
controller.Config.SetFloat("InteractionBox.Height", 1600.0f);
controller.Config.Save();
}
public void checkGestures(Frame frame)
{
GestureList gestures = frame.Gestures();
foreach (Gesture gesture in gestures)
{
// For Image 1
if (image.Source.Equals(images[1]))
{
if (gesture.Type == Gesture.GestureType.TYPE_SWIPE)
{
SwipeGesture swipe = new SwipeGesture(gesture);
if (swipe.State == Gesture.GestureState.STATE_START && swipe.Direction.x > 0 && Math.Abs(swipe.Direction.y) < 5)
{
image.Source = images[2];
// Console.WriteLine("Second");
}
}
}
// For Image 2
else if (image.Source.Equals(images[2]))
{
if (gesture.Type == Gesture.GestureType.TYPE_SWIPE)
{
SwipeGesture swipe = new SwipeGesture(gesture);
if (swipe.State == Gesture.GestureState.STATE_START && swipe.Direction.y > 0)
{
image.Source = images[3];
}
else if (swipe.State == Gesture.GestureState.STATE_START && swipe.Direction.x > 0 && Math.Abs(swipe.Direction.y) < 5)
{
image.Source = images[7];
}
}
if (gesture.Type == Gesture.GestureType.TYPE_KEY_TAP)
{
KeyTapGesture TapGesture = new KeyTapGesture(gesture);
image.Source = images[1];
Console.WriteLine("Circle");
}
}
// For Image 3
else if (image.Source.Equals(images[3]))
{
if (gesture.Type == Gesture.GestureType.TYPE_SWIPE)
{
SwipeGesture swipe = new SwipeGesture(gesture);
if (swipe.State == Gesture.GestureState.STATE_START && swipe.Direction.y < 0)
{
image.Source = images[4];
}
else if (swipe.State == Gesture.GestureState.STATE_START && swipe.Direction.x < 0 && Math.Abs(swipe.Direction.y) < 5)
{
image.Source = images[16];
}
}
if (gesture.Type == Gesture.GestureType.TYPE_KEY_TAP)
{
KeyTapGesture TapGesture = new KeyTapGesture(gesture);
image.Source = images[1];
}
}
}//foreach
}
}
}
The out of the box Gestures were deprecated in 3.x (Orion) as they weren't to reliable.
The best thing to do is to understand the SDK and just create your own gestures, you can go beyond whats already Out of the box and more reliable.
Everything its about 3d positioning so pay attention to your Y,X,Z, use the debuger hands or create your own debug system to see how it behaves.
I am trying to get my Kinect's SkeletonStream to feedback a data that tells me that nobody is detected. I can get feed if my skeleton is detected but I am unable to get any notification if there is nobody there. Is there a way to get the kinect to tell me if no skeletons are picked up?
private void kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame == null)
{
return;
}
frame.GetSkeletons(ref allSkeletons);
if (allSkeletons.All(s => s.TrackingState == SkeletonTrackingState.NotTracked))
return;
foreach (var skeleton in allSkeletons)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
{
continue;
}
if (skeleton.TrackingState == SkeletonTrackingState.NotTracked)
{
}
foreach (Joint joint in skeleton.Joints)
{
if (joint.TrackingState != JointTrackingState.Tracked)
continue;
if (joint.JointType == JointType.HipCenter)
{
hipCenter = joint.Position;
AdvanceFunction();
}
}
sdm.Draw(frame.GetSkeletons(), false);
}
}
}
There is nothing that will simply tell you that no skeletons are currently being tracked. You will need to look through the skeleton frames to determine if there are any users.
Your foreach loop steps through all the skeletons...
foreach (var skeleton in allSkeletons)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
{
continue;
}
....
}
In the first if statement -- if the current skeleton is not being actively tracked then the loop will move on to the next skeleton. You'll want to add a flag if any skeletons have been found. For example, you could do something like...
bool hasActivePlayer = false;
foreach (var skeleton in allSkeletons)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
{
continue;
}
hasActivePlayer = true;
....
}
if (hasActivePlayer == false)
{
// you aren't tracking anyone, deal with it
}
You may also be interested in checking SkeletonTrackingState.PositionOnly. In this case the Kinect knows someone is there, but it is not actively tracking their skeleton. You can update the ckeck in the foreach loop if you want to look for it as well.