Managing multi-touch events in WPF - c#

I am writing a program using the Surface SDK and .NET 4.0. I have to distinguish between multi-touch events and I'm having trouble distinguishing between gestures.
With two fingers I want to be able to zoom and rotate, but because generally the fingers are not moving in straight lines or perfect circles on the screen, the result is a combination of zoom and rotate. Could someone point out how this problem can be overcome? I am using some thresholds for ignoring small deviations, but these thresholds need to be manually tweaked and I couldn't find a good value for them.
I was thinking I could detect which kind of a gesture it is in the onManipulationStarting method and ignore the rest, but sometimes the gesture can start with just one finger on the screen and I'm identifying the wrong gesture.
I am including some code below:
private void OnManipulationDeltaHandler(object sender, ManipulationDeltaEventArgs mdea)
{
var zoomAmount = Math.Abs(mdea.DeltaManipulation.Scale.Length - Math.Sqrt(2));
// ZOOM ACTION: 2 fingers and scaling bigger than a threshold
if ((TouchesOver.Count() == 2) && (zoomAmount > scaleThreshold))
{
if (ZoomCommand != null)
{
if (Math.Abs(zoomAmount - 0) > 0.1)
{
ZoomCommand.Execute((-zoomAmount).ToString());
}
}
}
else
{
var rotateAmount = -mdea.DeltaManipulation.Rotation;
if ((TouchesOver.Count() == 2))
{
headValue += rotateAmount;
if (HeadRotationCommand != null)
{
HeadRotationCommand.Execute(new Orientation(pitchValue, headValue, rotateAmount));
}
}
}
mdea.Handled = true;
base.OnManipulationDelta(mdea);
}
Can someone help? Thanks!

Related

cannot make a moving picturebox stop at a specific point

i have to create a traffic simulator, i want to move a car (picturebox) while the traffic light is not red and have it stopped when it is red, at the point of the traffic light.
The traffic lights are 3 pannels changing color.
My problem is that my car does not stop when it meets the red traffic light. I have tried the "pictureBox.Location.X" and the "pictureBox.Left" but it just doesn't work, the pictureBox just goes on moving.
I have also tried throwing a messageBox when the car meets the traffic light just to see if the "pictureBox.Location.X" is working but still nothing. Seems like it does not recognize the function.
I have tried to make the traffic light both with panels and pictureboxes but still the same.
Bellow i send you my code so far:
private void timerCar1_Tick(object sender, EventArgs e)
{
//timerCar2.Enabled = true;
if(panelRed.BackColor == Color.Red)
{
car1.Left -= 5;
}
/* ---> */ else if (car1.Location.X == panelGreen.Location.X & panelRed.BackColor == Color.Red)
{
car1.Left -= 0;
}
else if (panelGreen.BackColor == Color.Green)
{
car1.Left -= 20;
}
else if (panelOrange.BackColor == Color.Orange)
{
car1.Left -= 10;
}
}
You use &.
else if (car1.Location.X == panelGreen.Location.X & panelRed.BackColor == Color.Red)
I've heard this can lead to unintended behavior. Did you mean to use the logical "AND" (&&)?
else if (car1.Location.X == panelGreen.Location.X && panelRed.BackColor == Color.Red)
I think that in c# for the logical "AND" ypu can use both & and &&. The problem was fixed by changing the pixel move from += 20 to += 3, so i think my picturebox would not meet the point i set as stopping point, due to the fact that it was moving 20 20 pixels.

how to display certain data to kinect?

I am using kinect v2 c# to detect hand gesture. All my algo used is working right. The problem is that I want kinect to display only hand detected but not all of body and to give all points of the hand in a black background?
This is code that gets the points of contouring hand.
private void HandsController_HandsDetected(object sender, HandCollection e) {
// Display the results!
if (e.HandLeft != null)
{
point = e.HandLeft.ContourDepth;
}
}
for example you can write it like this
// //left hand in front of left Shoulder
if (body.Joints[JointType.HandLeft].Position.Z < body.Joints[JointType.ElbowLeft].Position.Z && body.Joints[JointType.HandRight].Position.Y < body.Joints[JointType.SpineBase].Position.Y)
{
//Action here
}
You can see a sample of how other libraries uses this code here
I also have a tutorial on how to implements swipe gesture using Vitruvius Library do check them out! :D

