Software engineering and GUI design WPF graphics intro

  • Slides: 40
Download presentation
Software engineering and. GUI design WPF graphics intro Usage of the Framework. Element class

Software engineering and. GUI design WPF graphics intro Usage of the Framework. Element class 1

WPF graphics – coordinate system • The (0, 0) point is in the top-left

WPF graphics – coordinate system • The (0, 0) point is in the top-left corner, so every location is the position of the top-left corner based on the top-left corner of the container – An object’s final location is affected by many properties: Horizontal. Alignment, Margin, Padding, layout manager settings, … – Taking all factors into account, there is a separate phase (“Layout”) that determines the final 2 D position – not trivial to read, very hard to write! – Much easier if we use the Canvas layout manager 2

WPF graphics – types (System. Windows) • Nothing is displayed, these types are only

WPF graphics – types (System. Windows) • Nothing is displayed, these types are only used for data representation ! • Struct types (value types) • Point: a single point in 2 D space – X, Y • Size – Width, Height • Rect, Int 32 Rect: a rectangle in 2 D space – X, Y, Width, Height, Top, Bottom, Left, Right • Vector: a location vector in 2 D space – X, Y, Length. Squared 3

WPF graphics – colors • Every color is represented with four 8 bit values:

WPF graphics – colors • Every color is represented with four 8 bit values: • Red (R), Green (G), Blue (B) – bytes (0 -255), so totally 256^3 ≈ 16 million colors are possible (“good enough”) • Alpha (A) – Defines the transparency of the color, 0: fully transparent, 255: not transparent • The Color struct is used to represent colors Color color = Colors. Red; Color color = Color. From. Argb(20, 255, 0, 0); 4

WPF graphics – brushes • Forrás: http: //i. msdn. microsoft. com/dynimg/IC 107818. jpg 5

WPF graphics – brushes • Forrás: http: //i. msdn. microsoft. com/dynimg/IC 107818. jpg 5

WPF graphics – brushes • C# definition: //pre-defined solid color brush: button. Background =

WPF graphics – brushes • C# definition: //pre-defined solid color brush: button. Background = Brushes. Red; //self-made brush with pre-defined color: button. Background = new Solid. Color. Brush(Colors. Aqua); //self-made brush with self-made color: Color almost. Red = Color. From. Argb(20, 255, 0, 0); button. Background = new Solid. Color. Brush(almost. Red); • XAML definition: <Button Background="Alice. Blue" Content="Button". . . /> <Button Background="#FFFF 0000" Content="Button 2". . . /> <Grid. Resources> <Solid. Color. Brush x: Key="my. Color" Color="Azure"/> </Grid. Resources>. . . <Button Background="{Static. Resource my. Color}"></Button> 6

WPF graphics – other types • Pen – Used for drawing lines – Fill

WPF graphics – other types • Pen – Used for drawing lines – Fill (brush), thickness, line style, line endings • Geometry – Can represent an arbitrary geometrical shape (abstract class) – The descendants are used – System. Windows. Rect vs System. Windows. Media. Rectangle. Geometry vs System. Windows. Shapes. Rectangle – Universal geometrical operations, even with very complex geometrical shapes (e. g. we can create geometry from letters, union/intersection, splines, etc…) • Drawing – Pen + Brush + Geometry 7

Other geometry types • Stream. Geometry = polygons • Path. Geometry = set of

Other geometry types • Stream. Geometry = polygons • Path. Geometry = set of complex line segments – From text, using Formatted. Text. Build. Geometry(xxx) method • Handle multiple Geometry instances with Geometry. Group – The Geometry. Group is a Geometry descendant, so it is very easy to handle with complex geometric shapes Ellipse. Geometry ellipse = new Ellipse. Geometry (new Point (10, 10), 10 ); Formatted. Text text = new Formatted. Text ("This is my ellipse. ", Culture. Info. Current. Culture, Flow. Direction. Left. To. Right, new Typeface ("Tahoma" ), 16, Brushes. Black ); Geometry text. Geometry = text. Build. Geometry( new Point (10, 20 )); Geometry. Group group = new Geometry. Group (); group. Children. Add(ell ipse); group. Children. Add(text. Geometry); geometry. Drawing. Geometry = group; 8

