Click here to Skip to main content
12,348,760 members (29,352 online)
Click here to Skip to main content
Add your own
alternative version


99 bookmarked

Soccerlight World Cup 2010

, 11 Jul 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
A soccer game made with Silverlight and VS 2008.




This is my first Silverlight game. Some months ago, I had the idea to create something related to the ongoing 2010 FIFA World Cup, but for some time, I was asking myself what could be done? Fortunately, my childhood memories helped me to answer this question.

This game is a product of hours of hard work, mixing both study and trial-and-error approaches. Fortunately, when you really put focus on something, the learning curve starts getting easier. When the road is paved, you are ready to run.


In Brazil, there is a very well-known game named "Futebol de Botão" (Button Football), or "Futebol de Mesa" (Table Football), which deserves at least a brief note.

In the beginning of the 20th century, the boys in Brazil, just like in many other parts of the world, were big fans of football. There were football clubs everywhere, and the radio broadcasting helped spread this entertainment throughout Brazil. According to Wikipedia, someone had this idea to create a table football, where the field was any smooth flat surface, and the players were buttons positioned on a table. The buttons were the large ones, taken from clothes. Much for the despair of the poor mothers of that time, who had to sew new buttons, the table football became one of the most popular games among Brazilian children (specially when they were grounded and forbidden to play real football outdoors...)

Besides the use of clothing buttons, people tried other materials, such as pieces made of coconut shells and bones. The goalkeepers were just matchboxes filled in by sand or some heavy material. But finally, the industry started making buttons from plastic materials, which became the standard for commercial versions of the game.

Since most kids today prefer computer games, in this article, I tried to reproduce the feeling and atmosphere of those plastic buttons.

You can have a quick overview of the game by taking a look at the YouTube video I uploaded, in the link below:

System Requirements

In order to get the game to work, you can download the following, if you don't have VS 2008 and Silverlight 3:

Soccerlight Solution


Figure 1: Solution structure

The Visual Studio 2008 solution is made up mainly by the Soccerlight project, which contains the Silverlight logic itself, and other helper projects, as we can see in the following table.

Project Description
Silverlight This is the Silverlight project itself.
Silverlight.Controls This Silverlight Class Library project that holds some of the custom controls I use in the project.
Silverlight.Core This project holds some of the game logic and the model classes.
Silverlight.Web This project is the start up project that contains the application's entry page.

Intro Menu

The Intro menu consists of a table containing all of the 8 groups which played in the 2010 FIFA World Cup.

The idea is that you pick up a national team and start playing with that team. Then you will have to follow exactly the same games as they were scheduled in the 2010 World Cup.

For the implementation of this teams table, I didn't use much of XAML. I did it mostly programmatically. What you see in the image below is made up of Grid, TextBlock, and Image elements. I know I might have used a ListBox element with a custom template, but... I wanted more freedom than that. By constructing the visual elements programmatically, I feel that I can have much more control over animations, transforms, etc.


Figure 2: Intro menu

The following function GenerateGroups creates all the 32 teams divided into the 8 groups:

void GenerateGroups()
    for(int i = 0; i < 8; i++)
        Border brd = new Border();
        brd.CornerRadius = new CornerRadius(5);
        brd.Margin = new Thickness(2);
        brd.SetValue(Grid.ColumnProperty, i % 4);
        brd.SetValue(Grid.RowProperty, i / 4);

        LinearGradientBrush lgb = new LinearGradientBrush();
        lgb.StartPoint = new Point(0, 0);
        lgb.EndPoint = new Point(1, 1);
        lgb.GradientStops = new GradientStopCollection();
        lgb.GradientStops.Add(new GradientStop() 
          { Offset = 0.0, Color = Color.FromArgb(255, 0, 0, 0)});
        lgb.GradientStops.Add(new GradientStop() 
          { Offset = 0.5, Color = Color.FromArgb(255, 30, 30, 30)});
        lgb.GradientStops.Add(new GradientStop() 
          { Offset = 1.0, Color = Color.FromArgb(255, 40, 40, 40)});
        brd.Background = lgb;

        lgbEven.StartPoint = new Point(0, 0);
        lgbEven.EndPoint = new Point(1, 1);
        lgbEven.GradientStops = new GradientStopCollection();
        lgbEven.GradientStops.Add(new GradientStop() 
              { Offset = 0.0, Color = Color.FromArgb(255, 0, 0, 0) });
        lgbEven.GradientStops.Add(new GradientStop() 
              { Offset = 0.5, Color = Color.FromArgb(255, 30, 30, 30) });
        lgbEven.GradientStops.Add(new GradientStop() 
              { Offset = 1.0, Color = Color.FromArgb(255, 80, 80, 80) });

        Grid grdGroup = new Grid();
        grdGroup.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(28) });
        grdGroup.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
        grdGroup.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
        grdGroup.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(18) });
        grdGroup.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(18) });
        grdGroup.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(18) });
        grdGroup.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(18) });

        TextBlock txtGroupID = new TextBlock()
            Text = ((char)(i + 65)).ToString(),
            Foreground = new SolidColorBrush(Colors.White),
            FontSize = 18,
            FontWeight = FontWeights.Bold
        txtGroupID.SetValue(Grid.ColumnProperty, 0);
        txtGroupID.SetValue(Grid.RowProperty, 0);
        txtGroupID.SetValue(Grid.RowSpanProperty, 4);
        txtGroupID.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
        txtGroupID.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);

        for (int j = 0; j < 4; j++)
            Grid grdTeam = new Grid();
            grdTeam.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
            grdTeam.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
            grdTeam.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(25) });
            grdTeam.SetValue(Grid.ColumnProperty, 1);
            grdTeam.SetValue(Grid.ColumnSpanProperty, 2);
            grdTeam.SetValue(Grid.RowProperty, j);
            grdTeam.HorizontalAlignment = HorizontalAlignment.Stretch;
            grdTeam.VerticalAlignment = VerticalAlignment.Center;
            grdTeam.Width = 120;

            Team team = 
              GameHelper.Instance.TeamsDictionary[GameHelper.Instance.TeamCodes[i * 4 + j]];
            Image img = new Image()
                Source = new BitmapImage(new Uri(string.Format(
                         team.TeamID.ToLower()), UriKind.Absolute)),
                Width = 28.5,
                Height = 25.0,
                VerticalAlignment = VerticalAlignment.Center
            img.SetValue(Grid.ColumnProperty, 0);
            img.SetValue(Grid.RowProperty, j);
            img.VerticalAlignment = VerticalAlignment.Top;
            img.HorizontalAlignment = HorizontalAlignment.Stretch;
            img.Clip = new RectangleGeometry() { Rect = 
                       new Rect(new Point(0, 0), new Point(28.5, 14)) };
            img.Tag = team.TeamID;
            TranslateTransform tf = new TranslateTransform()
                 X = 0,
                 Y = 6
            img.RenderTransform = tf;

            TextBlock txt = new TextBlock()
                Text = team.TeamName,
                Foreground = new SolidColorBrush(Colors.White)
            txt.SetValue(Grid.ColumnProperty, 1);
            txt.SetValue(Grid.RowProperty, j);
            txt.VerticalAlignment = VerticalAlignment.Center;
            txt.HorizontalAlignment = HorizontalAlignment.Stretch;
            txt.Tag = team.TeamID;

            grdTeam.Tag = team.TeamID;
            grdTeam.MouseEnter += new MouseEventHandler(team_MouseEnter);
            grdTeam.MouseLeave += new MouseEventHandler(team_MouseLeave);
            grdTeam.MouseLeftButtonUp += 
                    new MouseButtonEventHandler(team_MouseLeftButtonUp);


        brd.Child = grdGroup;

Figure 3: The GenerateGroups() function in the IntroMenu.xaml.cs file

Soccerlight Table

If you have chosen England as your team in the Intro menu, you would next be redirected to the following view, which is, of course, the first game of England in the World Cup (England vs. USA, 06/12, in Rustenburg).

Notice that both teams start with the traditional 3-5-2 formation, being 3 fullbacks, 5 midfielders, and 2 forwards. Although this is the default formation for all teams in the game, it wouldn't be so hard to select another formation for the selected teams, since the formation is simply an array of integers:

