Private/Falling.ps1
using module .\Common.psm1 class Falling { static $characters = $null static $startLine = 0 static $windowHeight = 0 static $kStartLineVelocity = 0.2 static $kStartTime = [RandomDouble]::new(0.0, 0.1) static $kMass = [RandomDouble]::new(1.0, 6.0) static $kColorAnimDuration = [RandomDouble]::new(0.8, 1.2) static $kColorAnimStartTime = 0.6 static $kGravity = 9.8 static $kDragCoef = 10.0 static $kMeterToCellRatio = 20 static [void] Init([System.Management.Automation.Host.BufferCell[,]]$windowBuffer) { [Falling]::windowHeight = $windowBuffer.GetUpperBound(0) [Falling]::characters = CreateCharacters ([FallingCharacter]) $windowBuffer $maxY = 0 foreach ($character in [Falling]::characters) { $maxY = [Math]::Max($character.y, $maxY) } [Falling]::startLine = $maxY } static [void] Term() { [Falling]::characters = $null } static [Boolean] Render([System.Management.Automation.Host.BufferCell[,]]$windowBuffer, [Double]$dt, [Double]$speed) { [Falling]::startLine -= [Falling]::kMeterToCellRatio * [Falling]::kStartLineVelocity * $speed * $dt foreach ($character in [Falling]::characters) { if ($character.y -gt [Falling]::startLine) { $character.Start() } $character.Update($speed * $dt) } $isAllFinished = $true foreach ($character in [Falling]::characters) { if (-not $character.isFinished) { $isAllFinished = $false break } } if ($isAllFinished) { return $true } foreach ($character in [Falling]::characters) { $character.Render($windowBuffer) } return $false } } class FallingCharacter : RenderItem { $velocity = 0.0 $mass = 1.0 $startTime = 0 $timer = 0 $colorAnimation = $null $colorAnimStartTime = 0 $isStarted = $false FallingCharacter($cell, $cellTrailing, $x, $y) : base($cell, $cellTrailing, $x, $y) { $this.startTime = [Falling]::kStartTime.Get() $this.mass = [Falling]::kMass.Get() $colorAnimDuration = [Falling]::kColorAnimDuration.Get() $this.colorAnimation = [LinearAnimation]::new(@( [System.ConsoleColor]::Blue, [System.ConsoleColor]::Blue, [System.ConsoleColor]::Blue, [System.ConsoleColor]::DarkBlue, [System.ConsoleColor]::Green ), $colorAnimDuration) $this.colorAnimStartTime = $this.startTime + [Falling]::kColorAnimStartTime } [void] Start() { $this.isStarted = $true } [void] Update($dt) { if (-not $this.isStarted) { return } if ($this.isFinished) { return } $this.timer += $dt if ($this.timer -lt $this.startTime) { return } $a = [Falling]::kGravity - ([Falling]::kDragCoef * $this.velocity / $this.mass) $this.velocity += $a * $dt $this.y += [Falling]::kMeterToCellRatio * $this.velocity * $dt if ($this.y -ge [Falling]::windowHeight) { $this.Finish() } if ($this.timer -gt $this.colorAnimStartTime) { $this.colorAnimation.Update($dt) $color = $this.colorAnimation.GetValue() $this.SetCell($null, $color, $null) } } } |