UI element to display images: Image • Image. Source: the image to be displayed

UI element to display images: Image • Image. Source: the image to be displayed – Descendants of System. Windows. Media. Image. Source class • Image. Stretch automatic resize (None, Fill, Uniform. To. Fill) Bitmap. Source (+descendants) Drawing. Image D 3 DImage abcdef 9

Graphics possibilities in. WPF • Shapes (System. Windows. Shape descendants ) – Pre-made, simple

Graphics possibilities in. WPF • Shapes (System. Windows. Shape descendants ) – Pre-made, simple controls – Also accessible via the Toolbox (Rectangle, Ellipse. . . ) – Input, focus, events, data binding: to be handled individually… – Only if few (max ~100) objects are used • Drawings (System. Windows. Media. Drawing descendants ) – Cannot be used on their own, must be put into a hosting object ( Image. Source = new Drawing. Image(xxx) ) – No support for input events, the hosting object handles its own events – Also usable from XAML, with a few data bindings and converters – Faster than the Shape controls (max ~1000 objects) • Visuals (System. Windows. Media. Visual descendants ) – The most complex, also the fastest (max ~10000 drawn objects) – Drawn objects no need to be stored in the memory – Always handled from code hard to write pretty code! 10

Graphics possibilities in. WPF Approach Event handling / Display handling Usage Number of objects

Graphics possibilities in. WPF Approach Event handling / Display handling Usage Number of objects Shape Drawn object = XAML + Binding control, individually for every controls Drawing Hosting object (image) XAML + Binding ~1000 handles all drawn + Converters objects together (xxx Drawing) Visual Hosting object displays the drawn objects together, no real object storage, only used as a “drawing canvas” ~100 CS code: ~10000 On. Render + Drawing. Context + Geometry 11

Usage of Visual descendants class Main. Window : Window // window, we need Background=Transparent

Usage of Visual descendants class Main. Window : Window // window, we need Background=Transparent { protected override void On. Render( Drawing. Context drawing. Context) { drawing. Context. Draw. Geometry( Brushes. Blue, new Pen(Brushes. Red, 2), geometry); } } • Typically we do this not in a Window, but rather in a unique Framework. Element descendant – Using the On. Render() method we can issue drawing commands – Drawing. Context the drawing canvas that we draw upon – Not an immediate operation (retained mode) • Refresh of the control can always be enforced using the Invalidate. Visual () method which MUST NEVER be called from the On. Render method 12

Framework. Elementrules • Empty (not drawn) areas will not fire the mouse events –

Framework. Elementrules • Empty (not drawn) areas will not fire the mouse events – The first drawn object should be a big background rectangle • Keyboard events are not captured – The window will capture them, and we can always access the window using Window. Get. Window(this) (not elegant, but this semester it is good enough for us) – OR: Focusable=true and the control will also capture the keyboard events (if it has the keyboard focus!) • Try and use it in a nicely layered way – It is very easy to write hard-to-maintain code – Aim: Model + Logic + Control • Home-practice exercises: at the end of this presentation 13

Accessing UI elements from multiple threads • In Windows, UI elements (controls) can typically

Accessing UI elements from multiple threads • In Windows, UI elements (controls) can typically only be accessed from the creator thread (GUI thread, UI thread) – That includes indirect access – Few exceptions (some methods, Property. Changed event) • Universal solution : Invoke – Ask a callback from the UI thread (Blocking! Deadlock danger!) Dispatcher. Invoke(() => { label. Content =. . . ; list. Box. Items. Add(. . . ); }); • Using Task: alternative Task scheduler – Default: Thread Pool Task Scheduler – It is possible to assign new tasks to the GUI-thread scheduler 14

Accessing UI elements from multiple threads • GUI task scheduler – Obtain reference from

