O'Reilly Forums: Save The Humans - Issue - O'Reilly Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Save The Humans - Issue

#1 User is offline   Bwolly 

  • New Member
  • Pip
  • Group: Members
  • Posts: 3
  • Joined: 28-December 13

Posted 28 December 2013 - 03:16 PM

Hi,

I'm totally new to programming so i've picked up this book to learn. I'm hoping i can get some help here because i've hit an issue that i don't understand how to fix.

I've got as far as pg 35, ran the program and it ran ok. No crashes, but the enemies don't animate when i hit the start button....

I've tried to use breakpoints to see if there is any bit of the code that isn't being run but as far as i can tell it seems ok. Although i wasn'#t exactly sure what i expected to see by doing this.

The only difference i can discern between what i've got and what's in the book is this bit:
public sealed partial class MainPage : Page


In the book it's written:
public sealed partial class MainPage : Save_the_Humans.Common.LayoutAwarePage


I'm not sure why this would have any effect on the enemies animating. I assume the library code being use to animate them is not working or i can't connect with it maybe? I'm talking about this bit:
using Windows.UI.Xaml.Media.Animation;


Anyway, if anyone can take pity on a beginner and point me in the right direction i'd appreciate it. I don't really want to skip anything in the book, as i'm pretty sure it'll come back to bite my in the arse later, when i'm trying to understand something more complex.

Here is the entirety of my code so far:
using Save_the_Humans.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.UI.Xaml.Media.Animation;

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace Save_the_Humans
{
    /// <summary>
    /// A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        Random random = new Random();
        private NavigationHelper navigationHelper;
        private ObservableDictionary defaultViewModel = new ObservableDictionary();

        /// <summary>
        /// This can be changed to a strongly typed view model.
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        /// <summary>
        /// NavigationHelper is used on each page to aid in navigation and 
        /// process lifetime management
        /// </summary>
        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }


        public MainPage()
        {
            this.InitializeComponent();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;
            this.navigationHelper.SaveState += navigationHelper_SaveState;
        }

        /// <summary>
        /// Populates the page with content passed during navigation. Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="sender">
        /// The source of the event; typically <see cref="NavigationHelper"/>
        /// </param>
        /// <param name="e">Event data that provides both the navigation parameter passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
        /// a dictionary of state preserved by this page during an earlier
        /// session. The state will be null the first time a page is visited.</param>
        private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="sender">The source of the event; typically <see cref="NavigationHelper"/></param>
        /// <param name="e">Event data that provides an empty dictionary to be populated with
        /// serializable state.</param>
        private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
        {
        }

        #region NavigationHelper registration

        /// The methods provided in this section are simply used to allow
        /// NavigationHelper to respond to the page's navigation methods.
        /// 
        /// Page specific logic should be placed in event handlers for the  
        /// <see cref="GridCS.Common.NavigationHelper.LoadState"/>
        /// and <see cref="GridCS.Common.NavigationHelper.SaveState"/>.
        /// The navigation parameter is available in the LoadState method 
        /// in addition to page state preserved during an earlier session.

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedFrom(e);
        }

        #endregion

        private void startButton_Click(object sender, RoutedEventArgs e)
        {
            AddEnemy();
        }

        private void AddEnemy()
        {
            ContentControl enemy = new ContentControl();
            enemy.Template = Resources["EnemyTemplate"] as ControlTemplate;
            AnimateEnemy(enemy, 0, playArea.ActualWidth -100, "(Canvas.Left)");
            AnimateEnemy(enemy, random.Next((int)playArea.ActualHeight -100), 
                random.Next((int)playArea.ActualHeight -100), "(Canvas.Top)");
            playArea.Children.Add(enemy);
        }

        private void AnimateEnemy(ContentControl enemy, double from, double to, string propertyToAnimate)
        {
            Storyboard storyboard = new Storyboard() { AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever };
            DoubleAnimation animation = new DoubleAnimation()
            {
                From = from,
                To = to,
                Duration = new Duration(TimeSpan.FromSeconds(random.Next(4, 6)))
            };
            Storyboard.SetTarget(animation, enemy);
            Storyboard.SetTargetProperty(animation, propertyToAnimate);
            storyboard.Children.Add(animation);
            storyboard.Begin();
        }
    }
}


Thanks,
Ben
0

#2 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 716
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 29 December 2013 - 07:00 AM

Sorry that you're having trouble -- I bet we can get to the bottom of this. I don't see any immediate problems with the code you posted. Let's see if we can figure this out. Can you post the XAML as well?
(If you want to move forward, there's nothing in Chapter 2 that directly depends on Chapter 1 -- you don't get back to it until much later in the book.)

Also -- the LayoutAwarePage vs. Page thing is one of the changes that happened in Visual Studio 2013. Here's the VS2012 download link: http://www.microsoft...s.aspx?id=30664

I recommend installing it and using it for the rest of the book. You don't need to uninstall VS2012, both of them can run side by side.

Unfortunately, the book went to press before VS2013 came out, which is why it's based on VS2012. I'm currently working on a VS2013 update to the book for future printings (I'll definitely release a full PDF of the first three chapters with the VS2013, and also a summary of the updates so readers with the VS2012 version won't miss anything -- there are changes to individual pages, but none of the learning changed). There aren't that many changes, but there are enough that will break some projects. Your problem might be related, but it might not be -- we'll figure it out!
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#3 User is offline   Rich Hopkins 

  • Active Member
  • PipPip
  • Group: Members
  • Posts: 11
  • Joined: 17-December 13

Posted 31 December 2013 - 09:04 PM

