Partial class for FootballWorldPanel that animates the goal net. It tracks ball impacts and replay crossing data, then fills a 2 by 6 by 10 grid of net offsets from FootballNetMotion.Displacement so the panel can draw a deformed net.
using Sandbox;
using Socer;
using System;
public sealed partial class FootballWorldPanel
{
const int NetRows=6,NetColumns=10;
readonly float[,,] netOffset=new float[2,NetRows,NetColumns];
MatchSimulation netMatch;
int netGoals;
Point netImpact;
float netImpactHeight,netImpactSpeed,netImpactAt=-100;
public float GoalNetPeakDisplacement
{
get
{
float peak=0;
foreach(float value in netOffset)peak=Math.Max(peak,Math.Abs(value));
return peak;
}
}
Point NetPoint(int side,int row,int column)
{
float rear=side==0?-2.4f:107.4f;
float y=PitchPerspective.PostLeft+(PitchPerspective.PostRight-PitchPerspective.PostLeft)*column/(NetColumns-1);
return new Point(rear+(side==0?-1:1)*netOffset[side,row,column],y);
}
float NetHeight(int row)=>PitchPerspective.CrossbarCentre*row/(NetRows-1);
void UpdateGoalNets(MatchSimulation match)
{
InitializeGoalStrokes();
int goals=match.Goals[0]+match.Goals[1]+match.ShootoutScores[0]+match.ShootoutScores[1];
if(netMatch!=match)
{
netMatch=match;netGoals=Math.Max(0,goals-(match.GoalHoldRemaining>0?1:0));
netImpactAt=-100;netImpactSpeed=0;
}
if(goals>netGoals)
{
netImpact=match.Ball;netImpactHeight=match.BallHeight;
netImpactSpeed=match.BallSpeed/.58f;netImpactAt=match.Seconds;
}
netGoals=goals;
float age=match.GoalHoldRemaining>0?match.GoalCelebrationElapsed:match.Seconds-netImpactAt;
var replay=Game.Replay;
// Capture the crossing before the ball settles. Replay time continues
// after the football clock freezes for the team gathering.
if(replay.Playing || (match.GoalHoldRemaining>0 && replay.ScorerId==match.GoalScorerId && replay.GoalImpactSpeed>0))
{
netImpact=replay.GoalImpactPoint;netImpactHeight=replay.GoalImpactHeight;netImpactSpeed=replay.GoalImpactSpeed;
if(replay.Playing)age=replay.PlaybackTime-replay.GoalTime;
}
Array.Clear(netOffset);
if(!replay.Playing && match.GoalHoldRemaining>0 && age>=FootballNetMotion.Duration)netImpactSpeed=0;
if(age<=0 || age>=FootballNetMotion.Duration || netImpactSpeed<=0)return;
int side=netImpact.X<52.5f?0:1;
for(int row=1;row<NetRows-1;row++)for(int column=1;column<NetColumns-1;column++)
{
float y=PitchPerspective.PostLeft+(PitchPerspective.PostRight-PitchPerspective.PostLeft)*column/(NetColumns-1);
netOffset[side,row,column]=FootballNetMotion.Displacement(y,NetHeight(row),netImpact.Y,netImpactHeight,age,netImpactSpeed);
}
}
}