Accessing UI elements from multiple threads • GUI task scheduler – Obtain reference from the GUI thread – Task. Scheduler. From. Current. Synchronization. Context() Task<int> task. With. Return. Value = Task. Run(() => { Thread. Sleep(1000); return 6; }); task. With. Return. Value. Continue. With( t => text. Box 1. Text = "Result: " + t. Result, Cancellation. Token. None, Task. Continuation. Options. Only. On. Ran. To. Completion, Task. Scheduler. From. Current. Synchronization. Context()); 15

System. Windows. Threading. Dispatcher. Timer • We use it to execute operations periodically (Game.

System. Windows. Threading. Dispatcher. Timer • We use it to execute operations periodically (Game. Logic, automatic actions ) – Interval: property to set how often the timer will be executed (Time. Span type) – Start(), Stop(): Methods – Tick: Event that signals that the specified interval is over (with the event, the measurement of the interval re-starts) • Many different Timer types – do not mix them up ! – – System. Timers. Timer Threadsafe, very precise System. Threading. Timer Uses a Threadpool thread, not threadsafe System. Windows. Forms. Timer Windows forms component System. Web. UI. Timer Periodic webpage postback (synchronized or async) – System. Windows. Threading. Dispatcher. Timer WPF threadsafe timer that uses the Dispatcher. Thread 16

Lesson Exercise: Pong 17

Lesson Exercise: Pong 17

Flappy Bird 18

Flappy Bird 18

Transformations • Represented using Transform descendants (they are matrices ) – Rotate. Transform –

Transformations • Represented using Transform descendants (they are matrices ) – Rotate. Transform – Scale. Transform – Skew. Transform – Move (Translate. Transform) – Universal transformations (Matrix. Transform) – Multiple transformations after each other (Transform. Group) 19

Using transformations • Framework. Element + Layout manager (Grid, Stack. Panel…) – Layout. Transform

Using transformations • Framework. Element + Layout manager (Grid, Stack. Panel…) – Layout. Transform (before the layout phase) – Render. Transform (after the layout phase) • Geometry – Geometry geo = new Rectangle. Geometry(xxx); – geo. Transform = new xxx. Transform(xxx); – Warning: doesn’t modify the original geometry coordinates – Geometry result = geo. Get. Flattened. Path. Geometry() – Erase transformation: geo. Transform = Transform. Identity; • Drawing. Context – Drawing. Context. Push. Transform(new Translate. Transform(xxx)); – Drawing. Context. Draw. XXX(xxx); – Drawing. Context. Pop(); 20

Using transformations(in our games) • We should set every gameitem’s Geometry datafield to make

Using transformations(in our games) • We should set every gameitem’s Geometry datafield to make them centered around (0; 0) • Then before draw/collision detection, we transform them into the appropriate position/orientation • Slower (due to the continuous re-calculation ), but makes modeling/programming a lot easier 21

Intersection of geometries(collision detection) • To check for collisions, we have to create a

Intersection of geometries(collision detection) • To check for collisions, we have to create a new geometry from the intersection of the two geometries (Geometry. Combine()), and then calculate surface area (Get. Area()) Geometry intersection = Geometry. Combine(geometry, other. Geometry, Geometry. Combine. Mode. Intersect, null); return intersection. Get. Area() != 0; • Warning: Line. Geometry has no surface area, so the combined geometry will always have a surface area of zero – Solvable by „extending” the line – Geometry result = geometry. Get. Widened. Path. Geometry(new Pen(Brushes. Blue, 2)) – The color of the pen is not used, only the line style/thickness 22

Lesson exercise: Flappy Birds Turbo 23

Lesson exercise: Flappy Birds Turbo 23

Class Bird : Game. Item 24

Class Bird : Game. Item 24

Class Pipe : Game. Item 25

Class Pipe : Game. Item 25

Lesson exercise: Laby the Ultimate Labyrinth 26

Lesson exercise: Laby the Ultimate Labyrinth 26

Single-responsibility classes • Combine the previously known solutions AND – Attaching resources (file-s, do

Single-responsibility classes • Combine the previously known solutions AND – Attaching resources (file-s, do not overuse!) – Load images: BMP/PNG/JPG Image. Brush – Tiled Brush: for drawing walls, Tile vs Pixel coordinates – More efficient render process • Builder Design Pattern • Saving the Image. Brush instances into a Dictionary • Saving the Drawing (Brush + Pen + Geometry) instances into variables – Mouse clicks only work on drawn areas big background image – Subscribe to the Key. Down event of the owner window – Refresh the Game. Control • Based on the Game. Control (timer/keydown) • Based on the Game. Logic (when the Logic asks via an event) 27

Tiled brush? 28

Tiled brush? 28

Creating a self-made control • Can be used from XAML the usual way –

Creating a self-made control • Can be used from XAML the usual way – Zero-parameter constructor must exist • Inheritance : from Framework. Element base class – All our games beforehand were in fact, controls – Using the same rules, we can create a normally usable control that won’t fill up the whole window, and fits into the layout – Subscription to window events / Message. Box is not elegant • Inheritance : from arbitrary control as a base class – Extend a pre-existing control with extra functionality • Composition : User control – Create new control by assembling pre-existing controls – In the Logical tree it will be a single control – E. g. Numeric. Up. Down = Text. Box + Button 29

Accessing properties from XAML • Properties/events can be accessed the usual way – <local:

Accessing properties from XAML • Properties/events can be accessed the usual way – <local: Up. Down. Control Is. Down="True" Is. Down. Changed="Up. Down. Control_Is. Down. Changed„ • Data binding: Is. Down="{Binding Path=Points. Down}" – Data binding WILL NOT work with simple properties – It uses “Dependency Property” properties – If you want a bool-typed Dependency property, it can be described as a global storage similar to public static Dictionary<Up. Down. Control, bool> Is. Down. Property public bool Is. Down { get { return Is. Down. Property[this]; } set { Is. Down. Property[this] = value; } } 30

Dependency Property public static readonly Dependency. Property Is. Down. Property = Dependency. Property. Register(

Dependency Property public static readonly Dependency. Property Is. Down. Property = Dependency. Property. Register( xxx); public bool Is. Down { get { return (bool)Get. Value(Is. Down. Property); } set { Set. Value(Is. Down. Property, value ); } } Dependency. Property. Register( nameof (Is. Down ), typeof (bool), typeof (Up. Down. Control ), new Framework. Property. Metadata () { Binds. Two. Way. By. Default = true } ); 31

Lesson exercise: Up. Down. Control + Sorted. LB 32

Lesson exercise: Up. Down. Control + Sorted. LB 32

Software engineering and. GUI design Practice exercises 33

Software engineering and. GUI design Practice exercises 33

Home practice: Simple. Laby 34

Home practice: Simple. Laby 34

Home practice: Simple. Laby • If the player finishes a level, a new one

Home practice: Simple. Laby • If the player finishes a level, a new one should be automatically loaded • We should measure the time for every level (System. Diagnostics. Stopwatch class) • In a new window, display the level times using a Graph drawn using a Geometry. Drawing 35

Home practice: Asteroids 36

Home practice: Asteroids 36

Home practice: Asteroids • Asteroids rules: – The player can only rotate and shoot.

Home practice: Asteroids • Asteroids rules: – The player can only rotate and shoot. – The asteroid moves in a random direction using a constant speed, when it hits the side of the gamescreen, it re-appears on the other side – If the bullet hits an asteroid, it disappears (real version: it splits up into smaller asteroids) – The bullet also re-appears on the other side of the gamescreen (but the bullet is only “alive” for a given amount of time) 37

Home practice: Chaos Frogger 38

Home practice: Chaos Frogger 38

Home practice: Chaos Frogger • A single obstacle can only move in the up-down

Home practice: Chaos Frogger • A single obstacle can only move in the up-down OR in the left-right directions. If they reach the side of the window, they reverse • Their speed changes randomly , and also there are some evil obstacles that speed up if the player is nearby • The player has three lives at the beginning, and we have to get to the bottom-right corner. If an obstacle touches the player, then the player loses a life. 39

Home practice: Tic Tac Toe – Rules: the players take turns in putting down

Home practice: Tic Tac Toe – Rules: the players take turns in putting down their respective marks. The one who makes up three items horizontally, vertically or diagonally will win the game – If the playing field fills up without a win, then it’s a tie 40