I want to make a Kinect program thanks to, when your left hand X position cross your right shoulder X position, it plays the following slide on PowerPoint. I've already done the program part which draws the skeleton stream, and it's work correctly. For the second part, I've tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
bool check = false;
if (leftHand.Position.X == shoulderRight.Position.X && check == false)
{
check = true;
System.Windows.Forms.SendKeys.Send("{RIGHT}");
}
if (leftHand.Position.X == spine.Position.X && check == true)
{
check = false
}
}
Can anyone explain me what is the problem in my code ?
Thanks,
Edit :
I've also tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
double lefthandposition = (int)leftHand.Position.X;
double shoulderrightposition = (int)shoulderRight.Position.X;
double spineposition = (int)spine.Position.X;
bool turn = false;
double right = lefthandposition - shoulderrightposition;
bool finish = false;
double ok = lefthandposition - spineposition;
if (right < 0)
{
turn = true;
}
if (ok > 0)
{
finish = true;
}
bool check = false;
if (turn == true && check == false && finish == false)
{
System.Windows.Forms.SendKeys.Send("{RIGHT}");
check = true;
turn = false;
}
if (finish == true && check == true && turn == false)
{
check = false;
finish = false;
}
}
But it doesn't work too :/
The trouble you are running into is that you using == as a check. You will rarely, if ever, run into a situation where two joints are exactly the same value. You need to be using >= or <= for your checks, depending on your needs.
For example, check the JointType.LeftHand >= JointType.RightShoulder, and that JointType.LeftHand <= JointType.Spine, for your position checks.
Another solution could be to use an existing gesture library to accomplish what you want. Here are two of them:
http://kinecttoolbox.codeplex.com/
https://github.com/EvilClosetMonkey/Fizbin.Kinect.Gestures
The Fizbin library's GitHub page explains how to set up and execute on existing gestures: Executing on Gestures. Included in the existing gesture set is a "Swipe Right" and a "Swipe Left" gesture, which execute similar to what you are wanting to do.
The GitHub pages goes into more detail, but a quick rundown would start with setting up the gesture library and a callback:
gestureController = new GestureController();
gestureController.GestureRecognized += OnGestureRecognized;
You'd then initialize the gesture(s) you want to use:
IRelativeGestureSegment[] swipeleftSegments = new IRelativeGestureSegment[3];
swipeleftSegments[0] = new SwipeLeftSegment1();
swipeleftSegments[1] = new SwipeLeftSegment2();
swipeleftSegments[2] = new SwipeLeftSegment3();
gestureController.AddGesture("SwipeLeft", swipeleftSegments);
You can modify the existing gesture components or write your own. The several examples will demonstrate how you can compare joint positions. For example, the first segment in the "SwipeLeft" gesture follows:
public class SwipeLeftSegment1 : IRelativeGestureSegment
{
/// <summary>
/// Checks the gesture.
/// </summary>
/// <param name="skeleton">The skeleton.</param>
/// <returns>GesturePartResult based on if the gesture part has been completed</returns>
public GesturePartResult CheckGesture(Skeleton skeleton)
{
// right hand in front of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.Z < skeleton.Joints[JointType.ElbowRight].Position.Z && skeleton.Joints[JointType.HandLeft].Position.Y < skeleton.Joints[JointType.ShoulderCenter].Position.Y)
{
// right hand below shoulder height but above hip height
if (skeleton.Joints[JointType.HandRight].Position.Y < skeleton.Joints[JointType.Head].Position.Y && skeleton.Joints[JointType.HandRight].Position.Y > skeleton.Joints[JointType.HipCenter].Position.Y)
{
// right hand right of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.X > skeleton.Joints[JointType.ShoulderRight].Position.X)
{
return GesturePartResult.Succeed;
}
return GesturePartResult.Pausing;
}
return GesturePartResult.Fail;
}
return GesturePartResult.Fail;
}
}
Notice it goes through a series of joint checks and returns one of three results:
Succeed: The gesture has completed in full (fired when all the 'if' statements succeed)
Pausing: The gesture is partially complete (fired when you want to indicate the gesture is "in motion" but not complete)
Fail: The gesture is not being executed at all
When you have the gesture you want initialized you just need to send the 'skeleton' data to the gesture library:
private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame == null)
return;
// resize the skeletons array if needed
if (skeletons.Length != frame.SkeletonArrayLength)
skeletons = new Skeleton[frame.SkeletonArrayLength];
// get the skeleton data
frame.CopySkeletonDataTo(skeletons);
foreach (var skeleton in skeletons)
{
// skip the skeleton if it is not being tracked
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
// update the gesture controller
gestureController.UpdateAllGestures(skeleton);
}
}
}
Finally, execute on the gesture:
private void OnGestureRecognized(object sender, GestureEventArgs e)
{
switch (e.GestureName)
{
case "SwipeLeft":
// do what you want to do
break;
default:
break;
}
}
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'm making a board game in Unity with multiple branching paths where the players can decide which one to follow. (Think the Mario Part game board) But the player input on which path to follow isn't working.
So I have a script that has the tokens follow a set path and (Linked List for the path) with a for loop to have the tokens move their allocated amount. Within the loop, I have an If statement that checks how many paths the tile has and if there are more than one if runs a separate script that pauses the game and offers a menu prompt for the players to pick one path or the other.
I've tried tossing in a few contitions for continuing the game within the loop but they either ignore the player input, are an input behind or just break the code.
`for (int i = 0; i < spacesToMove; i++)
{
if (final_Waypoint == null)
{
final_Waypoint = Starting_Waypoint;
}
else
{
if (final_Waypoint.Next_Waypoint == null || final_Waypoint.Next_Waypoint.Length == 0)
{
//we are overshooting the final waypoint, so just return some nulls in the array
//just break and we'll return the array, which is going to have nulls at the end.
Debug.Log(Current_Waypoint);
break;
}
else if (final_Waypoint.Next_Waypoint.Length > 1) // && if playerID == 0 so it only appears for players.
{
menu.Pause_for_Choice();
//if (menu.ButtonPress == true)
final_Waypoint = final_Waypoint.Next_Waypoint[menu.choice_int];
//***There's a bug here. It calls menu as per normal, and the game pauses.
//But when I click 'no', choice_int isn't updated first: this function finishes first,
//so this function gets old choice_int. THEN the button function executes.
Debug.Log("test 3 " + menu.choice_int);
}
else
{
final_Waypoint = final_Waypoint.Next_Waypoint[0];
}
}
listOfWaypoints[i] = final_Waypoint;
Debug.Log("i:" + i);
}
return listOfWaypoints;
}`
`{
public GameObject choice_Menu;
public bool isPaused = true;
public int choice_int=0;
public int choice_placeholder = 0;
public void Pause_for_Choice()
{
isPaused = true;
choice_Menu.SetActive(true);
Time.timeScale = 0;
}
public void Yes()
{
choice_placeholder = 0;
UnPause_Game();
}
public void No()
{
choice_placeholder = 1;
UnPause_Game();
}
public void UnPause_Game()
{
isPaused = false;
choice_Menu.SetActive(false);
Time.timeScale = 1;
}
}`
Hi,
Im working on Visual Studio Winforms and I'm trying to build tic-tac-toe.
I got stuck in the Check if player win method.
I have tried to do that in activated. little example:
private void StartForm_Activated(object sender, EventArgs e)
{
if ((_pcb1.Image == imagecircle) && (_pcb2.Image == imagecircle) && (_pcb3.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb4.Image == imagecircle) && (_pcb5.Image == imagecircle) && (_pcb6.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb7.Image == imagecircle) && (_pcb8.Image == imagecircle) && (_pcb9.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
}
(I know that there are more situations to win).
It's never get into the method, I trying to find a method that active always when the form is open. please help :)
You should check player's victory after each move of that player. I assume, that your players make their moves by clicking on "Make a Move" button or clicking on the game field. Also I assume, that you have Click event of your button or game field. So you should paste your check code in Click event of your button or game field.
Here is some code that will extend to whatever game size:
public class Level
{
private readonly Team[,] _game;
public Level(int extent)
{
_game = new Team[extent, extent];
}
public bool HasWon(Team team)
{
var yMax = GetYMax();
var xMax = GetXMax();
var won = false;
// check horizontally
for (var y = 0; y < yMax; y++)
{
won = false;
for (var x = 0; x < xMax; x++)
won |= _game[y, x] == team;
if (won) return true;
}
// TODO check vertically
// TODO check diagonally
return won;
}
public void SetTile(Team team, int x, int y)
{
var xMax = GetXMax();
var yMax = GetYMax();
if ((x < 0) || (x > xMax))
throw new ArgumentOutOfRangeException("x");
if ((y < 0) || (y > yMax))
throw new ArgumentOutOfRangeException("y");
_game[y, x] = team;
}
private int GetXMax()
{
var xMax = _game.GetUpperBound(1);
return xMax;
}
private int GetYMax()
{
var yMax = _game.GetUpperBound(0);
return yMax;
}
}
public enum Team
{
Red,
Blue
}
Things for you to do:
implement logic for checking if a team has won vertically or diagonally
implement your game using this class, drawing pictures according the array _game (make it available publicly)
study the | OR operator to understand how it's used in here : https://msdn.microsoft.com/en-us/library/6373h346.aspx
further debug the code (I haven't :)
If you want to find some method that is constantly called, so as to check whether the players have won, you can just create a Timer that runs every 1 millisecond. Then the event handler for Timer.Tick would be such a method.
However, you shouldn't find such a method to check for winning/losing. It's a waste of resources to check for that every 1 millisecond.
Think, what action can affect the result of a game of tic tac toe? It's of course when either player places something (X or O) on the board! That is when you need to check whether someone has won. Also, if the thing placed is a X, you don't need to check whether the player who is playing O has won, because that's simply impossible!
Also, checking whether the image in a picture box is equal to the X or O image is really "non abstract" code. Try to put these things into a model by abstraction.
I am extremely new to programming, and I have started off with C#. I am now trying to make my first game, I decided on snake. So far I have been trying to research this question, but all of the answers I see are ones that pertain to people who are using a different method of moving their snake around.
My program uses two doubles (left and top) in order to store where the snake is on the Canvas. My program also uses two doubles for the "food" in the game, called randomFoodSpawnLeft and randomFoodSpawnTop.
My question is this. How does one detect collision between two rectangular objects with just a left and top value? I am rather confused.
snakeWindow is the Window, snakeHead is the rectangle that represents a snake, left is the left value of the snake, top is the top value of the snake.
void timer_Tick(object sender, EventArgs e)
{
double left = Canvas.GetLeft(snakeHead);
double top = Canvas.GetTop(snakeHead);
if (keyUp)
{
top -= 3;
}
else if (keyDown)
{
top += 3;
}
else if (keyLeft)
{
left -= 3;
}
else if (keyRight)
{
left += 3;
}
// These statements see if you have hit the border of the window, default is 1024x765
if (left < 0)
{
left = 0;
gameOver = true;
}
if (top < 0)
{
top = 0;
gameOver = true;
}
if (left > snakeWindow.Width)
{
left = 0;
gameOver = true;
}
if (top > snakeWindow.Height)
{
top = 0;
gameOver = true;
}
// Statements that detect hit collision between the snakeHead and food
//
if (foodEaten == true)
{
spawnFood();
textBlockCurrentScore.Text += 1;
}
// If gameOver were to be true, then the game would have to end. In order to accomplish this I display to the user that the game is over
// and the snakeHead is disabled, and should restart.
if (gameOver == true)
{
keyRight = false;
keyLeft = false;
keyUp = false;
keyDown = false;
top = 0;
left = 0;
textBlockGameOver.Text = "GAME OVER!";
snakeCanvas.Background = Brushes.Blue;
}
Canvas.SetLeft(snakeHead, left);
Canvas.SetTop(snakeHead, top);
}
You can use System.Windows.Rect.IntersectsWith. Try it like this:
Rect rect1 = new Rect(left1, top1, widht1, height1);
Rect rect2 = new Rect(left2, top2, widht2, height2);
bool intersects = rect1.IntersectsWith(rect2);
Of course you will have to check the snake's head against all it's parts.
This my code for clapping hand gesture ,i use the result to set a robotic arm end effector to a 3d location for every clap)
i want the event handler to trigger just once for every clap gesture,
and reset for another clap gesture. but when i clap and my hands are close together, my event handler keeps firing!! please how do i correct this issue. could i use a reset method or something
[hand clap code]
float previousDistance = 0.0f;
private void MatchClappingGesture(Skeleton skeleton)
{
if (skeleton == null)
{
return;
}
if (skeleton.Joints[JointType.WristRight].TrackingState == JointTrackingState.Tracked && skeleton.Joints[JointType.WristLeft].TrackingState == JointTrackingState.Tracked)
{
float currentDistance = GetJointDistance(skeleton.Joints[JointType.WristRight], skeleton.Joints[JointType.WristLeft]);
{
if (currentDistance < 0.1f && previousDistance > 0.1f )
{
if (this.GestureRecognized != null)
{
this.GestureRecognized(this, new GestureEventArgs(RecognitionResult.Success));
previousDate = DateTime.Now;
}
}
previousDistance = currentDistance;
}
}
}
this is where i call the event handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
kinect = KinectSensor.KinectSensors[0];
kinect.Start();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show("Could not find Kinect Camera: " + ex.Message);
}
kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
kinect.ColorStream.Enable(ColorImageFormat.RgbResolution1280x960Fps12);
kinect.SkeletonStream.Enable(new TransformSmoothParameters()
{
Correction = 0.5f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.05f,
Prediction = 0.5f,
Smoothing = 0.5f
});
kinect.AllFramesReady += Kinect_SkeletonAllFramesReady;
recognitionEngine = new GestureRecognitionEngine();
armEngine = new ArmControllerEngine();
recognitionEngine.GestureRecognized += new EventHandler<GestureEventArgs>(recognitionEngine_GestureRecognized);
}
event handler fires here
void recognitionEngine_GestureRecognized(object sender,
GestureEventArgs e)
{
//armEngine.setArm(raMove,port,servoId);
MessageBox.Show("HI");
}
the message box prints multiple time instead of just once!!please help
You must bear in mind that Kinect's measurements have a degree of inaccuracy. Also, in certain cases (like when the hands are together!!) that inaccuracy increases greatly, and the detected joint positions start jumping all over the place. Try it with the SDK's provided skeleton viewer and you'll see. This is often mitigated by using smoothing algorithms, but in your case that might not be the most adequate solution. Try increasing the distance you are using to detect the gesture, give it some 20cm or so (btw, what does your GetJointDistance returns? Meters? Then give it 0.2)
void wait(int a)
{
for (int i = 0; i < a; i++) ;
}
int count = 0;
void recognitionEngine_GestureRecognized(object sender, GestureEventArgs e)
{
wait(3);
clapShow();
}
//clap method
void clapShow()
{
count += 1;
if (count == 1)
{
MessageBox.Show("Gesture Capture Within >> " + time.Millisecond.ToString() + " milli Seconds");
}
count = 0 ;
}
}
I called the message box as a method every 3millsecs wait(3) so that slows down the the event handler.
Then set the count to "1" before a gesture then back to "0"after every clap gesture and it works pretty well!!
Note!.... The wait(X) method i created a simple loop that counts down to the value X. It can be any value based on the level of sensitivity level one desires. Thanks jose!!
i hope this helps someone..