public Team()
    Formation = new int[] {1, 3, 5, 2};
Figure 4: Team class constructor, showing how the 3-5-2 formation is set up for every team.

Notice that the array in the code snippet above starts with 1. This is so because we have to take the goalkeeper into consideration.


Figure 5: Soccerlight table, showing the 3-5-2 formations of England vs. USA

Notice in the listing below that the field lines and circles are not really images, but instead are made up of Border and Ellipse elements. Notice also that at the four corners, there are quarter-of-circles, which can easily be created by clipping the ordinary circles (see the Ellipse.Clip tags below) using RectangleGeometry to show only the quarter you want.

<Grid x:Name="LayoutRoot" 
       VerticalAlignment="Center" ...
        <ColumnDefinition x:Name="colLeftEscapeArea" Width="53"/>
        <ColumnDefinition x:Name="colLeftPosts" Width="53"/>
        <ColumnDefinition x:Name="colLeftGoalArea" Width="70"/>
        <ColumnDefinition x:Name="colLeftPenaltyArea" Width="280"/>
        <ColumnDefinition x:Name="colHalfWay" Width="280"/>
        <ColumnDefinition x:Name="colRightPenaltyArea" Width="70"/>
        <ColumnDefinition x:Name="colRightGoalArea" Width="53"/>
        <ColumnDefinition x:Name="colRightPosts" Width="53"/>
        <ColumnDefinition x:Name="colMenu" Width="32"/>
        <RowDefinition x:Name="rowTopEscapeArea" Height="50"/>
        <RowDefinition x:Name="rowTopFieldLine" Height="108"/>
        <RowDefinition x:Name="rowTopPenaltyArea" Height="67"/>
        <RowDefinition x:Name="rowTopGoalArea" Height="153"/>
        <RowDefinition x:Name="rowBottomGoalArea" Height="67"/>
        <RowDefinition x:Name="rowBottomPenaltyArea" Height="108"/>
        <RowDefinition x:Name="rowBottomFieldLine" Height="50"/>
    <Border Grid.Column="0" Grid.Row="0" 
            Grid.ColumnSpan="8" Grid.RowSpan="1" 
            Background="DarkGreen" ...
    <Border Grid.Column="0" Grid.Row="1" 
            Grid.ColumnSpan="1" Grid.RowSpan="5" Background="DarkGreen" ...
    <Border Grid.Column="1" Grid.Row="1" 
            Grid.ColumnSpan="3" Grid.RowSpan="5" BorderBrush="White" ...
    <Border Grid.Column="4" Grid.Row="1" 
            Grid.ColumnSpan="3" Grid.RowSpan="5" BorderBrush="White" ...
    <Border Grid.Column="1" Grid.Row="3" 
            Grid.ColumnSpan="1" Grid.RowSpan="1" BorderBrush="White" ...
    <Border Grid.Column="6" Grid.Row="3" 
            Grid.ColumnSpan="1" Grid.RowSpan="1" BorderBrush="White" ...
    <Border Grid.Column="1" Grid.Row="2" 
            Grid.ColumnSpan="2" Grid.RowSpan="3" BorderBrush="White" ...
    <Border Grid.Column="1" Grid.Row="2" 
            Grid.ColumnSpan="2" Grid.RowSpan="3" BorderBrush="White" ...
    <Border Grid.Column="5" Grid.Row="2" 
            Grid.ColumnSpan="2" Grid.RowSpan="3" BorderBrush="White" ...
    <Border Grid.Column="7" Grid.Row="1" 
            Grid.ColumnSpan="1" Grid.RowSpan="5" Background="DarkGreen" ...
    <Border Grid.Column="0" Grid.Row="6" 
            Grid.ColumnSpan="8" Grid.RowSpan="1" Background="DarkGreen" ...
    <StackPanel Grid.Column="1" Grid.Row="1" 
            Grid.ColumnSpan="6" Grid.RowSpan="5" Margin="8, 8, 0, 0" ...
        <Image Source="../Images/Soccerlight.png" Stretch="UniformToFill">
                <ScaleTransform ScaleX="0.25" ScaleY="0.25"/>
    <Grid Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="6" Grid.RowSpan="5" >
            <ColumnDefinition Width="30"/>
            <ColumnDefinition Width="92"/>
            <ColumnDefinition Width="115"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="15"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="115"/>
            <ColumnDefinition Width="92"/>
            <ColumnDefinition Width="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="15"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        <Ellipse Grid.Column="0" Grid.Row="0" StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="15,15,30,30"/>
                <TranslateTransform X="-15" Y="-15"/>
        <Ellipse Grid.Column="10" Grid.Row="0" StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="0,15,15,15"/>
                <TranslateTransform X="15" Y="-15"/>
        <Ellipse Grid.Column="0" Grid.Row="6" StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="15,0,15,15"/>
                <TranslateTransform X="-15" Y="15"/>
        <Ellipse Grid.Column="10" Grid.Row="6" StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="0,0,15,15"/>
                <TranslateTransform X="15" Y="15"/>
        <Ellipse Grid.Column="4" Grid.Row="2" Grid.ColumnSpan="3" Grid.RowSpan="3" 
        StrokeThickness="2" Stroke="White"/>
        <Ellipse Grid.Column="5" Grid.Row="3" Fill="White"/>
        <Ellipse Grid.Column="2" Grid.Row="2" Grid.ColumnSpan="1" Grid.RowSpan="3" 
        StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="57.5,0,115,115"/>
                <TranslateTransform X="-57.5" Y="0"/>
        <Ellipse Grid.Column="8" Grid.Row="2" Grid.ColumnSpan="1" 
                 Grid.RowSpan="3" StrokeThickness="2" Stroke="White">
                <RectangleGeometry Rect="0,0,57.5,115"/>
                <TranslateTransform X="57.5" Y="0"/>
    <Canvas x:Name="rootCanvas"/>
    <Border Grid.Column="0" Grid.Row="3" 
             Grid.ColumnSpan="1" Grid.RowSpan="1" BorderBrush="White" ...
                <ImageBrush ImageSource="../Images/goalnet.png" Stretch="UniformToFill"/>
    <Border Grid.Column="7" Grid.Row="3" 
              Grid.ColumnSpan="1" Grid.RowSpan="1" BorderBrush="White" ...
                <ImageBrush ImageSource="../Images/goalnet.png" Stretch="UniformToFill"/>
    <Border x:Name="brdBallStrengthContainer" 
              Grid.Column="8" Grid.Row="4" Grid.ColumnSpan="1" ...
            <Border x:Name="brdStrength" CornerRadius="4" Margin="8,56,8,8">
                        <GradientStop Color="Red" Offset="0.0"/>
                        <GradientStop Color="Orange" Offset="0.5"/>
                        <GradientStop Color="Yellow" Offset="1.0"/>
            <Image x:Name="imgBallStrength" Source="../Images/Jabulani.png" 
                      VerticalAlignment="Top" Margin="0,32,0,0">
                    <RotateTransform x:Name="rtBallStrength" 
                         CenterX="11.5" CenterY="11.5" Angle="30">
    <Grid x:Name="grdStadiumScreen" MaxWidth="800" 
             MaxHeight="180" Grid.Column="1" Grid.Row="0"...
            <RectangleGeometry Rect="0,0,800,180"/>
        <TextBlock Foreground="White" FontSize="120" 
              Text="GOALLLLLL!!!" TextAlignment="Center" Margin="0">
            <TranslateTransform x:Name="lettersXTranslate" X="0"/>
        <Image Source="../Images/mask.png" Stretch="Fill" Opacity="0.75"/>
        <Grid x:Name="grdBrightness" Background="Black" Opacity="1.00"/>
        <ScaleTransform ScaleX="0.868" ScaleY="0.8700"/>

