-
Notifications
You must be signed in to change notification settings - Fork 0
Field and Coordinates
As soon as the main screen is opened the app is forced into portrait mode.
mainScreen.dart
SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft, ]);
The flutter class GestureDetector is used which has an attribute onTapDown where you can insert a function of TabDownDetails. TabDownDetails details carries information about the coordinates on the screen. details.globalPosition gives the global coordinates of the whole screen. We need details.localPosition which gives the local position of its parent, which is the field image in our case.
To be able to select the location where a palyer performed an action, we decided to show a halffield on the screen. To switch between attack and defense, the app user can swich between right and left field view (the swich possibility will be implemented later).
The screen looks like this:



right side example:

- fieldWidth, fieldHeight: dart.ui library is used to get the number of pixels of the device in width and height. Only a fraction of those pixels can be used, so not the whole screen is used for the field. In the example images the whole width but only 80% of the height is taken.
The following parameters should not be hardcoded but taken as a fraction from fieldWith and fieldHeight.
- sixMeterRadiusX: Radius of the smaller ellipse in horizontal direction.
- sixMeterRadiusY: Radius of the smaller ellipse in vertical direction.
- nineMeterRadiusX: Radius of the bigger ellipse in horizontal direction.
- nineMeterRadiusY: Radius of the bigger ellipse in vertical direction.
The sector borders are simply lines which are desctibed by y=gradient * x + yIntercept
- gradients: List of gradients of the sector borders.
- yIntercepts: List of y intercepts of the sector borders.
The widget which paints the field and handles the coordinates is called CustomField. The flutter class CustomPaint is used for painting the geometries which carries the GestureDetector as child to get the coordinates. What had to be implemented is the Painter for CustomPaint (FieldPainter) and the handling of the coordinates (SectorCalc), both can be found in helper.dart.
With the parameter bool leftSide the shown field side can be changed.
-
FieldPainter: The geometries to be painted are defined in the function paint. Therefore, the parameter from fieldSizeParameter.dart are used.
- The two ellipses (canvas.drawOval) are defined by their center, width and height. Width is ...MeterRadiusX * 2, height is ...MeterRadiusY * 2 and the center y-position is fieldHeigh / 2. The center x-position depends on if the left or right side is depicted, it is 0 or fieldWidth, respectively.
- The sector borders (canvas.drawLine) are defined by two points, the start and end point of the line.
To draw a line you need two points: (x1,y1) and (x2,y2).
(x1,y1) is given: x1 is 0 for left side, fieldWidth for right side and y1 is the given y intercept.
(x2,y2) needs to be calculated:- for the left side we define x2=fieldWidth and put it into the given line equation (gradient*x2+y_intercept)
- for the right side we know gradient_right = -gradient_left and with this we calculate the y intercept. So we also have a line equation and can put x2 into it to get y2.
-
SectorCalc: Class to calculate if a click was inside or outside a section. It takes x and y coordinates from GestureDetector and has functions which say if a click was inside or outside:
-
inSixMeterEllipse(), inNineMeterEllipse(): It is checked if
$$\frac{x²}{...MeterRadiusX²}+\frac{y²}{...MeterRadiusY²} <= 1$$ -
inSector(): Calculates if a point (x,y) is between two sector borders. Goes through each line defined by gradient and y intercept in fieldSizeParameter.dart and checks with
gradient * x + yIntercept <= y
if (x,y) is below this border and with
lowerGradient * x + lowerIntercept > y
if (x,y) is still above the border below.
-
To get the radial sector degrees like in issue #60, you need the pitch angle (Steigungswinkel). In our case the pitch angles are 20°,55°,-20°,-55°. You get the slope of the line then which tan(pitch angle).
To swipe between the painting of left and right field side, the flutter class PageView is used. It takes as children the Widgets to swipe between, so in our case CustomField(leftSide: true) and CustomField(leftSide: false) which depicts the field on left and right side respectively. It is important to put the PageView or the Widget returning the PageView inside a SizedBox, otherwise there will be a rendering error.
After goal, err throw and block&steal an automatic switch to the defense side (in goal, err throw case) and attack side (in block&steal case) is implemented. This works with a static PageController for the FieldSwitch widget that holds the PageView for switching between both sides. The PageController is for programmatically changing the displayed children in a PageView widget.
In playermenu.dart the logic for the automatic switch is implemented. If the global variables fieldIsLeft (is the left or right field side shown in this moment?) and attackIsLeft (is the left or right side the offense side?) have the right combination of bool values and one of the above mentioned actions happened, with FieldSwitch.pageController.jumpToPage(0/1) the displayed field side is changed.
As for a static PageController (as well as when it is saved in a getx controller) there are automatically positions attached which bring up an error (which is not understood), the following code lines are used:
while (FieldSwitch.pageController.positions.length > 1) {
FieldSwitch.pageController
.detach(FieldSwitch.pageController.positions.first);
}


