PhotoMemory WP7 App

The Basic Outline of Functionality

  1. Choose the difficulty mode to play in.
  2. Clear default picture values used in development.
  3. Set the board up based on the difficulty mode.
  4. Get personal photos from the phone.
  5. Shuffle photos and select appropriate number based on difficulty mode.
  6. Create pairs and shuffle all cards/photos.
  7. Display unturned cards and any already matched photos.
  8. Choose card and determine matches.
  9. Track number of moves and time.
  10. Display winner once all cards are matched.

PhotoMemory WP7 App

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>

PhotoMemory WP7 App

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;
        }

PhotoMemory WP7 App

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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s