Score Control

The score control shows the elapsed time, the team nicknames, a blinking ball indicating the playing team, and... the scores.

The elapsed time is controlled by a DispatcherTimer object, which triggers a Tick event every second. This is propagated to the score control to increase the total elapsed time.

In real soccer games, there are two halves of 45 minutes each, separated by a 15-minute break. In Soccerlight, however, the game is over when the timer reaches 30 minutes.

The blinking ball is a useful indicator to show which team is playing at a given moment.


Figure 6: The score control

The Goals

Each goal is delimited by three borders: two at both sides, and one at the back of the goal. If the ball strikes these borders, it will bounce as if it was hitting a wall. Besides, at both sides in front of the goal, there are goalposts, which behave like real cylindrical goalposts, making the ball bounce as if it was hitting a circular object.

Besides, the goal has a transparent goal net, which gives the game a cool and realistic look and feel.

The rule is simple as that: whenever the ball enters the goal, the application updates the score control to increment the score of the attacking team.


Figure 7: The goal: notice the borders, the goal posts, and the detailed goal net



Figure 8: The Jabulani ball

As some of the readers may know, Jabulani is the innovative official ball in the FIFA World Cup, so I decided to use it too in Soccerlight World Cup.

Some players have complained about Jabulani in FIFA Cup, because they have reported "strange" behavior and unpredicted direction changing, while other players have declared their love for the ball. (On the other side, no Soccerlight player has complained about the ball yet...)

