MonoGame阅读触摸手势(MonoGame reading touch gestures)

2019-08-16 17:13发布

我现在用的是梦幻般的monogame框架目前正在写一个游戏。 我无法反应,正确触摸输入。 当用户水平或垂直拖拽我想每一次拖动执行操作。 问题是,手势越来越多次发出的每条拖。 这里是我的代码:

var gesture = default(GestureSample);

while (TouchPanel.IsGestureAvailable)
    gesture = TouchPanel.ReadGesture();

if (gesture.GestureType == GestureType.VerticalDrag)
{
    if (gesture.Delta.Y < 0)
        return new RotateLeftCommand(_gameController);

    if (gesture.Delta.Y > 0)
        return new RotateRightCommand(_gameController);
}

if (gesture.GestureType == GestureType.HorizontalDrag)
{
    if (gesture.Delta.X < 0)
        return new RotateLeftCommand(_gameController);

    if (gesture.Delta.X > 0)
        return new RotateRightCommand(_gameController);
}

我提出这些代码的一个块这个例子的目的。 返回的RotateRightCommand或RotateLeftCommand然后由该旋转屏幕上的对象调用代码执行。 这整个的代码块在monogame的更新循环中运行。 我想我失去了一些东西在重置触摸输入方面,这就是为什么我得到一个拖回到3个或4 RotateCommands。 我究竟做错了什么?

Answer 1:

编辑:您没有使用正确的姿势这里。 甲拖动手势生成的每个手指在屏幕上移动的时间。 如果你从屏幕到另一个(很快)的一侧移动你的手指,你会得到很多的小的拖拽手势。 这是怎么XNA和MonoGame工作。

这就是你要找的逻辑:

var touchCol = TouchPanel.GetState();

foreach (var touch in touchCol)
{
    // You're looking for when they finish a drag, so only check
    // released touches.
    if (touch.State != TouchState.Released)
        continue;

    TouchLocation prevLoc;

    // Sometimes TryGetPreviousLocation can fail. Bail out early if this happened
    // or if the last state didn't move
    if (!touch.TryGetPreviousLocation(out prevLoc) || prevLoc.State != TouchState.Moved)
        continue;

    // get your delta
    var delta = touch.Position - prevLoc.Position ;

    // Usually you don't want to do something if the user drags 1 pixel.
    if (delta.LengthSquared() < YOUR_DRAG_TOLERANCE)
        continue;

    if (delta.X < 0 || delta.Y < 0)
        return new RotateLeftCommand(_gameController);

    if (delta.X > 0 || delta.Y > 0)
        return new RotateRightCommand(_gameController);   
}

如果您愿意的手势,你可以这样做:

var gesture = default(GestureSample);

while (TouchPanel.IsGestureAvailable)
{
    gesture = TouchPanel.ReadGesture();

    if (gesture.GestureType == GestureType.DragComplete)
    {
        if (gesture.Delta.Y < 0 || gesture.Delta.X < 0)
            return new RotateLeftCommand(_gameController);
        if (gesture.Delta.Y > 0 || gesture.Delta.X > 0)
            return new RotateRightCommand(_gameController);
    }
}

无论哪种方式,会给你你正在寻找的行为。 你仍然需要把逻辑循环内正如我在原来的职位说,因为你可以有多个手势排队,而你不想假设最后一个堆栈的阻力。 (感谢多点触摸,你可以有拖动,水龙头,拖动完成,等等)。

我不是100%肯定,如果这是你的问题...但你的逻辑是错在这里。 该CodeFormatting老板在这里打我,但它应该是更多这样的:

var gesture = default(GestureSample);

while (TouchPanel.IsGestureAvailable)
{
    gesture = TouchPanel.ReadGesture();

    if (gesture.GestureType == GestureType.VerticalDrag)
    {
        if (gesture.Delta.Y < 0)
            return new RotateLeftCommand(_gameController);
        if (gesture.Delta.Y > 0)
            return new RotateRightCommand(_gameController);
    }

    if (gesture.GestureType == GestureType.HorizontalDrag)
    {
        if (gesture.Delta.X < 0)
            return new RotateLeftCommand(_gameController);
        if (gesture.Delta.X > 0)
            return new RotateRightCommand(_gameController);
    }
}

如果不把TouchPanel.ReadGesure()在一个循环内,你只阅读每帧的一个gesure。 可用手势放入队列,只有移除时ReadGesture()被调用。 因此,如果你的帧率打嗝,或者如果您无法读取手势一样快,您的操作系统可以读取它(这是很可能的),你会用旧的信息工作。 你可以看到在这里 。 对于这种应用,我建议采取每个手势,并将其组合成一个或两个,然后决定应该基于该做些什么。



Answer 2:

我想这取决于你认为是一个拖累。 MonoGame和XNA考虑从一个更新到下一一拖变化的触摸输入的检测。 所以,如果你认为你会收到一个手势,从你触摸你的手指在屏幕上的时间,直到你删除它,那将是XNA和MonoGame方面不正确。 被返回的手势是由T-1的三角洲其中T是现在和T-1是上一次调用更新。



文章来源: MonoGame reading touch gestures