Mouse drag direction tolerance

I'm working on a 2D game where the player can drag tiles around. It works in a way that the player clicks and hold a tile and depending in which direction the player moves the mouse from then on, the drag direction is decided.
The problem however is that this is overly sensitive. It might often be the case that the player starts dragging and wanted to drag vertically but due to the mouse sensitivity it turns out to drag horizontally (or vice versa).
Does anyone have an idea how to add a tolerance threshold to this dragging behavior? The relevant part in my code looks basically like this:
private void Update()
{
if (_isMouseDown && sourceTile != null)
{
_isDraggingTile = true;
/* Determine drag direction and drag target cell. */
Vector3 dragDistance = Input.mousePosition - _originMousePosition;
dragDistance.Normalize();
if (_dragDirection == DragDirection.None)
{
float f = Vector3.Dot(dragDistance, Vector3.up);
/* Mouse up drag. */
if (f >= 0.5f)
{
_dragDirection = DragDirection.Up;
_dragTargetCell = sourceTile.gridCell.upNeighbor;
}
/* Mouse down drag. */
else if (f <= -0.5f)
{
_dragDirection = DragDirection.Down;
_dragTargetCell = sourceTile.gridCell.downNeighbor;
}
else
{
/* Mouse right drag. */
f = Vector3.Dot(dragDistance, Vector3.right);
if (f >= 0.5f)
{
_dragDirection = DragDirection.Right;
_dragTargetCell = sourceTile.gridCell.rightNeighbor;
}
/* Mouse left drag. */
else if (f < -0.5f)
{
_dragDirection = DragDirection.Left;
_dragTargetCell = sourceTile.gridCell.leftNeighbor;
}
}
}
if (_dragTargetCell != null)
{
// Take care of moving the dragged tile!
}
}
}
Simply delaying the calculation of dragDistance by some frames doesn't turn out to work very well. I think what is needed is a solution to figure out the mouse movement and decide on which axes it moves farthest. Determining the drag direction as above will probably never work out well.
The problem with any collection of information is noise. In your case, the noise is defined by the wrong movement of the user. Nonetheless, it should be possible to minimize the effect of noise by averaging the values.
There are advanced algorithms used in DSP but I guess a basic averaging of the info should do in your case.
What you could try is that instead of moving in Update at once like you do, collect movement over several frames, then average all those frames and see if it goes better:
IEnumerator GetAverageMovement(Action<Vector3> result)
{
int frames = 0;
List<Vector3>list = new List<Vector3>();
while(frames < 30f) // half a second appr
{
list.Add(GetDirection());
frames++;
yield return null;
}
result(AverageAllValues());
}
GetDirection is just returning the delta between current and previous position, AverageAllValues simply adds all values in list and divides by list.Count (aka 30).
This should fix cases when the user move all the way right but a bit up at the end. The last bit should be canceled by the large right movement.
If that is still not enough, then you could add some logic within the method that if a value is too far gone from the average, discard it. I don't think you need this in there.
I think you should create a Queue of positions with limited size right after dragging .
by comparing final value of Queue and first value you can find the direction.
If you want to get better results you can get Variance of positions and get better results.

GestureRecognizer Swipe Gesture

