The Basic Outline of Functionality
- Choose the difficulty mode to play in.
- Clear default picture values used in development.
- Set the board up based on the difficulty mode.
- Get personal photos from the phone.
- Shuffle photos and select appropriate number based on difficulty mode.
- Create pairs and shuffle all cards/photos.
- Display unturned cards and any already matched photos.
- Choose card and determine matches.
- Track number of moves and time.
- Display winner once all cards are matched.
The Game Board (XAML)
The game board is basically a grid with several cells to hold the gradient cards or overturned photos. At the bottom, I keep track of number of moves and time expired.
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <toolkit:WrapPanel Grid.Row="0" x:Name="LayoutPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Image Source="Images/1.jpg" Width="150" Margin="5"></Image> <Image Source="Images/2.jpg" Width="150" Margin="5"></Image> <Image Source="Images/3.jpg" Width="150" Margin="5"></Image> <Image Source="Images/6.jpg" Width="150" Margin="5"></Image> <Image Source="Images/4.jpg" Width="150" Margin="5"></Image> <Image Source="Images/1.jpg" Width="150" Margin="5"></Image> <Image Source="Images/2.jpg" Width="150" Margin="5"></Image> <Image Source="Images/7.jpg" Width="150" Margin="5"></Image> <Image Source="Images/8.jpg" Width="150" Margin="5"></Image> <Image Source="Images/5.jpg" Width="150" Margin="5"></Image> <Image Source="Images/9.jpg" Width="150" Margin="5"></Image> <Image Source="Images/3.jpg" Width="150" Margin="5"></Image> <Image Source="Images/4.jpg" Width="150" Margin="5"></Image> <Image Source="Images/6.jpg" Width="150" Margin="5"></Image> <Image Source="Images/7.jpg" Width="150" Margin="5"></Image> <Image Source="Images/8.jpg" Width="150" Margin="5"></Image> <Image Source="Images/9.jpg" Width="150" Margin="5"></Image> <Image Source="Images/5.jpg" Width="150" Margin="5"></Image> </toolkit:WrapPanel> <StackPanel Grid.Row="1" Orientation="Horizontal"> <TextBlock Text="Moves:"></TextBlock> <TextBlock x:Name="MovesLabel" Foreground="Yellow" Text="0" Margin="10,0,0,0"></TextBlock> <TextBlock Text="Time:" Margin="50,0,0,0"></TextBlock> <TextBlock x:Name="TimeLabel" Foreground="Yellow" Text="0 seconds" Margin="10,0,0,0"></TextBlock> </StackPanel> </Grid>
Highlighting a Few Areas of Development
Get Photos
A large part of the charm in this simple application is that it uses your own photos as the cards to match. I had pictures of my daughter and some wildlife we had taken while on a hiking trip (as well as some stock images that came with Windows 7) in my phone when I developed this app. Below is code to retrieve the photos from your phone – stored in MediaLibrary.
private List GetPhotos() { //Get photos from phone List photos = new List(); var library = new MediaLibrary(); var pics = library.Pictures.ToArray(); //Shuffle user pics pics.Shuffle(); //Loop through photos and add to game collection foreach (var pic in pics) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(pic.GetThumbnail()); photos.Add(bmp); } //Check if enough photos are available if (photos.Count < _tileCount / 2) { //Setting default images if user does not have enough pictures of their own photos.Add(new BitmapImage(new Uri("Images/1.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/2.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/3.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/4.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/5.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/6.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/7.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/8.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/9.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/10.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/11.jpg", UriKind.Relative))); photos.Add(new BitmapImage(new Uri("Images/12.jpg", UriKind.Relative))); //Shuffle newly added photos as well photos.Shuffle(); } return photos; }
Display Cards
This is the initial generation of the cards (gradients) and their corresponding actions once a user clicks on them.
private void DisplayCards() { foreach (var card in _collection.Cards) { var rect = new System.Windows.Shapes.Rectangle() { Fill = new LinearGradientBrush(new GradientStopCollection() { new GradientStop() { Color = "#FF003366".ToColor(), Offset = 0 }, new GradientStop() { Color = "#FF208FFF".ToColor(), Offset = 1 }, }, 45 ) { MappingMode = BrushMappingMode.RelativeToBoundingBox }, Height = _cardHeight, Margin = new Thickness(_margin), Name = string.Format("rect_{0}", card.ID), Stroke = new SolidColorBrush(Colors.White), StrokeThickness = 2, Width = _cardWidth, Visibility = System.Windows.Visibility.Visible }; rect.MouseLeftButtonUp += new MouseButtonEventHandler(ChooseCard); LayoutPanel.Children.Add(rect); var img = new Image() { Height = _cardHeight, HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, Margin = new Thickness(_margin), Name = string.Format("card_{0}", card.ID), Source = card.Bitmap, Width = _cardWidth, VerticalAlignment = System.Windows.VerticalAlignment.Stretch, Visibility = System.Windows.Visibility.Collapsed }; LayoutPanel.Children.Add(img); } }
Play a SoundEffect
This code snippet is all over the place on the internet and WP7 forums, but I thought I would include it here for completeness. In PhotoMemory, I play sound effects both in match and non-match scenarios and at the end when all cards are matched for a fun little “triumph”.
//Play failure sound var snd = SoundEffect.FromStream(TitleContainer.OpenStream("Sounds/failed.wav")); snd.Play();
Navigate to Another Page
Again, another simple snippet but this simply shows a way to navigate to another page within WP7 Silverlight.
this.NavigationService.Navigate(new Uri("/Game.xaml?mode=" + mode, UriKind.Relative));
Create and Use a DispatchTimer
Timers are very important in game/mobile development and using a DispatchTimer appears to be the simplest way to do it. Here I create a timer, set some variables such as the duration and what eventhandler to call, and then start the timer. After the timer has expired, the event is raised and I reset the flipped cards.
DispatcherTimer _cardTimer; //Need to pause for 1 second before flipping back _cardTimer = new DispatcherTimer(); _cardTimer.Interval = TimeSpan.FromSeconds(1); _cardTimer.Tick += new EventHandler(FinishStudyingCards); _cardTimer.Start(); void FinishStudyingCards(object sender, EventArgs e) { //Stop timer _cardTimer.Stop(); //Flip cards back down after finished viewing FlipCard(_firstCard, FlipDirection.Down); FlipCard(_secondCard, FlipDirection.Down); //Allow user to try again _firstCard = null; _secondCard = null; _lock = false; }
Submission
I would like to have a link to the application on Zune, however, because of complications with Microsoft my submission is still pending after more than a month. You can bet I will be writing a post on the submission process as well. Good luck, and have fun developing WP7 apps of your own!
One thought on “PhotoMemory WP7 App”