In Soccerlight, the physics calculations involving the ball are no different from those involving the players (except for the the fact that players have greater diameters and greater friction coefficients). In fact, both ball and players inherit from the same base class, Discoid:

public class Ball : Discoid
    public class Player : Discoid


Each team has a set of 11 players. In the real world, each player may have different roles, but in Soccerlight, they are treated in the same manner. The only difference between a striker and a goalkeeper, for example, is the fact that the goalkeeper is closer to the goal and the striker's initial position is closer to the opponent's goal. Maybe in future versions I will define different skills, such as, for example, a skilled striker might have more precision when shooting to goal than other average players.


Figure 9: Players caught in action: say "cheese"...

Player Info Bar

Whenever you select a player, the application will show a Player Info Bar. This bar contains basic info about the player: the number, the name, and the picture.

Each Soccerlight player has a number, a name, and a picture. Numbers and names are hard-coded in the application, but the pictures are taken from the FIFA website, as shown in the code snippet below:

imgPlayer.ImageSource = new BitmapImage(new Uri(string.Format(
    teamPlayer.ID), UriKind.Absolute));

The listing below is responsible for showing the Player Info Bar:

<Grid x:Name="grdPlayerInfo" HorizontalAlignment="Center" 
             VerticalAlignment="Bottom" Visibility="Collapsed">
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="8"/>
        <ColumnDefinition Width="400"/>
        <ColumnDefinition Width="200"/>
    <Border Margin="8,8,0,64" CornerRadius="8" 
             Width="75" Height="100" 
                <TranslateTransform X="4" Y="4"/>
    <Border Margin="8,8,0,64" CornerRadius="8" 
             Width="75" Height="100">
                <GradientStop Offset="0.0" Color="#00000000"/>
                <GradientStop Offset="9.0" Color="#20000000"/>
                <GradientStop Offset="1.0" Color="#40000000"/>
                <TranslateTransform X="4" Y="4"/>
    <Border Margin="8,8,0,64" CornerRadius="8" 
             Width="75" Height="100">
            <ImageBrush x:Name="imgPlayer"/>
    <StackPanel Grid.Column="2" VerticalAlignment="Center" Margin="0,0,0,64">
        <Border BorderBrush="Black" BorderThickness="2" CornerRadius="4">
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                    <GradientStop Offset="0.0" Color="Yellow"/>
                    <GradientStop Offset="0.5" Color="Yellow"/>
                    <GradientStop Offset="0.5" Color="Gold"/>
                    <GradientStop Offset="1.0" Color="Goldenrod"/>
                <SkewTransform AngleX="-10"/>
            <StackPanel Orientation="Horizontal">
                <TextBlock x:Name="numPlayer" Text="" Foreground="Black" 
                FontSize="22" FontWeight="Bold" Margin="32,0,0,0"/>
                <TextBlock Text=" - " Foreground="Black" FontSize="22" 
                <TextBlock x:Name="txtPlayerName" Text="" Foreground="Black" 
                FontSize="22" FontWeight="Bold" Margin="0,0,0,0"/>