Yeah, the odd changes between Windows 8 / VS2012 and Windows 8.1 / VS2013 have been the cause for a lot of confusion with me. Add to that the variance between Windows 8 and Windows Phone... ugh.
0

#4 User is offline   Bwolly 

  • New Member
  • Pip
  • Group: Members
  • Posts: 3
  • Joined: 28-December 13

Posted 07 January 2014 - 12:43 PM

Thanks for the replies :) Yeah i'm told that IDE's are particular bug bare of programmers but i wasn't aware of how they might break functionality. I suppose it must be the the stuff it generates automatically is slightly different and pretty brick wallish for a beginner. Currently downloading 2012 and will start on the 2nd chapter. But in the meantime, as requested here is the xaml that i generated:

<Page
    x:Name="pageRoot"
    x:Class="Save_the_Humans.MainPage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Save_the_Humans"
    xmlns:common="using:Save_the_Humans.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">Save the Humans</x:String>
        <ControlTemplate x:Key="EnemyTemplate" TargetType="ContentControl">
            <Grid/>
        </ControlTemplate>
    </Page.Resources>

    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="160"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="160"/>
        </Grid.ColumnDefinitions>
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition/>
            <RowDefinition Height="160"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid Grid.ColumnSpan="3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                        Style="{StaticResource NavigationBackButtonNormalStyle}"
                        VerticalAlignment="Top"
                        AutomationProperties.Name="Back"
                        AutomationProperties.AutomationId="BackButton"
                        AutomationProperties.ItemType="Navigation Button"/>
            <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                        IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
        </Grid>
        <Button x:Name="startButton" 
                Content="Start!" 
                HorizontalAlignment="Center" 
                Grid.Row="2" 
                VerticalAlignment="Center" Click="startButton_Click"/>
        <StackPanel Grid.Column="2" Orientation="Vertical" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock 
        		TextWrapping="Wrap" 
        		Text="Avoid these!" Style="{StaticResource SubheaderTextBlockStyle}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <ContentControl Content="ContentControl" 
                            VerticalAlignment="Center" 
                            HorizontalAlignment="Center" 
                            Template="{StaticResource EnemyTemplate}"/>
            <Ellipse Fill="#FF002EFF" 
                     Height="100" 
                     Stroke="Black" 
                     Width="100"/>
        </StackPanel>
        <ProgressBar Grid.Column="1" 
                     Grid.Row="2" Height="20"/>
        <Canvas x:Name="playArea" 
                Grid.Row="1" Grid.ColumnSpan="3">
            <Canvas.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFFF2E00" Offset="0"/>
                    <GradientStop Color="#FFFFDD00" Offset="1"/>
                </LinearGradientBrush>
            </Canvas.Background>
            <StackPanel x:Name="human" Orientation="Vertical">
                <Ellipse Fill="#FFFFD2E2" Height="10" Stroke="Black" Width="10"/>
                <Rectangle Fill="#FFFFD2E2" Height="25" Stroke="Black" Width="10"/>
            </StackPanel>
            <TextBlock x:Name="gameOverText" Canvas.Left="443" TextWrapping="Wrap" Text="Game Over" Canvas.Top="166" FontSize="100" FontFamily="Arial Black" FontWeight="Bold" FontStyle="Italic" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Rectangle x:Name="target" Height="50" Canvas.Left="692" Stroke="Black" Canvas.Top="93" Width="50" RenderTransformOrigin="0.5,0.5">
                <Rectangle.RenderTransform>
                    <CompositeTransform Rotation="45"/>
                </Rectangle.RenderTransform>
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF1F3BE8" Offset="0"/>
                        <GradientStop Color="#FF15E4BE" Offset="1"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>
        </Canvas>
    </Grid>
</Page>


I'm told i can import projects easily enough from one version to another, however i suspect the damage has already been done and that something which was automatically generated is causing the issue. :s
0

#5 User is offline   AndrewStellman 

  • Andrew Stellman
  • PipPipPipPipPipPipPipPipPipPipPip
  • Group: O'Reilly Author
  • Posts: 716
  • Joined: 08-October 08
  • Gender:Male
  • Location:Brooklyn, NY
  • Interests:Author of: "Head First C#", "Beautiful Teams", "Head First PMP", "Applied Software Project Management"

Posted 07 January 2014 - 09:47 PM

Thanks for posting -- I see what the problem is. Here's the problem:


        <ControlTemplate x:Key="EnemyTemplate" TargetType="ContentControl">
            <Grid/>
        </ControlTemplate> 


Instead of dragging the ellipse into the template on page 25, it looks like you dragged it onto the main canvas. If you're really careful to follow the steps on page 25, here's what it should look like:

        <ControlTemplate x:Key="EnemyTemplate" TargetType="ContentControl">
            <Grid>
                <Ellipse Fill="Red" Height="100" Stroke="Black" Width="100"/>
            </Grid>
        </ControlTemplate>


The reason your program didn't look like it was doing anything was that it actually was adding the enemy and animating it, but since the template had no visible controls, the enemies were invisible. Once I fixed enemy template, it worked just fine for me (in Visual Studio 2013).


Just be really careful to follow page 25 exactly, and it should work just fine.

I hope this helps!
Andrew Stellman
Author, Head First C#
Building Better Software -- http://www.stellman-greene.com
0

#6 User is offline   Bwolly 

  • New Member
  • Pip
  • Group: Members
  • Posts: 3
  • Joined: 28-December 13

Posted 08 January 2014 - 02:37 PM

awesome! it worked. Thanks!
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users