📜 ⬆️ ⬇️

Cross-platform New Year's demo on .NET Core and Avalonia

" AAA! It's time to rewrite to .NET Coreǃ, " they said, WPF discussed in the comments. So let's check if you can write a cross-platform GUI application in .NET / C #.



Christmas mood inspired the idea to make the animation of falling snow. There were such demos for DOS, burning fire, fractals, a snowball falling on a Christmas tree, and so on.


As we will see below, it is not only fun, but also allows you to experience the key functionality of the UI framework. Go!


Project Creation and UI


For Avalonia, there is a Visual Studio Extension with a project template. Install, create Avalonia .NET Core Application . We see habitual on WPF App.xaml and MainWindow.xaml . However, the project contains <TargetFrameworks>netcoreapp1.1;net461</TargetFrameworks> , change to <TargetFramework>netcoreapp2.0</TargetFramework> , we are not in the Stone Age.


The Avalonia extension for the studio contains the XAML Designer, but it did not work for me. Resharper goes a little crazy in the markup editor, wants to insert explicit namespaces everywhere, so we'll manage without him too.


For the rest, we have in our hands the usual XAML with the usual controls and properties. All differences can be read in the documentation .


For arbitrary drawing, there is an analogue of the same name WriteableBitmap from WPF. A huge plus is that there are no problems drawing in it from any stream, it looks like this:


 <Image Source="{Binding Bitmap}" Stretch="Fill" /> 

 using (ILockedFramebuffer buf = writeableBitmap.Lock()) { uint* ptr = (uint*) buf.Address; //  *ptr = uint.MaxValue; } 

However, Image , which is tied to our writeableBitmap, will not update by itself, it needs to say InvalidateVisual() .


Thus, we can draw animations in the background thread without loading UI thread. In addition to Image we will add a couple of sliders to control the speed of snow falling and the number of snowflakes, everything is standard here, {Binding Mode=TwoWay} . Plus, the "start over" button is also a standard link to ICommand . I note that vector icons on XAML, copied from Google, are used, <Path> functions as expected.


Full markup: MainWindow.xaml


Snow algorithm


"Physics"


Move the snowflake down one pixel. If the pixel is already occupied by the "lying" snowflake, check the points on the left and right, and move to where it is free. Everything is busy - mark the point as "lying." Thus, the rolling of snowflakes from inclined surfaces is achieved.


Parallax


To achieve the volume effect, let us set a random speed for each snowflake. The lower the speed, the darker the shade we use for drawing.


In order for our "physics" to work correctly, it is necessary to move the snowflakes no more than 1 pixel per frame. That is, the fastest snowflakes move each frame per pixel, the others skip some frames. To do this, you can use the float coordinates and simply redraw every snowflake for each frame. Instead, I use two integer short fields and redraw the snowflake only if it really moved .


Rendering


The main idea is to avoid full frame redrawing. We need to somehow store the "lying" snow, user-drawn dots, downloaded images (yes, you can draw with the mouse and load picchi with a right click - the snowball will stick to Christmas trees and inscriptions).


A simple and effective solution is to use WriteableBitmap itself. Let the “permanent” pixels be completely opaque (A = 255), and for moving snowflakes A = 254.


Falling snowflakes are always a fixed number, position and speed of each stored in the array. As a result, if the snowflake has moved - we erase the point on the old position and draw on the new one. If turned into a "recumbent" - set the alpha channel of the point to 255, move the live dropback back to the top.


How to run it?


Thanks to the possibility of drawing directly "alive", it turned out to be a pretty sticky thing, try it :)


For all OS, the instruction is the same:



Conclusion


.NET Core is young, Avalonia is still in alpha, but now these tools solve the problem! The code is simple and clear, no hacks and extra squats, works great on Windows, macOS, Linux.


Alternatives?



The UI in this demo is very simple, but it uses some of the most important features:



This is enough to build a UI of any complexity. So, we can say that the last gap in the .NET ecosystem is closed: it is possible to create web (ASP.NET Core), mobile (Xamarin) and desktop (Avalonia) applications, while reusing the code by placing it in the .NET Standard libraries.


Links



')

Source: https://habr.com/ru/post/345708/


All Articles