Figure 10: Player Info Bar

Strength Control Bar

The Strength Control Bar is the means that you have to calibrate your shot strength. The higher you put the Jabulani ball in the bar, the stronger you shoot the ball.


Figure 11: Strength Control Bar

The strength is redefined whenever the user clicks in the Strength Control Bar. This is done by the following code:

private void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    Point point = e.GetPosition(rootCanvas);

    if ((point.X > strengthPointNW.X) &&
        (point.X < strengthPointSE.X) &&
        (point.Y > strengthPointNW.Y) &&
        (point.Y < strengthPointSE.Y))
        e.Handled = true;
        double relativeY = strengthPointSE.Y - point.Y;
        currentGame.Team1BallStrength = ((strengthPointSE.Y - point.Y) / 
               (strengthPointSE.Y - strengthPointNW.Y)) * 100.0;

        imgBallStrength.Margin = new Thickness(0, point.Y - 
            strengthPointNW.Y - imgBallStrength.ActualHeight / 2.0, 0, 0);
        brdStrength.Margin = new Thickness(8, point.Y - 
            strengthPointNW.Y + imgBallStrength.ActualHeight / 2.0, 8, 8);

Stadium Screen

The role of the Stadium Screen is just to show that a team has scored the goal. Simple as that.


Figure 12: Stadium Screen

The Stadium Screen has three different animations. First, there is the translateAnimation, which translates the "GOOAL" string from right to left. Then there is the lettersOpacityAnimation that fades in and fades out the letters of the screen. And finally, there is the screenOpacityAnimation, responsible for fading out the whole Stadium Screen element:

sbStadiumScreen = new Storyboard()
    Duration = new Duration(new TimeSpan(0, 0, 0, 10))

DoubleAnimation translateAnimation = new DoubleAnimation()
    From = 800,
    To = 0,
    Duration = new Duration(new TimeSpan(0, 0, 0, 3))

Storyboard.SetTarget(translateAnimation, lettersXTranslate);
Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("X"));

DoubleAnimation lettersOpacityAnimation = new DoubleAnimation()
    From = 0.8,
    To = 1.0,
    Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500)),
    AutoReverse = true,
    RepeatBehavior = RepeatBehavior.Forever

Storyboard.SetTarget(lettersOpacityAnimation, grdBrightness);
Storyboard.SetTargetProperty(lettersOpacityAnimation, new PropertyPath("Opacity"));

DoubleAnimation screenOpacityAnimation = new DoubleAnimation()
    From = 1.0,
    To = 0.0,
    BeginTime = new TimeSpan(0, 0, 0, 0),
    Duration = new Duration(new TimeSpan(0, 0, 0, 4))


Storyboard.SetTarget(screenOpacityAnimation, grdStadiumScreen);
Storyboard.SetTargetProperty(screenOpacityAnimation, new PropertyPath("Opacity"));

Wish List and Known Issues

Some issues with the game, and some desirable improvements which I'm willing to be correcting/implementing in future releases:

  • The game still doesn't handle fouls. At first, this seems easy to implement, but depending on where the foul occurred, after the foul, you might have to rearrange the players so that they don't collide with each other, etc.
  • There are still no games for the knockout stage. Maybe I'll generate random results for the other matches, and if your team keeps winning, you'll advance from the round of 16 to the quarter-of-finals, semi-finals, and finally to the final match.
  • It would be very cool to implement an online, service-based, human-to-human version of the game. A WCF Service will do, I think.

Final Considerations

If you reached this line, I'd like to thank you for your patience. Please tell me what you liked or disliked in the application. Criticism and suggestions are welcome, and I'm willing to improve this article and application based on your feedback.


  • 2010-06-29: First version.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Marcelo Ricardo de Oliveira
Software Developer
Brazil Brazil
Marcelo Ricardo de Oliveira is a senior software developer who lives with his lovely wife Luciana and his little buddy and stepson Kauê in Guarulhos, Brazil, is co-founder of the Brazilian TV Guide TV Map and currently works for ILang Educação.

