@luceosports/play-rendering 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/play-rendering.js +3 -3
- package/dist/play-rendering.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.js +7 -0
- package/src/layers/court/layers/LACROSSE/constants.js +7 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_M/constants.js +6 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_M/layers/CenterLineLayer.js +33 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_M/layers/GoalAreaLineLayer.js +57 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_M/layers/WingAreaLineLayer.js +43 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_W/constants.js +5 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_W/layers/CenterLineLayer.js +23 -0
- package/src/layers/court/layers/LACROSSE/courtTypes/US_LACROSSE_W/layers/FanLineLayer.js +147 -0
- package/src/layers/court/layers/LACROSSE/layers/BorderRectLayer.js +12 -0
- package/src/layers/court/layers/LACROSSE/layers/RestrainingLineLayer.js +23 -0
- package/src/layers/court/layers/SOCCER/constants.js +7 -0
- package/src/layers/court/layers/SOCCER/courtTypes/SOCCER_FIFA/constants.js +4 -0
- package/src/layers/court/layers/SOCCER/layers/BorderRectLayer.js +12 -0
- package/src/layers/court/layers/SOCCER/layers/CenterCircleLayer.js +20 -0
- package/src/layers/court/layers/SOCCER/layers/CenterLineLayer.js +16 -0
- package/src/layers/court/layers/SOCCER/layers/CornerLayer.js +25 -0
- package/src/layers/court/layers/SOCCER/layers/PenaltyAreaLayer.js +52 -0
- package/src/models/Play.js +10 -2
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -2,6 +2,8 @@ module.exports = Object.freeze({
|
|
|
2
2
|
SPORT_TYPE_BASKETBALL: 'BASKETBALL',
|
|
3
3
|
SPORT_TYPE_VOLLEYBALL: 'VOLLEYBALL',
|
|
4
4
|
SPORT_TYPE_FOOTBALL: 'FOOTBALL',
|
|
5
|
+
SPORT_TYPE_LACROSSE: 'LACROSSE',
|
|
6
|
+
SPORT_TYPE_SOCCER: 'SOCCER',
|
|
5
7
|
|
|
6
8
|
COURT_TYPE_BIG3: 'BIG3',
|
|
7
9
|
COURT_TYPE_FIBA: 'FIBA',
|
|
@@ -17,6 +19,11 @@ module.exports = Object.freeze({
|
|
|
17
19
|
|
|
18
20
|
COURT_TYPE_INDOOR: 'INDOOR',
|
|
19
21
|
|
|
22
|
+
COURT_TYPE_US_LACROSSE_M: 'US_LACROSSE_M',
|
|
23
|
+
COURT_TYPE_US_LACROSSE_W: 'US_LACROSSE_W',
|
|
24
|
+
|
|
25
|
+
COURT_TYPE_SOCCER_FIFA: 'SOCCER_FIFA',
|
|
26
|
+
|
|
20
27
|
SHAPE_TYPE_CIRCLE: 'CIRCLE',
|
|
21
28
|
SHAPE_TYPE_SQUARE: 'SQUARE',
|
|
22
29
|
SHAPE_TYPE_TRIANGLE: 'TRIANGLE',
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class CenterLineLayer extends InternalCourtLayer {
|
|
4
|
+
drawLogic() {
|
|
5
|
+
const courtOrigin = { x: 0.0, y: this.courtCenter.y };
|
|
6
|
+
const courtTerminus = { x: this.courtTypeConstants.COURT_RECT_WIDTH, y: this.courtCenter.y };
|
|
7
|
+
|
|
8
|
+
this.ctx.beginPath();
|
|
9
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
10
|
+
this.ctx.moveTo(courtOrigin.x, courtOrigin.y);
|
|
11
|
+
this.ctx.lineTo(courtTerminus.x, courtTerminus.y);
|
|
12
|
+
this.ctx.stroke();
|
|
13
|
+
|
|
14
|
+
const xAsRectangle = [
|
|
15
|
+
{ x: this.courtCenter.x - 1, y: this.courtCenter.y - 1 },
|
|
16
|
+
{ x: this.courtCenter.x + 1, y: this.courtCenter.y - 1 },
|
|
17
|
+
{ x: this.courtCenter.x + 1, y: this.courtCenter.y + 1 },
|
|
18
|
+
{ x: this.courtCenter.x - 1, y: this.courtCenter.y + 1 }
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
this.ctx.beginPath();
|
|
22
|
+
|
|
23
|
+
this.ctx.moveTo(xAsRectangle[0].x, xAsRectangle[0].y);
|
|
24
|
+
this.ctx.lineTo(xAsRectangle[2].x, xAsRectangle[2].y);
|
|
25
|
+
|
|
26
|
+
this.ctx.moveTo(xAsRectangle[1].x, xAsRectangle[1].y);
|
|
27
|
+
this.ctx.lineTo(xAsRectangle[3].x, xAsRectangle[3].y);
|
|
28
|
+
|
|
29
|
+
this.ctx.stroke();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = CenterLineLayer;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const GOAL_LINE_WIDTH = 2;
|
|
4
|
+
const GOAL_LINE_OFFSET_Y = 15;
|
|
5
|
+
const GOAL_LINE_RADIUS = 3;
|
|
6
|
+
|
|
7
|
+
class GoalAreaLineLayer extends InternalCourtLayer {
|
|
8
|
+
reflection() {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
drawLogic() {
|
|
13
|
+
const sideLineLeftOrigin = { x: this.courtTypeConstants.WING_OFFSET_X, y: 0 };
|
|
14
|
+
const sideLineLeftTerminus = {
|
|
15
|
+
x: this.courtTypeConstants.WING_OFFSET_X,
|
|
16
|
+
y: this.courtCenter.y - this.courtTypeConstants.RESTRAINING_CENTER_OFFSET_Y
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
this.ctx.beginPath();
|
|
20
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
21
|
+
this.ctx.moveTo(sideLineLeftOrigin.x, sideLineLeftOrigin.y);
|
|
22
|
+
this.ctx.lineTo(sideLineLeftTerminus.x, sideLineLeftTerminus.y);
|
|
23
|
+
this.ctx.stroke();
|
|
24
|
+
|
|
25
|
+
const sideLineRightOrigin = {
|
|
26
|
+
x: this.courtTypeConstants.COURT_RECT_WIDTH - this.courtTypeConstants.WING_OFFSET_X,
|
|
27
|
+
y: 0
|
|
28
|
+
};
|
|
29
|
+
const sideLineRightTerminus = {
|
|
30
|
+
x: this.courtTypeConstants.COURT_RECT_WIDTH - this.courtTypeConstants.WING_OFFSET_X,
|
|
31
|
+
y: this.courtCenter.y - this.courtTypeConstants.RESTRAINING_CENTER_OFFSET_Y
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.ctx.beginPath();
|
|
35
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
36
|
+
this.ctx.moveTo(sideLineRightOrigin.x, sideLineRightOrigin.y);
|
|
37
|
+
this.ctx.lineTo(sideLineRightTerminus.x, sideLineRightTerminus.y);
|
|
38
|
+
this.ctx.stroke();
|
|
39
|
+
|
|
40
|
+
const goalLineCenter = {
|
|
41
|
+
x: this.courtCenter.x,
|
|
42
|
+
y: GOAL_LINE_OFFSET_Y
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
this.ctx.beginPath();
|
|
46
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
47
|
+
this.ctx.moveTo(goalLineCenter.x - GOAL_LINE_WIDTH / 2, goalLineCenter.y);
|
|
48
|
+
this.ctx.lineTo(goalLineCenter.x + GOAL_LINE_WIDTH / 2, goalLineCenter.y);
|
|
49
|
+
this.ctx.stroke();
|
|
50
|
+
|
|
51
|
+
this.ctx.beginPath();
|
|
52
|
+
this.ctx.arc(goalLineCenter.x, goalLineCenter.y, GOAL_LINE_RADIUS, 0, Math.PI * 2, true);
|
|
53
|
+
this.ctx.stroke();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = GoalAreaLineLayer;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const WING_LINE_CENTER_OFFSET_Y = 10;
|
|
4
|
+
|
|
5
|
+
class WingAreaLineLayer extends InternalCourtLayer {
|
|
6
|
+
reflection() {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
drawLogic() {
|
|
11
|
+
const wingLineLeftOrigin = {
|
|
12
|
+
x: this.courtTypeConstants.WING_OFFSET_X,
|
|
13
|
+
y: this.courtCenter.y - WING_LINE_CENTER_OFFSET_Y
|
|
14
|
+
};
|
|
15
|
+
const wingLineLeftTerminus = {
|
|
16
|
+
x: this.courtTypeConstants.WING_OFFSET_X,
|
|
17
|
+
y: this.courtCenter.y
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
this.ctx.beginPath();
|
|
21
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
22
|
+
this.ctx.moveTo(wingLineLeftOrigin.x, wingLineLeftOrigin.y);
|
|
23
|
+
this.ctx.lineTo(wingLineLeftTerminus.x, wingLineLeftTerminus.y);
|
|
24
|
+
this.ctx.stroke();
|
|
25
|
+
|
|
26
|
+
const wingLineRightOrigin = {
|
|
27
|
+
x: this.courtTypeConstants.COURT_RECT_WIDTH - this.courtTypeConstants.WING_OFFSET_X,
|
|
28
|
+
y: this.courtCenter.y - WING_LINE_CENTER_OFFSET_Y
|
|
29
|
+
};
|
|
30
|
+
const wingLineRightTerminus = {
|
|
31
|
+
x: this.courtTypeConstants.COURT_RECT_WIDTH - this.courtTypeConstants.WING_OFFSET_X,
|
|
32
|
+
y: this.courtCenter.y
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
this.ctx.beginPath();
|
|
36
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
37
|
+
this.ctx.moveTo(wingLineRightOrigin.x, wingLineRightOrigin.y);
|
|
38
|
+
this.ctx.lineTo(wingLineRightTerminus.x, wingLineRightTerminus.y);
|
|
39
|
+
this.ctx.stroke();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = WingAreaLineLayer;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const CENTER_DASH_WIDTH = 3;
|
|
4
|
+
const CENTER_CIRCLE_RADIUS = 10;
|
|
5
|
+
|
|
6
|
+
class CenterLineLayer extends InternalCourtLayer {
|
|
7
|
+
drawLogic() {
|
|
8
|
+
const centerDashOrigin = { x: this.courtCenter.x - CENTER_DASH_WIDTH / 2, y: this.courtCenter.y };
|
|
9
|
+
const centerDashTerminus = { x: this.courtCenter.x + CENTER_DASH_WIDTH / 2, y: this.courtCenter.y };
|
|
10
|
+
|
|
11
|
+
this.ctx.beginPath();
|
|
12
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
13
|
+
this.ctx.moveTo(centerDashOrigin.x, centerDashOrigin.y);
|
|
14
|
+
this.ctx.lineTo(centerDashTerminus.x, centerDashTerminus.y);
|
|
15
|
+
this.ctx.stroke();
|
|
16
|
+
|
|
17
|
+
this.ctx.beginPath();
|
|
18
|
+
this.ctx.arc(this.courtCenter.x, this.courtCenter.y, CENTER_CIRCLE_RADIUS, 0, Math.PI * 2, true);
|
|
19
|
+
this.ctx.stroke();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = CenterLineLayer;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const ARC_8M_RADIUS = 11.59;
|
|
4
|
+
const ARC_12M_RADIUS = 15.97;
|
|
5
|
+
const GOAL_CIRCLE_RADIUS = 2.84;
|
|
6
|
+
const GOAL_LINE_RESTRAINING_OFFSET_Y = 30;
|
|
7
|
+
const GOAL_LINE_CIRCLE_HASH_MARK_OFFSET = 8.75;
|
|
8
|
+
const GOAL_LINE_BACK_CIRCLES_OFFSET_Y = 5;
|
|
9
|
+
const GOAL_LINE_BACK_CIRCLES_RADIUS = 0.5;
|
|
10
|
+
const GOAL_LINE_CAGE_LENGTH = 2;
|
|
11
|
+
const HASH_MARK_LENGTH = 1;
|
|
12
|
+
|
|
13
|
+
class CenterLineLayer extends InternalCourtLayer {
|
|
14
|
+
reflection() {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
drawLogic() {
|
|
19
|
+
const goalLineCenter = {
|
|
20
|
+
x: this.courtCenter.x,
|
|
21
|
+
y: this.courtCenter.y - this.courtTypeConstants.RESTRAINING_CENTER_OFFSET_Y - GOAL_LINE_RESTRAINING_OFFSET_Y
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
25
|
+
|
|
26
|
+
// 1. Draw goal circle
|
|
27
|
+
this.ctx.beginPath();
|
|
28
|
+
this.ctx.arc(goalLineCenter.x, goalLineCenter.y, GOAL_CIRCLE_RADIUS, 0, Math.PI * 2, false);
|
|
29
|
+
this.ctx.stroke();
|
|
30
|
+
|
|
31
|
+
// 2. Draw 12 meter arc
|
|
32
|
+
this.ctx.beginPath();
|
|
33
|
+
this.ctx.arc(goalLineCenter.x, goalLineCenter.y, ARC_12M_RADIUS, 0, Math.PI, false);
|
|
34
|
+
this.ctx.stroke();
|
|
35
|
+
|
|
36
|
+
// 3. Draw 12 meter arc semi-circle flat side
|
|
37
|
+
const leftFlatOrigin = { x: goalLineCenter.x - ARC_12M_RADIUS, y: goalLineCenter.y };
|
|
38
|
+
const leftFlatTerminus = { x: goalLineCenter.x - GOAL_CIRCLE_RADIUS, y: goalLineCenter.y };
|
|
39
|
+
const rightFlatOrigin = { x: goalLineCenter.x + ARC_12M_RADIUS, y: goalLineCenter.y };
|
|
40
|
+
const rightFlatTerminus = { x: goalLineCenter.x + GOAL_CIRCLE_RADIUS, y: goalLineCenter.y };
|
|
41
|
+
this.ctx.beginPath();
|
|
42
|
+
this.ctx.moveTo(leftFlatOrigin.x, leftFlatOrigin.y);
|
|
43
|
+
this.ctx.lineTo(leftFlatTerminus.x, leftFlatTerminus.y);
|
|
44
|
+
this.ctx.moveTo(rightFlatOrigin.x, rightFlatOrigin.y);
|
|
45
|
+
this.ctx.lineTo(rightFlatTerminus.x, rightFlatTerminus.y);
|
|
46
|
+
this.ctx.stroke();
|
|
47
|
+
|
|
48
|
+
// 4. Draw 8 meter arc
|
|
49
|
+
const goalCircleBackCenter = { x: goalLineCenter.x, y: goalLineCenter.y - GOAL_CIRCLE_RADIUS };
|
|
50
|
+
const goalCircleBackCenterRadius = ARC_8M_RADIUS + GOAL_CIRCLE_RADIUS;
|
|
51
|
+
const arcStartAngle = Math.PI / 4;
|
|
52
|
+
const arcEndAngle = Math.PI / 2 + Math.PI / 4;
|
|
53
|
+
|
|
54
|
+
this.ctx.beginPath();
|
|
55
|
+
this.ctx.arc(
|
|
56
|
+
goalCircleBackCenter.x,
|
|
57
|
+
goalCircleBackCenter.y,
|
|
58
|
+
goalCircleBackCenterRadius,
|
|
59
|
+
arcStartAngle,
|
|
60
|
+
arcEndAngle,
|
|
61
|
+
false
|
|
62
|
+
);
|
|
63
|
+
this.ctx.stroke();
|
|
64
|
+
|
|
65
|
+
// 5. Connect 8 meter arc edge points with goal circle
|
|
66
|
+
const arcEdgePointLeft = getArcPointForAngle(goalCircleBackCenter, goalCircleBackCenterRadius, arcEndAngle);
|
|
67
|
+
const arcEdgePointRight = getArcPointForAngle(goalCircleBackCenter, goalCircleBackCenterRadius, arcStartAngle);
|
|
68
|
+
|
|
69
|
+
const goalCircleLeftX = goalLineCenter.x - GOAL_CIRCLE_RADIUS;
|
|
70
|
+
const goalCircleRightX = goalLineCenter.x + GOAL_CIRCLE_RADIUS;
|
|
71
|
+
|
|
72
|
+
this.ctx.beginPath();
|
|
73
|
+
this.ctx.moveTo(arcEdgePointLeft.x, arcEdgePointLeft.y);
|
|
74
|
+
this.ctx.lineTo(goalCircleLeftX, goalLineCenter.y);
|
|
75
|
+
this.ctx.stroke();
|
|
76
|
+
|
|
77
|
+
this.ctx.beginPath();
|
|
78
|
+
this.ctx.moveTo(arcEdgePointRight.x, arcEdgePointRight.y);
|
|
79
|
+
this.ctx.lineTo(goalCircleRightX, goalLineCenter.y);
|
|
80
|
+
this.ctx.stroke();
|
|
81
|
+
|
|
82
|
+
// 6. Add 2 additional hash marks on the sides of goal circle
|
|
83
|
+
const hashMarkLeft = { x: goalCircleLeftX - GOAL_LINE_CIRCLE_HASH_MARK_OFFSET, y: goalLineCenter.y };
|
|
84
|
+
const hashMarkRight = { x: goalCircleRightX + GOAL_LINE_CIRCLE_HASH_MARK_OFFSET, y: goalLineCenter.y };
|
|
85
|
+
this.ctx.beginPath();
|
|
86
|
+
this.ctx.moveTo(hashMarkLeft.x, hashMarkLeft.y);
|
|
87
|
+
this.ctx.lineTo(hashMarkLeft.x, hashMarkLeft.y + HASH_MARK_LENGTH);
|
|
88
|
+
this.ctx.stroke();
|
|
89
|
+
|
|
90
|
+
this.ctx.beginPath();
|
|
91
|
+
this.ctx.moveTo(hashMarkRight.x, hashMarkRight.y);
|
|
92
|
+
this.ctx.lineTo(hashMarkRight.x, hashMarkRight.y + HASH_MARK_LENGTH);
|
|
93
|
+
this.ctx.stroke();
|
|
94
|
+
|
|
95
|
+
// 9. Draw hash marks 8 meter arc
|
|
96
|
+
const hashMarkMidPoint = getArcPointForAngle(goalCircleBackCenter, goalCircleBackCenterRadius, Math.PI / 2);
|
|
97
|
+
this.ctx.beginPath();
|
|
98
|
+
this.ctx.moveTo(hashMarkMidPoint.x, hashMarkMidPoint.y - HASH_MARK_LENGTH);
|
|
99
|
+
this.ctx.lineTo(hashMarkMidPoint.x, hashMarkMidPoint.y + HASH_MARK_LENGTH);
|
|
100
|
+
this.ctx.stroke();
|
|
101
|
+
|
|
102
|
+
for (let i = 1; i <= 3; i++) {
|
|
103
|
+
[1, -1].forEach(signChanger => {
|
|
104
|
+
const arcHashAngle = Math.PI / 2 + (Math.PI / 10) * signChanger * i;
|
|
105
|
+
const hashMarkPointForAngle = getArcPointForAngle(
|
|
106
|
+
goalCircleBackCenter,
|
|
107
|
+
goalCircleBackCenterRadius,
|
|
108
|
+
arcHashAngle
|
|
109
|
+
);
|
|
110
|
+
this.ctx.save();
|
|
111
|
+
this.ctx.translate(hashMarkPointForAngle.x, hashMarkPointForAngle.y);
|
|
112
|
+
this.ctx.rotate((Math.PI / 10) * signChanger * i);
|
|
113
|
+
this.ctx.beginPath();
|
|
114
|
+
this.ctx.moveTo(0, -HASH_MARK_LENGTH);
|
|
115
|
+
this.ctx.lineTo(0, HASH_MARK_LENGTH);
|
|
116
|
+
this.ctx.stroke();
|
|
117
|
+
this.ctx.restore();
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 8. Draw goal line back circles
|
|
122
|
+
const goalBackCircleLeft = { x: hashMarkLeft.x, y: hashMarkLeft.y - GOAL_LINE_BACK_CIRCLES_OFFSET_Y };
|
|
123
|
+
const goalBackCircleRight = { x: hashMarkRight.x, y: hashMarkRight.y - GOAL_LINE_BACK_CIRCLES_OFFSET_Y };
|
|
124
|
+
this.ctx.beginPath();
|
|
125
|
+
this.ctx.arc(goalBackCircleLeft.x, goalBackCircleLeft.y, GOAL_LINE_BACK_CIRCLES_RADIUS, 0, Math.PI * 2, false);
|
|
126
|
+
this.ctx.arc(goalBackCircleRight.x, goalBackCircleRight.y, GOAL_LINE_BACK_CIRCLES_RADIUS, 0, Math.PI * 2, false);
|
|
127
|
+
this.ctx.fill();
|
|
128
|
+
|
|
129
|
+
// 9. Draw goal line cage
|
|
130
|
+
const goalCageLeft = { x: goalLineCenter.x - GOAL_LINE_CAGE_LENGTH / 2, y: goalLineCenter.y };
|
|
131
|
+
const goalCageRight = { x: goalLineCenter.x + GOAL_LINE_CAGE_LENGTH / 2, y: goalLineCenter.y };
|
|
132
|
+
const goalCageTop = { x: goalLineCenter.x, y: goalLineCenter.y - GOAL_LINE_CAGE_LENGTH / 2 };
|
|
133
|
+
|
|
134
|
+
this.ctx.beginPath();
|
|
135
|
+
this.ctx.moveTo(goalCageLeft.x, goalCageLeft.y);
|
|
136
|
+
this.ctx.lineTo(goalCageRight.x, goalCageRight.y);
|
|
137
|
+
this.ctx.lineTo(goalCageTop.x, goalCageTop.y);
|
|
138
|
+
this.ctx.closePath();
|
|
139
|
+
this.ctx.stroke();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getArcPointForAngle(c, radius, angle) {
|
|
144
|
+
return { x: c.x + Math.cos(angle) * radius, y: c.y + Math.sin(angle) * radius };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = CenterLineLayer;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class BorderRectLayer extends InternalCourtLayer {
|
|
4
|
+
drawLogic() {
|
|
5
|
+
this.ctx.beginPath();
|
|
6
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
7
|
+
this.ctx.rect(0, 0, this.courtTypeConstants.COURT_RECT_WIDTH, this.courtTypeConstants.COURT_RECT_HEIGHT);
|
|
8
|
+
this.ctx.stroke();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = BorderRectLayer;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class RestrainingLineLayer extends InternalCourtLayer {
|
|
4
|
+
reflection() {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
drawLogic() {
|
|
9
|
+
const courtOrigin = { x: 0.0, y: this.courtCenter.y - this.courtTypeConstants.RESTRAINING_CENTER_OFFSET_Y };
|
|
10
|
+
const courtTerminus = {
|
|
11
|
+
x: this.courtTypeConstants.COURT_RECT_WIDTH,
|
|
12
|
+
y: this.courtCenter.y - this.courtTypeConstants.RESTRAINING_CENTER_OFFSET_Y
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
this.ctx.beginPath();
|
|
16
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
17
|
+
this.ctx.moveTo(courtOrigin.x, courtOrigin.y);
|
|
18
|
+
this.ctx.lineTo(courtTerminus.x, courtTerminus.y);
|
|
19
|
+
this.ctx.stroke();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = RestrainingLineLayer;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class BorderRectLayer extends InternalCourtLayer {
|
|
4
|
+
drawLogic() {
|
|
5
|
+
this.ctx.beginPath();
|
|
6
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
7
|
+
this.ctx.rect(0, 0, this.courtTypeConstants.COURT_RECT_WIDTH, this.courtTypeConstants.COURT_RECT_HEIGHT);
|
|
8
|
+
this.ctx.stroke();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = BorderRectLayer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class CenterCircleLayer extends InternalCourtLayer {
|
|
4
|
+
drawLogic() {
|
|
5
|
+
const circleOuterRadius = 10.0;
|
|
6
|
+
const circleInnerRadius = 0.5;
|
|
7
|
+
|
|
8
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
9
|
+
|
|
10
|
+
this.ctx.beginPath();
|
|
11
|
+
this.ctx.arc(this.courtCenter.x, this.courtCenter.y, circleOuterRadius, 0, Math.PI * 2, true);
|
|
12
|
+
this.ctx.stroke();
|
|
13
|
+
|
|
14
|
+
this.ctx.beginPath();
|
|
15
|
+
this.ctx.arc(this.courtCenter.x, this.courtCenter.y, circleInnerRadius, 0, Math.PI * 2, true);
|
|
16
|
+
this.ctx.fill();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = CenterCircleLayer;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
class CenterLineLayer extends InternalCourtLayer {
|
|
4
|
+
drawLogic() {
|
|
5
|
+
const courtOrigin = { x: 0.0, y: this.courtCenter.y };
|
|
6
|
+
const courtTerminus = { x: this.courtTypeConstants.COURT_RECT_WIDTH, y: this.courtCenter.y };
|
|
7
|
+
|
|
8
|
+
this.ctx.beginPath();
|
|
9
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
10
|
+
this.ctx.moveTo(courtOrigin.x, courtOrigin.y);
|
|
11
|
+
this.ctx.lineTo(courtTerminus.x, courtTerminus.y);
|
|
12
|
+
this.ctx.stroke();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = CenterLineLayer;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const CORNER_RADIUS = 1;
|
|
4
|
+
class CornerLayer extends InternalCourtLayer {
|
|
5
|
+
reflection() {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
drawLogic() {
|
|
10
|
+
const leftCorner = { x: 0, y: 0 };
|
|
11
|
+
const rightCorner = { x: this.courtTypeConstants.COURT_RECT_WIDTH, y: 0 };
|
|
12
|
+
|
|
13
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
14
|
+
|
|
15
|
+
this.ctx.beginPath();
|
|
16
|
+
this.ctx.arc(leftCorner.x, leftCorner.y, CORNER_RADIUS, 0, Math.PI / 2, false);
|
|
17
|
+
this.ctx.stroke();
|
|
18
|
+
|
|
19
|
+
this.ctx.beginPath();
|
|
20
|
+
this.ctx.arc(rightCorner.x, rightCorner.y, CORNER_RADIUS, Math.PI, Math.PI / 2, true);
|
|
21
|
+
this.ctx.stroke();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = CornerLayer;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const InternalCourtLayer = require('../../../base/InternalCourtLayer');
|
|
2
|
+
|
|
3
|
+
const GOAL = { width: 8, height: 2.66 };
|
|
4
|
+
const GOAL_AREA = { width: 20, height: 6 };
|
|
5
|
+
const PENALTY_AREA = { width: 44, height: 18 };
|
|
6
|
+
const PENALTY_SPOT_OFFSET_Y = 12;
|
|
7
|
+
const PENALTY_SPOT_RADIUS = 0.5;
|
|
8
|
+
const PENALTY_ARC_RADIUS = 10;
|
|
9
|
+
|
|
10
|
+
class PenaltyAreaLayer extends InternalCourtLayer {
|
|
11
|
+
reflection() {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
drawLogic() {
|
|
16
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH * 2;
|
|
17
|
+
|
|
18
|
+
// 1. Draw penalty area rect
|
|
19
|
+
this.ctx.beginPath();
|
|
20
|
+
this.ctx.rect(this.courtCenter.x - PENALTY_AREA.width / 2, 0, PENALTY_AREA.width, PENALTY_AREA.height);
|
|
21
|
+
this.ctx.stroke();
|
|
22
|
+
|
|
23
|
+
// 2. Draw penalty spot
|
|
24
|
+
this.ctx.beginPath();
|
|
25
|
+
this.ctx.arc(this.courtCenter.x, PENALTY_SPOT_OFFSET_Y, PENALTY_SPOT_RADIUS, 0, Math.PI * 2, false);
|
|
26
|
+
this.ctx.fill();
|
|
27
|
+
|
|
28
|
+
// 3. Draw penalty area arc
|
|
29
|
+
this.ctx.beginPath();
|
|
30
|
+
this.ctx.arc(
|
|
31
|
+
this.courtCenter.x,
|
|
32
|
+
PENALTY_SPOT_OFFSET_Y,
|
|
33
|
+
PENALTY_ARC_RADIUS,
|
|
34
|
+
Math.PI / 5,
|
|
35
|
+
Math.PI - Math.PI / 5,
|
|
36
|
+
false
|
|
37
|
+
);
|
|
38
|
+
this.ctx.stroke();
|
|
39
|
+
|
|
40
|
+
// 4. Draw goal area rect
|
|
41
|
+
this.ctx.beginPath();
|
|
42
|
+
this.ctx.rect(this.courtCenter.x - GOAL_AREA.width / 2, 0, GOAL_AREA.width, GOAL_AREA.height);
|
|
43
|
+
this.ctx.stroke();
|
|
44
|
+
|
|
45
|
+
// 5. Draw goal rect
|
|
46
|
+
this.ctx.beginPath();
|
|
47
|
+
this.ctx.rect(this.courtCenter.x - GOAL.width / 2, -GOAL.height, GOAL.width, GOAL.height);
|
|
48
|
+
this.ctx.stroke();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = PenaltyAreaLayer;
|
package/src/models/Play.js
CHANGED
|
@@ -3,7 +3,13 @@ const { loadImage } = require('canvas');
|
|
|
3
3
|
const playerHatsConfig = require('../playerHatsConfig');
|
|
4
4
|
const shapesConfig = require('../shapesConfig');
|
|
5
5
|
const { useDefaults } = require('./Play/Options');
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
SPORT_TYPE_BASKETBALL,
|
|
8
|
+
SPORT_TYPE_VOLLEYBALL,
|
|
9
|
+
SPORT_TYPE_FOOTBALL,
|
|
10
|
+
SPORT_TYPE_LACROSSE,
|
|
11
|
+
SPORT_TYPE_SOCCER
|
|
12
|
+
} = require('../constants');
|
|
7
13
|
|
|
8
14
|
const STORAGE_URL = 'https://playbooksstore.blob.core.windows.net/public';
|
|
9
15
|
const LUCEOSPORTS_WATERMARK_PATH = 'partners/LuceoSports/luceo-sports-logo-powered-by-sm.png';
|
|
@@ -28,7 +34,9 @@ class Play {
|
|
|
28
34
|
Hardwood: hardwoodImage,
|
|
29
35
|
[SPORT_TYPE_BASKETBALL]: hardwoodImage,
|
|
30
36
|
[SPORT_TYPE_VOLLEYBALL]: hardwoodImage,
|
|
31
|
-
[SPORT_TYPE_FOOTBALL]: grassImage
|
|
37
|
+
[SPORT_TYPE_FOOTBALL]: grassImage,
|
|
38
|
+
[SPORT_TYPE_LACROSSE]: grassImage,
|
|
39
|
+
[SPORT_TYPE_SOCCER]: grassImage
|
|
32
40
|
};
|
|
33
41
|
|
|
34
42
|
const luceoSportsWatermark = await loadImage(`${STORAGE_URL}/${LUCEOSPORTS_WATERMARK_PATH}`);
|