I am trying to detect a horizontal swipe gesture with GestureRecognizer by hooking up to the CrossSliding event.
_gr = new GestureRecognizer
{
GestureSettings = GestureSettings.ManipulationTranslateX |
GestureSettings.ManipulationTranslateY |
GestureSettings.CrossSlide
};
_gr.CrossSliding += OnSwipe;
_gr.ManipulationStarted += OnManipulationStarted;
_gr.ManipulationUpdated += OnManipulationUpdated;
_gr.ManipulationCompleted += OnManipulationCompleted;
_gr.CrossSlideHorizontally = true;
As you can see from the code above, not only swipe should be detected, but also dragging gestures.
My problem is I can't seem to customize the swipe gesture.
I want to customize the minimum speed and distance a user has to drag the pointer before the gesture is considered a swipe. In the current state even the slowest and smallest horizontal drag motion will trigger a CrossSliding event.
I saw the CrossSlideThresholds class that allows to customize the gesture, but I couldn't see how it could be used to configure speed and distance of the swipe gesture.
Is the CrossSliding event the proper way to detect a swipe? If so, how can I configure speed and swipe distance?
If not, how can I detect a swipe gesture?
I could not find any built in way to detect a swipe, so I implemented my own detection method.
The code detects a horizontal swipe.
The shown methods are the event handlers for the GestureRecognizer events:
readonly Stopwatch _manipulationTimer = new Stopwatch();
public void OnManipulationStarted(ManipulationStartedEventArgs e)
{
_manipulationTimer.Restart();
}
public void OnManipulationCompleted(ManipulationCompletedEventArgs e)
{
var millis = _manipulationTimer.ElapsedMilliseconds;
if (Math.Abs(e.Cumulative.Translation.Y) < MaxVerticalSwipeDistanceInPix &&
Math.Abs(e.Cumulative.Translation.X) > MinHorizontalSwipeDistanceInPix &&
millis > MinSwipeDurationInMillis &&
millis < MaxSwipeDurationInMillis &&
Math.Abs(e.Cumulative.Scale - 1) < 0.01 // 1 touch point
)
{
var leftSwipe = e.Cumulative.Translation.X < 0;
if (leftSwipe)
{
}
else // right swipe
{
}
}
_manipulationTimer.Stop();
_manipulationTimer.Reset();
}

Tile Engine Collision

Okay, so, I am making a small tile-based digging game, now I want to do collision. How would I go about doing this correctly? I know how to check if the player collides with a tile, but I don't know how to actually make the player stop when it hits a wall.
This is the game, I got 20x20 tiles here.
This is the code I'm using atm:
foreach (Tile tiles in allTiles)
{
if (ply.rect.Intersects(tiles.rect))
{
if (tiles.ID != -1 && tiles.ID != 1)
{
if (ply.X > tiles.X)
{
Console.WriteLine("Right part.");
ply.X = tiles.pos.X + 30;
}
if (ply.X <= tiles.X)
{
Console.WriteLine("Left part.");
ply.X = tiles.pos.X - 30;
}
if (ply.Y > tiles.Y)
{
Console.WriteLine("Bottom part.");
ply.Y = tiles.pos.Y + 30;
}
if (ply.Y <= tiles.Y)
{
Console.WriteLine("Upper part.");
ply.Y = tiles.pos.Y - 30;
}
}
}
}
What type of collision detection are you using?
If your using Rectangles and the '.intersects' method you can always declare a bool to make sure your character is touching the floor. If he isn't you apply a Gravity Vector to make it fall to the next Tile with a different Rectangle so when he hits it he's going to stop falling.
If you want to block him from side to side just test to see which side of the rectangle he is touching and block him from moving on the 'X' axis.
E.g if he is going right and intersects with the left part of a rectangle, block is 'GoingRight' movement.
if(myCharacterRectangle.Intersects(tileRectangle)
{
if(myCharacterPosition.X > (tilePosition.X)
{
//You know the character hits the Right part of the tile.
}
if(mycharacterPosition.X <= tilePosition.X)
{
//You know the character hits the Left Part of the tile.
}
}
And same goes for the Position.Y if you want to test the Top or Bottom.
If you want to use Pixel by Pixel collision detection using Matrices I know a good tutorial here.
The detection will return a 'Vector2(-1,-1)' if there is no collision.
If there is a one the method will return the coordinates of the collisions which makes it even easier to determine what part of the tile your character is touching.
Hope this helps. Good Luck with your game.

Categories

Resources