He is often working with serious, enterprise projects, although in spare time he's trying to write fun Code Project articles involving WPF, Silverlight, XNA, HTML5 canvas, Windows Phone app development, game development and music.

Published Windows Phone apps:


CodeProject MVP 2012
CodeProject MVP 2011

Best Web Dev article of March 2013
Best Web Dev article of August 2012
Best Web Dev article of May 2012
Best Mobile article of January 2012
Best Mobile article of December 2011
Best Mobile article of October 2011
Best Web Dev article of September 2011
Best Web Dev article of August 2011
HTML5 / CSS3 Competition - Second Prize
Best ASP.NET article of June 2011
Best ASP.NET article of May 2011
Best ASP.NET article of April 2011
Best C# article of November 2010
Best overall article of November 2010
Best C# article of October 2010
Best C# article of September 2010
Best overall article of September 2010
Best overall article of February 2010
Best C# article of November 2009

You may also be interested in...

Comments and Discussions

Questioncompilation in Visual Studio 2012 Pin
erma19895-Jun-14 8:58
membererma19895-Jun-14 8:58 
Questionhtml5 version Pin
kiquenet.com4-Sep-13 9:55
memberkiquenet.com4-Sep-13 9:55 
AnswerRe: html5 version Pin
Marcelo Ricardo de Oliveira4-Sep-13 11:29
mvpMarcelo Ricardo de Oliveira4-Sep-13 11:29 
GeneralRe: html5 version Pin
kiquenet.com7-Sep-13 3:20
memberkiquenet.com7-Sep-13 3:20 
GeneralRe: html5 version Pin
kiquenet.com10-Jul-14 4:41
memberkiquenet.com10-Jul-14 4:41 
GeneralRe: html5 version Pin
Marcelo Ricardo de Oliveira10-Jul-14 6:58
mvpMarcelo Ricardo de Oliveira10-Jul-14 6:58 
GeneralRe: html5 version Pin
kiquenet.com19-Jul-14 9:13
memberkiquenet.com19-Jul-14 9:13 
GeneralMy vote of 5 Pin
prelate25-May-13 11:46
memberprelate25-May-13 11:46 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira27-May-13 13:28
mvpMarcelo Ricardo de Oliveira27-May-13 13:28 
GeneralMy vote of 5 Pin
soulprovidergr18-Sep-12 23:24
membersoulprovidergr18-Sep-12 23:24 
GeneralMy vote of 5 Pin
Pravin Patil, Mumbai15-Jul-12 22:40
memberPravin Patil, Mumbai15-Jul-12 22:40 
GeneralMy vote of 5 Pin
kiquenet.com5-Jun-12 11:40
memberkiquenet.com5-Jun-12 11:40 
Questionturtle Pin
baazka9-Mar-12 18:15
memberbaazka9-Mar-12 18:15 
GeneralMy vote of 5 Pin
gif202013-Sep-11 23:32
membergif202013-Sep-11 23:32 
GeneralMy vote of 5 Pin
RaviRanjankr1-Jan-11 1:08
memberRaviRanjankr1-Jan-11 1:08 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira1-Jan-11 6:19
memberMarcelo Ricardo de Oliveira1-Jan-11 6:19 
GeneralGreat Job Pin
Bassam Abdul-Baki22-Nov-10 2:54
memberBassam Abdul-Baki22-Nov-10 2:54 
GeneralRe: Great Job Pin
Marcelo Ricardo de Oliveira3-Dec-10 7:52
memberMarcelo Ricardo de Oliveira3-Dec-10 7:52 
GeneralThanks & bugs & advice Pin
hollysong29-Sep-10 0:38
memberhollysong29-Sep-10 0:38 
GeneralRe: Thanks & bugs & advice Pin
Marcelo Ricardo de Oliveira30-Sep-10 0:59
memberMarcelo Ricardo de Oliveira30-Sep-10 0:59 
GeneralLittle bug Pin
_ZIgi14-Sep-10 5:48
member_ZIgi14-Sep-10 5:48 
GeneralRe: Little bug Pin
Marcelo Ricardo de Oliveira26-Sep-10 12:35
memberMarcelo Ricardo de Oliveira26-Sep-10 12:35 
GeneralMy vote of 5 Pin
thatraja2-Sep-10 4:01
memberthatraja2-Sep-10 4:01 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira27-Sep-10 4:24
memberMarcelo Ricardo de Oliveira27-Sep-10 4:24 
GeneralMy vote of 5 Pin
César de Souza20-Aug-10 7:46
memberCésar de Souza20-Aug-10 7:46 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira26-Aug-10 4:05
memberMarcelo Ricardo de Oliveira26-Aug-10 4:05 
GeneralMy vote of 5 Pin
Abhinav S17-Jul-10 7:15
memberAbhinav S17-Jul-10 7:15 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira17-Jul-10 11:55
memberMarcelo Ricardo de Oliveira17-Jul-10 11:55 
GeneralMy vote of 5 Pin
Petr Pechovic13-Jul-10 21:02
memberPetr Pechovic13-Jul-10 21:02 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira14-Jul-10 3:19
memberMarcelo Ricardo de Oliveira14-Jul-10 3:19 
GeneralRe: My vote of 5 Pin
Petr Pechovic14-Jul-10 4:32
memberPetr Pechovic14-Jul-10 4:32 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira14-Jul-10 7:06
memberMarcelo Ricardo de Oliveira14-Jul-10 7:06 
GeneralMy vote of 5 Pin
linuxjr12-Jul-10 11:59
memberlinuxjr12-Jul-10 11:59 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira12-Jul-10 13:38
memberMarcelo Ricardo de Oliveira12-Jul-10 13:38 
GeneralMuito bom, parabéns!! Pin
memberRICARDO MARCONE12-Jul-10 4:19 
GeneralRe: Muito bom, parabéns!! Pin
Marcelo Ricardo de Oliveira12-Jul-10 7:36
memberMarcelo Ricardo de Oliveira12-Jul-10 7:36 
GeneralMy vote of 5 Pin
defwebserver12-Jul-10 4:14
memberdefwebserver12-Jul-10 4:14 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira12-Jul-10 7:34
memberMarcelo Ricardo de Oliveira12-Jul-10 7:34 
GeneralMy vote of 5 Pin
jujusharp12-Jul-10 3:45
memberjujusharp12-Jul-10 3:45 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira12-Jul-10 7:31
memberMarcelo Ricardo de Oliveira12-Jul-10 7:31 
GeneralMy vote of 5 Pin
Raul Mainardi Neto12-Jul-10 2:53
memberRaul Mainardi Neto12-Jul-10 2:53 
GeneralRe: My vote of 5 Pin
Marcelo Ricardo de Oliveira12-Jul-10 3:12
memberMarcelo Ricardo de Oliveira12-Jul-10 3:12 
GeneralRe: My vote of 5 Pin
Raul Mainardi Neto12-Jul-10 3:52
memberRaul Mainardi Neto12-Jul-10 3:52 
GeneralWell done Pin
Jordy "Kaiwa" Ruiter8-Jul-10 22:54
memberJordy "Kaiwa" Ruiter8-Jul-10 22:54 
GeneralRe: Well done Pin
Marcelo Ricardo de Oliveira9-Jul-10 8:02
memberMarcelo Ricardo de Oliveira9-Jul-10 8:02 
GeneralNice one Pin
Sacha Barber8-Jul-10 22:52
mvpSacha Barber8-Jul-10 22:52 
GeneralRe: Nice one Pin
Marcelo Ricardo de Oliveira9-Jul-10 7:59
memberMarcelo Ricardo de Oliveira9-Jul-10 7:59 
GeneralWicked stuff Pin
Alan Beasley8-Jul-10 22:06
memberAlan Beasley8-Jul-10 22:06 
GeneralRe: Wicked stuff Pin
Marcelo Ricardo de Oliveira9-Jul-10 7:58
memberMarcelo Ricardo de Oliveira9-Jul-10 7:58 
GeneralMy vote of 5 Pin
IronXAres7-Jul-10 3:53
memberIronXAres7-Jul-10 3:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160621.1 | Last Updated 11 Jul 2010
Article Copyright 2010 by Marcelo Ricardo de Oliveira
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid