using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using SnailQuest.Controls;
using System.Windows.Media.Animation;
namespace SnailQuest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
const int mazeWidth = 15;
const int mazeHeight = 10;
const int cellWidth = 60;
int animationMs = 300;
List<Glass> glassList = new List<Glass>();
char[,] mazeValues = new char[mazeWidth, mazeHeight];
Glass[,] mazeGlasses = new Glass[mazeWidth, mazeHeight];
List<Squid> squids = new List<Squid>();
List<Starfish> starfishes = new List<Starfish>();
List<Pearl> pearls = new List<Pearl>();
Stack<Starfish> collectedStarfishes = new Stack<Starfish>();
Stack<Pearl> collectedPearls = new Stack<Pearl>();
bool movementHalted = true;
Snail snail = null;
MidiHelper midiHelper = null;
IrrKlang.ISoundEngine irrKlangEngine;
IrrKlang.ISound currentlyPlayingSound;
int score = 0;
int lives = 0;
int level = 1;
public MainWindow()
{
InitializeComponent();
AddLive();
AddLive();
AddLive();
irrKlangEngine = new IrrKlang.ISoundEngine();
snail = new Snail()
{
MazeValues = mazeValues
};
squids.Add(new Squid() { Color = new SolidColorBrush(Colors.Red), MazeValues = mazeValues });
squids.Add(new Squid() { Color = new SolidColorBrush(Colors.Orange), MazeValues = mazeValues });
squids.Add(new Squid() { Color = new SolidColorBrush(Colors.White), MazeValues = mazeValues });
squids.Add(new Squid() { Color = new SolidColorBrush(Colors.Blue), MazeValues = mazeValues });
foreach (var squid in squids)
{
cnvMain.Children.Add(squid);
}
cnvMain.Children.Add(snail);
CreateMazeGrid();
LoadMaze(1);
//LoadMaze(2);
ResetPositions();
var osSquidMovementTick = Observable.ObserveOnDispatcher(
Observable.Interval(TimeSpan.FromMilliseconds(animationMs / 1.0))
);
osSquidMovementTick.Subscribe(e =>
{
if (!movementHalted)
{
var xSnail = (int)((double)snail.GetValue(Canvas.LeftProperty) / cellWidth);
var ySnail = (int)((double)snail.GetValue(Canvas.TopProperty) / cellWidth);
foreach (var squid in squids)
{
if (!squid.IsDying)
{
squid.ChaseSnail(new Point(xSnail, ySnail));
squid.TryProcessNextAnimation();
}
}
//TestCollisions();
}
}
);
var osCollisionTestTick = Observable.ObserveOnDispatcher(
Observable.Interval(TimeSpan.FromMilliseconds(animationMs / 1.0))
);
osCollisionTestTick.Subscribe(e =>
{
TestCollisions();
}
);
midiHelper = new MidiHelper();
midiHelper.Load("km_stage1", @"Midis\km_stage1.mid");
midiHelper.Load("km_stage2", @"Midis\km_stage2.mid");
midiHelper.Load("km_gameover", @"Midis\km_gameover.mid");
midiHelper.Load("km_start", @"Midis\km_start.mid");
midiHelper.Load("km_crystal", @"Midis\km_crystal.mid");
midiHelper.Load("km_ending", @"Midis\km_ending.mid");
}
private void TestCollisions()
{
var snailCellPoint = snail.GetCellPoint();
bool collided = false;
var rectSnail = snail.GetRect(cnvMain);
foreach (var squid in squids)
{
if (!squid.IsDying)
{
var rectSquid = squid.GetRect(cnvMain);
var snailPoint = snail.GetCellPoint();
var squidPoint = squid.GetCellPoint();
if (!snail.IsDying)
{
if (rectSnail.IntersectsWith(rectSquid))
{
squid.IsDying =
collided = true;
break;
}
}
foreach (var starfish in starfishes)
{
if (starfish.IsMoving)
{
var starfishPoint = starfish.GetCellPoint();
var x1 = (starfishPoint.X < snailPoint.X) ? starfishPoint.X : snailPoint.X;
var x2 = (starfishPoint.X > snailPoint.X) ? starfishPoint.X : snailPoint.X;
var y1 = (starfishPoint.Y < snailPoint.Y) ? starfishPoint.Y : snailPoint.Y;
var y2 = (starfishPoint.Y > snailPoint.Y) ? starfishPoint.Y : snailPoint.Y;
if ((x1 <= squidPoint.X && squidPoint.X <= x2 && starfishPoint.Y == squidPoint.Y) ||
(y1 <= squidPoint.Y && squidPoint.Y <= y2 && starfishPoint.X == squidPoint.X))
{
AddScore(10);
irrKlangEngine.Play2D(@"Sounds\bulle.wav", false);
squid.Die(() =>
{
squid.Born(() =>
{
squid.ResetAnimations();
squid.IsDying = false;
});
}
);
break;
}
}
}
}
}
bool gotStarfish = false;
foreach (var starfish in starfishes)
{
if (starfish.Visibility == System.Windows.Visibility.Visible)
{
var rectStarfish = starfish.GetRect(cnvMain);
var starfishCellPoint = starfish.GetCellPoint();
if (rectSnail.IntersectsWith(rectStarfish))
{
irrKlangEngine.Play2D(@"Sounds\Reload.wav");
gotStarfish = true;
starfish.Visibility = System.Windows.Visibility.Hidden;
AddStarfish(starfish);
mazeValues[(int)starfishCellPoint.X, (int)starfishCellPoint.Y] = ' ';
break;
}
if (starfish.IsMoving)
{
foreach (var squid in squids)
{
var rectSquid = squid.GetRect(cnvMain);
if (rectStarfish.IntersectsWith(rectSquid))
{
AddScore(10);
irrKlangEngine.Play2D(@"Sounds\bulle.wav", false);
squid.Die(() =>
{
squid.ResetAnimations();
squid.Born(() =>
{
squid.ResetAnimations();
squid.IsDying = false;
});
}
);
break;
}
}
}
}
}
foreach (var pearl in pearls)
{
if (pearl.Visibility == System.Windows.Visibility.Visible)
{
var rectPearl = pearl.GetRect(cnvMain);
var pearlCellPoint = pearl.GetCellPoint();
if (rectSnail.IntersectsWith(rectPearl))
{
AddScore(100);
midiHelper.Play("km_crystal", null);
AddPearl(pearl);
pearl.Visibility = System.Windows.Visibility.Hidden;
mazeValues[(int)pearlCellPoint.X, (int)pearlCellPoint.Y] = ' ';
break;
}
}
}
if (collided)
{
collided = false;
movementHalted = true;
foreach (var squid in squids)
{
squid.ResetAnimations();
}
midiHelper.StopAll();
currentlyPlayingSound = irrKlangEngine.Play2D(@"Sounds\quit.wav", false);
RemoveLive();
}
}
private void PlayStage1Music()
{
midiHelper.Play("km_stage1",
() =>
{
midiHelper.Play("km_stage2",
() =>
{
midiHelper.Play("km_stage1",
() =>
{
});
});
});
}
private void PlayStage2Music()
{
midiHelper.Play("km_stage2",
() =>
{
midiHelper.Play("km_stage1",
() =>
{
midiHelper.Play("km_stage2",
() =>
{
});
});
});
}
private void ResetPositions()
{
snail.Born(null);
snail.IsDying = false;
for (var i = 0; i < squids.Count(); i++)
{
var squid = squids[i];
squid.Born(() =>
{
squid.ClearAnimationQueue();
squid.MovementHalted = false;
});
squid.IsDying = false;
}
}
private void EnableMovement(int index)
{
}
private void CreateMazeGrid()
{
for (var c = 0; c < mazeWidth; c++)
{
grdMaze.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(cellWidth) });
}
for (var l = 0; l < mazeHeight; l++)
{
grdMaze.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(cellWidth) });
}
}
private void LoadMaze(int level)
{
collectedPearls.Clear();
collectedStarfishes.Clear();
grdMaze.Children.Clear();
for (var i = 0; i < starfishes.Count(); i++)
{
cnvMain.Children.Remove(starfishes[i]);
}
starfishes.Clear();
for (var i = 0; i < pearls.Count(); i++)
{
cnvMain.Children.Remove(pearls[i]);
}
pearls.Clear();
for (var i = 0; i < mazeGlasses.GetLength(0); i++)
{
for (var j = 0; j < mazeGlasses.GetLength(1); j++)
{
mazeGlasses[i, j] = null;
}
}
for (var i = 0; i < mazeValues.GetLength(0); i++)
{
for (var j = 0; j < mazeValues.GetLength(1); j++)
{
mazeValues[i, j] = ' ';
}
}
var fileName = string.Format(@"Mazes\Level{0}.txt", level);
using (var sr = new StreamReader(fileName))
{
var l = 0;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
for (var c = 0; c < line.Length; c++)
{
mazeValues[c, l] = line[c];
if (mazeValues[c, l] == '1')
{
var glass = new Glass();
glass.SetValue(Grid.ColumnProperty, c);
glass.SetValue(Grid.RowProperty, l);
grdMaze.Children.Add(glass);
mazeGlasses[c, l] = glass;
}
else if (mazeValues[c, l] == '*')
{
var starfish = new Starfish();
starfish.SetValue(Canvas.LeftProperty, 0.0);
starfish.SetValue(Canvas.TopProperty, 0.0);
starfish.SetValue(Canvas.ZIndexProperty, -1);
cnvMain.Children.Add(starfish);
starfish.Throw(new Point(c, l), new Point(c, l), TimeSpan.FromMilliseconds(50), null);
starfishes.Add(starfish);
}
else if (mazeValues[c, l] == 'o')
{
var pearl = new Pearl()
{
Width = 30,
Height = 30
};
pearl.SetValue(Canvas.LeftProperty, 0.0);
pearl.SetValue(Canvas.TopProperty, 0.0);
pearl.SetValue(Canvas.ZIndexProperty, -1);
cnvMain.Children.Add(pearl);
pearl.PlaceAt(new Point(c, l));
pearls.Add(pearl);
}
else if (mazeValues[c, l] == 'S')
{
snail.OriginalCellPoint = new Point(c, l);
}
else if ("ABCD".Contains(mazeValues[c, l]))
{
var index = "ABCD".IndexOf(mazeValues[c, l]);
squids[index].OriginalCellPoint = new Point(c, l);
}
}
l++;
}
}
for (var c = 0; c < mazeWidth; c++)
{
for (var l = 0; l < mazeHeight; l++)
{
var topValue = ' ';
var bottomValue = ' ';
var leftValue = ' ';
var rightValue = ' ';
if (l > 0)
topValue = mazeValues[c, l - 1];
if (l < mazeHeight - 1)
bottomValue = mazeValues[c, l + 1];
if (c > 0)
leftValue = mazeValues[c - 1, l];
if (c < mazeWidth - 1)
rightValue = mazeValues[c + 1, l];
var glass = mazeGlasses[c, l];
if (glass != null)
{
glass.LeftValue = leftValue;
glass.RightValue = rightValue;
glass.TopValue = topValue;
glass.BottomValue = bottomValue;
}
}
}
}
private void AddScore(int points)
{
score += points;
txtScore1.Text =
txtScore2.Text = score.ToString("00000");
}
private void AddStarfish(Starfish starfish)
{
cnvMain.Children.Remove(starfish);
collectedStarfishes.Push(starfish);
txtStarfishes2.Text = string.Format("x{0}", collectedStarfishes.Count());
}
private Starfish RemoveStarfish()
{
var starfish = collectedStarfishes.Pop();
txtStarfishes2.Text = string.Format("x{0}", collectedStarfishes.Count());
cnvMain.Children.Add(starfish);
return starfish;
}
private void AddPearl(Pearl pearl)
{
cnvMain.Children.Remove(pearl);
collectedPearls.Push(pearl);
txtPearls2.Text = string.Format("x{0}", collectedPearls.Count());
if (collectedPearls.Count() == pearls.Count())
{
GoNextLevel();
}
}
private Pearl RemovePearl()
{
stkPearl.Children.RemoveAt(0);
var pearl = collectedPearls.Pop();
cnvMain.Children.Add(pearl);
return pearl;
}
private void AddLive()
{
lives++;
txtLives2.Text = string.Format("x{0}", lives);
}
private void RemoveLive()
{
if (lives == 0)
{
snail.Die(ResetPositions);
snail.ResetAnimations();
gameOverScreen.Text = "Game Over";
Storyboard sbGameOver = this.FindResource("sbGameOver") as Storyboard;
sbGameOver.Begin();
midiHelper.Play("km_gameover",
() =>
{
this.Dispatcher.Invoke((Action)delegate
{
LoadMaze(level);
AddLive();
AddLive();
AddLive();
Storyboard sbSplashScreen = this.FindResource("sbSplashScreen") as Storyboard;
sbSplashScreen.Begin();
});
});
}
else
{
lives--;
txtLives2.Text = string.Format("x{0}", lives);
snail.Die(ResetPositions);
snail.ResetAnimations();
var osWaitBeforeReborn = Observable.Interval(TimeSpan.FromMilliseconds(3000)).Take(1);
osWaitBeforeReborn.Subscribe(e =>
{
PlayStage1Music();
movementHalted = false;
}
);
}
}
private void GoNextLevel()
{
movementHalted = true;
midiHelper.StopAll();
var fileName = string.Format(@"Mazes\Level{0}.txt", level + 1);
if (!File.Exists(fileName))
{
midiHelper.StopAll();
gameOverScreen.Text = "Congratulations!";
Storyboard sbGameOver = this.FindResource("sbGameOver") as Storyboard;
sbGameOver.Begin();
midiHelper.Play("km_ending",
() =>
{
this.Dispatcher.Invoke((Action)delegate
{
Storyboard sbSplashScreen = this.FindResource("sbSplashScreen") as Storyboard;
sbSplashScreen.Begin();
});
});
}
else
{
irrKlangEngine.Play2D(@"Sounds\bjp.wav", false);
AddScore(200);
var osWaitBeforeNextLevel = Observable.Interval(TimeSpan.FromMilliseconds(3000)).Take(1);
osWaitBeforeNextLevel.Subscribe(e =>
{
this.Dispatcher.Invoke((Action)delegate
{
level++;
LoadMaze(level);
ResetPositions();
levelScreen.LevelNumber = level;
Storyboard sbLevel = this.FindResource("sbLevel") as Storyboard;
sbLevel.Begin();
midiHelper.Play("km_start",
() =>
{
movementHalted = false;
PlayStage2Music();
});
});
});
}
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
var deltaX = 0;
var deltaY = 0;
var spacePressed = false;
switch (e.Key)
{
case Key.Right:
deltaX = 1;
break;
case Key.Left:
deltaX = -1;
break;
case Key.Up:
deltaY = -1;
break;
case Key.Down:
deltaY = 1;
break;
case Key.Space:
spacePressed = true;
break;
}
if (spacePressed)
{
if (splashScreen.Opacity == 1.0)
{
levelScreen.LevelNumber = level;
Storyboard sbStart = this.FindResource("sbStart") as Storyboard;
sbStart.Begin();
Storyboard sbLevel = this.FindResource("sbLevel") as Storyboard;
sbLevel.Begin();
midiHelper.StopAll();
midiHelper.Play("km_start",
() =>
{
movementHalted = false;
PlayStage1Music();
});
}
else
{
if (collectedStarfishes.Count() > 0)
{
var starfishPoint1 = snail.GetCellPoint();
var starfish = RemoveStarfish();
var xDirection = 0;
var yDirection = 0;
switch (snail.SnailDirection)
{
case SnailDirection.Right:
xDirection = 1;
yDirection = 0;
break;
case SnailDirection.Left:
xDirection = -1;
yDirection = 0;
break;
case SnailDirection.Down:
xDirection = 0;
yDirection = 1;
break;
case SnailDirection.Up:
xDirection = 0;
yDirection = -1;
break;
}
var targetX = (int)starfishPoint1.X;
var targetY = (int)starfishPoint1.Y;
var starfishPoint2 = new Point(targetX, targetY);
var length = 0;
for (var i = 1; i <= 3; i++)
{
targetX = (int)starfishPoint1.X + i * xDirection;
targetY = (int)starfishPoint1.Y + i * yDirection;
if (targetX >= 0 && targetX < mazeWidth &&
targetY >= 0 && targetY < mazeHeight)
{
if (mazeValues[targetX, targetY] == '1')
{
break;
}
else
{
starfishPoint2 = new Point(targetX, targetY);
length = i;
}
}
}
irrKlangEngine.Play2D(@"Sounds\boomerang.wav");
starfish.Throw(starfishPoint1, starfishPoint2, TimeSpan.FromMilliseconds((animationMs / 3.0) * length),
() =>
{
var starfishPoint = starfish.GetCellPoint();
foreach (var squid in squids)
{
var squidPoint = squid.GetCellPoint();
var x1 = (starfishPoint1.X < starfishPoint2.X) ? starfishPoint1.X : starfishPoint2.X;
var x2 = (starfishPoint1.X < starfishPoint2.X) ? starfishPoint2.X : starfishPoint1.X;
var y1 = (starfishPoint1.Y < starfishPoint2.Y) ? starfishPoint1.Y : starfishPoint2.Y;
var y2 = (starfishPoint1.Y < starfishPoint2.Y) ? starfishPoint2.Y : starfishPoint1.Y;
if ((x1 <= squidPoint.X && squidPoint.X <= x2 && squidPoint.Y == starfishPoint.Y) ||
(y1 <= squidPoint.Y && squidPoint.Y <= y2 && squidPoint.X == starfishPoint.X))
{
irrKlangEngine.Play2D(@"Sounds\bulle.wav", false);
squid.Die(() =>
{
squid.IsDying = true;
squid.Born(null);
}
);
break;
}
}
});
}
}
}
else
{
if (!movementHalted)
{
snail.TryMoveXY(new Point(deltaX, deltaY));
}
}
}
private void Window_Closed(object sender, EventArgs e)
{
midiHelper.DisposeAll();
Application.Current.Shutdown();
}
}
public enum MovementType
{
None = 0,
Left = 1,
Right = 2,
Top = 3,
Bottom = 4
}
}