-
[main_screen_field_helper.dart] Change colors: The colors can be changed easily in the drawOval function of FieldPainter.
-
[main_screen_field_helper.dart] Add 7m line: The line is added with the drawLine function of CustomPainter in FieldPainter. It is defined by two points: (x1,y1) and (x2,y2). As the line is vertical, it is x1=x2 and is the first third between 6m and 9m line. y1 is a bit above halve the field height and y2 is a bit below.
-
[main_screen_field_helper.dart] Add dashed 9m line: It is not supported well to draw dashes in flutter (stackoverflow), a new CustomPainter DashedPathPainter is added, the code is taken mainly from stackoverflow. It uses the function drawPath from CustomPainter, to convert the geometry (in our case the 9m oval) into a path and alternately draws a dash and a gap along the path.
[field.dart] CustomField is adapted, so it uses a Stack to paint DashedPathPainter and FieldPainter. -
[mainScreen.dart] Add border. A border is added around the field which has the same thickness as the 7m line and 9m dashed line. Therefore, a Container is added which takes the FieldSwitch as child and has the parameter border: Border.all(width: fieldSizeParameter.lineSize)).
-
[fieldSizeParameter.dart] Expand height to available height and set field width to a fix proportion of the height, so the field has the same aspect ratio for different screen ratios. The available screen heigh is screenHeight - toolbarHeight - paddingBottom - paddingTop - lineSize * 2. So it takes all the height of the screen minus the height of the toolbar (toolbarHeight), other device specific bars on top and bottom (paddingBottom, paddingTop) and the upper and lower border around the field (lineSize). The field height is set to min(availableScreenHeight, screenWidth), so if the screen width is smaller than the screen height, the field is not expanded along the available height but a bit shorter, so the field width always fits on the screen and leaves space for other features. (Issue #131)
-
[main_screen_field_helper.dart] The lines indicating the sectors are removed in FieldPainter. As the painting is independent of the recognition of the sectors, the functionality to get the sector a click was in is still working.
To change the colors depending on if we are on attack or defense side, GetBuilder is used. GetBuilder is building the CustomPaint Widget, which paints the Field with FieldPainter. FieldPainter now takes as arguments colors for 9m, 6m circle and background. Depending on values in TempController it is decided on if we are on defense or attack side and the colors are assigned.
For the background color, a new geometry is added to FieldPainter: The rectangle for the background. This way, the colors can all be assigned by giving them FieldPainer as parameter.
This sidebar is customized. You can add new pages here by clicking 'Edit sidebar' above. To see all pages that exist in the Wiki click here
Ef Score
Firebase
UI
Figma Screens
Flutter
- Dashboard
- Start Game Screen
- Authentication Screen
- App Settings
- Class Model and Data
- Feed
- First Steps
- Helper Screen
- Settings Screen
- State Management
- Testing
- String Management
- Helpers