Adding touch to a game using Xamarin Forms and SkiaSharp

In the previous part we had our gameloop which rendered a moving circle. In this part we are adding SkiaSharp touch events to the SKCanvasView. When the screen is tapped or the mouse is clicked a rectangle is rendered at the position that was clicked.

To enable touch events, set EnableTouchEvents to true and subscribe to the Touch handler in the MainPage.xaml.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label x:Name="fpsLabel" HorizontalOptions="Start" VerticalOptions="Start" Margin="20,0"/>
        <forms:SKCanvasView x:Name="canvasView" Grid.Row="1" EnableTouchEvents="True" Touch="OnTouching"/>
    </Grid>
	

The MainPage.xaml.cs is extended with the OnTouching method, which sends the touch information to the app.

    public partial class MainPage : ContentPage
    {
        // See refactor blog for the full implementation

        public MainPage()
        {
            InitializeComponent();
        }

        // Handle the touch events and send it to the PixelApp. Note, to enable other events, set e.Handled = true;
        private void OnTouching(object sender, SKTouchEventArgs e)
        {
            switch (e.ActionType)
            {
                case SKTouchAction.Pressed:
                    _pixelApp.OnPressed(e.Location);
                    break;
            }
        }
    }		
	

The PixelApplication class gets a new method OnPressed which has the touch location as a SKPoint. This is stored in a list, which is rendered in the Render method using the canvas DrawRect method

    public class PixelApplication
    {
        // See the refactor blog for the remaining code, it is the same as there.
		
        private List touches = new List();

        public void OnPressed(SKPoint point)
        {
            touches.Add(point);
        }

        public void Render(SKCanvas canvas, double updateDelta)
        {
            // Extra elapsed time since last stopwatch restart
            var dt = updateDelta + remainingTime;

            // Update the position with the extra elapsed time distance
            float xp = (float)(x + dt * vx);
            float yp = (float)(y + dt * vy);

            canvas.Clear(_fillColor);

            using (SKPaint skPaint = new SKPaint())
            {
                skPaint.Style = SKPaintStyle.Fill;
                skPaint.IsAntialias = true;
                skPaint.Color = SKColors.Blue;
                skPaint.StrokeWidth = 10;

                // Draw a rectangle whose center is the touch point
                foreach (var p in touches)
                    canvas.DrawRect(p.X-50.0f, p.Y-50.0f, 100.0f, 100.0f, skPaint);

                canvas.DrawCircle(xp, yp, r, skPaint);
            }
        }
    }
	

When everything is working you should see the same blue circle bouncing around on the screen as in the previous refactor tutorial. Now you can press or click the screen and you should see blue rectangles drawn at those locations.