cards/CardMap.cs
using Sandbox;
using System.Threading.Tasks;
public class CardMap : Card
{
public override bool ValidateStartingGridPos()
{
var maps = Manager.Instance.Cards.Where( x => x.CardType == CardType.Map ).ToList();
var map0 = maps[0];
var map1 = maps[1];
int farthestDist = GetFarthestDistance( map0, map1 );
if ( maps.Count < 2 || farthestDist > 3 )
return true;
int NUM_TRIES = 100;
for ( int i = 0; i < NUM_TRIES; i++ )
{
var newGridPos = Manager.Instance.GetRandomGridPos( except: map0.GridPos );
var otherCard = Manager.Instance.GetCardAtGridPos( newGridPos );
if ( GetFarthestDistance( otherCard, map1 ) > 3 && otherCard.CardType != CardType.Map )
{
Manager.Instance.SwapCardPositionsNonAsync( map0, otherCard );
break;
}
}
if ( !Manager.IsNearby( map0.GridPos, map1.GridPos ) )
return true;
NUM_TRIES = 100;
for ( int i = 0; i < NUM_TRIES; i++ )
{
var newGridPos = Manager.Instance.GetRandomGridPos( except: map0.GridPos );
var otherCard = Manager.Instance.GetCardAtGridPos( newGridPos );
if ( !Manager.IsNearby( newGridPos, map1.GridPos ) && otherCard.CardType != CardType.Map )
{
Manager.Instance.SwapCardPositionsNonAsync( map0, otherCard );
break;
}
}
return false;
}
int GetFarthestDistance(Card card0, Card card1)
{
return Math.Max(Math.Abs( card0.GridPos.x - card1.GridPos.x ), Math.Abs( card0.GridPos.y - card1.GridPos.y ));
}
public override bool ShouldHandleEvent( EventType eventType )
{
return eventType == EventType.Match && Manager.Instance.ChosenCards[0] == this;
}
public override async Task HandleEventAsync( EventType eventType )
{
var mapPos0 = Manager.Instance.ChosenCards[0].GridPos;
var mapPos1 = Manager.Instance.ChosenCards[1].GridPos;
var linePositions = GetLine( mapPos0.x, mapPos0.y, mapPos1.x, mapPos1.y );
List<Card> lineCards = new();
foreach(var linePos in linePositions)
{
var card = Manager.Instance.GetCardAtGridPos( linePos );
if ( card != null && !Manager.Instance.ChosenCards.Contains( card ) )
lineCards.Add( card );
}
if ( lineCards.Count == 0 )
return;
Manager.Instance.PushEventMessage( this, eventType );
await Task.DelayRealtime( 50 );
Manager.Instance.PlayCardSfxBetween( "map_open", this, Manager.Instance.ChosenCards[1], volume: 1.5f, pitch: Game.Random.Float(0.95f, 1.1f) );
await Task.DelayRealtime( 500 );
foreach(var card in lineCards)
{
Manager.Instance.PlayCardSfx( "card_flip", card, volume: 0.8f, pitch: Game.Random.Float( 1.15f, 1.2f ) );
await Manager.Instance.RevealCard( card );
await Task.DelayRealtime( 200 );
}
await Task.DelayRealtime( 1400 );
Manager.Instance.PlayCardSfxBetween( "map_close", this, Manager.Instance.ChosenCards[1], volume: 1.4f, pitch: Game.Random.Float( 0.95f, 1.1f ) );
await Task.DelayRealtime( 500 );
foreach ( var card in lineCards )
{
Manager.Instance.HideCard( card );
Manager.Instance.PlayCardSfx( "card_flip", card, volume: 0.7f, pitch: Game.Random.Float( 0.65f, 0.75f ) );
await Task.DelayRealtime( 150 );
}
await Task.DelayRealtime( 300 );
Manager.Instance.PopEventMessage();
}
List<IntVector2> GetLine( int x0, int y0, int x1, int y1 )
{
List<IntVector2> points = new List<IntVector2>();
int dx = Math.Abs( x1 - x0 );
int dy = Math.Abs( y1 - y0 );
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
while ( true )
{
points.Add( new IntVector2( x0, y0 ) );
if ( x0 == x1 && y0 == y1 )
break;
int e2 = 2 * err;
if ( e2 > -dy )
{
err -= dy;
x0 += sx;
}
if ( e2 < dx )
{
err += dx;
y0 += sy;
}
}
return points;
}
}