Click here to Skip to main content
15,892,797 members
Articles / Web Development / ASP.NET

Online Circular Chess in Silverlight, ASP.NET AJAX, WCF Web Services, and LINQ to SQL

Rate me:
Please Sign up or sign in to vote.
4.84/5 (61 votes)
31 Dec 2007CPOL34 min read 220.4K   1.9K   145  
An application for users to play Circular Chess over the internet based on Silverlight, ASP.NET AJAX, WCF Web Services, and LINQ to SQL.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Collections.Generic;
using Silverlight.Controls;
using CChess.Controls;
using System.Windows.Browser;
using System.Net;
using CircularChess.CChessProxy;

namespace CircularChess
{
    public partial class Page : Canvas
    {
        public Page()
        {
            Loaded += new EventHandler(Page_Loaded);
            current_selected_square = null;
            _last_move = new CChessMove() { move_id = 0 };

            proxy = new CircularChess.CChessProxy.CChessSkeleton();
            // Because the proxy was generated with an ASMX web service, we must
            // redirect it to the WCF web service.
            proxy.Url = "CChessService.svc";

            drag_drop = new DragAndDrop { CenterOnMouseDown = true };
            drag_drop.CustomMouseDown += new DragAndDropEventHandler(_drag_drop_CustomMouseDown);
            drag_drop.CustomMouseMove += new DragAndDropEventHandler(_drag_drop_CustomMouseMove);
            drag_drop.CustomMouseUp += new DragAndDropEventHandler(_drag_drop_CustomMouseUp);
        }

        #region Fields

        private DragAndDrop drag_drop;
        private CChessSquare current_selected_square;
        private CChessBoard my_chessboard;
        private CChessProxy.CChessGamesPlayers you;
        private CChessProxy.CChessGamesPlayers opponent;
        private CChessProxy.CChessSkeleton proxy;
        private HtmlTimer opponent_get_timer;
        private HtmlTimer new_move_timer;
        private CChessMove _last_move;
        private const int tile_img_width = 159;
        private const int tile_img_height = 159;
        private const String tile_img_url = "images/wood7.jpg";

        #endregion

        public void Page_Loaded(object o, EventArgs e)
        {
            // Required to initialize variables
            InitializeComponent();

            proxy.BeginGetYou(new AsyncCallback(YouGotten), null);
            proxy.BeginGetOpponent(new AsyncCallback(OpponentGotten), null);

            opponent_get_timer = new HtmlTimer();
            opponent_get_timer.Interval = 5000;
            opponent_get_timer.Tick += new EventHandler(opponent_timer_Tick);

            new_move_timer = new HtmlTimer();
            new_move_timer.Interval = 4000;
            new_move_timer.Tick += new EventHandler(_new_move_timer_Tick);
            new_move_timer.Start();

            SetTileBackground();
        }

        public void SetTileBackground()
        {
            Image tmp;
            for (int i = 0; tile_img_width * i < Width; i++)
            {
                for (int j = 0; tile_img_height * j < Height; j++)
                {
                    tmp = new Image();
                    tmp.SetValue(Canvas.ZIndexProperty, -1);
                    tmp.SetValue(Canvas.LeftProperty, i * tile_img_width);
                    tmp.SetValue(Canvas.TopProperty, j * tile_img_height);
                    tmp.Source = new Uri(tile_img_url, UriKind.RelativeOrAbsolute);
                    Children.Add(tmp);
                }
            }
        }

        public void YouGotten(IAsyncResult iar)
        {
            you = proxy.EndGetOpponent(iar);
            your_textblock.Text = you.player_nick;

            proxy.BeginGetAllMoves(you.game_id, AllMovesGotten, null);
        }

        public void AllMovesGotten(IAsyncResult iar)
        {
            CChessMove[] moves = proxy.EndGetAllMoves(iar);
            CChess.CChessBoard board = new CChess.CChessBoard();
            for (int i = 0; i < moves.Length; i++)
            {
                board.MovePiece(moves[i].piece_id, moves[i].destination_ring, moves[i].destination_square);
                _last_move = moves[i];
            }

            Color your_color = (you.color == (byte)CChess.CChessColors.White) ? CChessBoard.white_color : CChessBoard.black_color;
            my_chessboard = new CChessBoard(your_color, 275, 100, board);
            my_chessboard.SetValue<double>(Canvas.TopProperty, 0);
            my_chessboard.SetValue<double>(Canvas.LeftProperty, (Width / 2 - my_chessboard.Width / 2));
            my_chessboard.SetValue<double>(Canvas.TopProperty, (Height / 2 - my_chessboard.Height / 2));
            my_chessboard.OnLoad += new CChessBoard.NoParametersEventHandler(_my_chessboard_OnLoad);
            Children.Add(my_chessboard);

            my_textblock.Text = "Ready.";
        }

        void _my_chessboard_OnLoad()
        {
            foreach (CChessPiece piece in my_chessboard.Pieces)
            {
                if (piece.IsAlive)
                {
                    drag_drop.MakeDraggable(piece);
                }
            }

            foreach (CChessSquare square in my_chessboard.Squares)
            {
                square.MovingAnimationComplete += new EventHandler(piece_storyboard_Completed);
            }

            SelectCurrentPlayer();
        }

        void SelectCurrentPlayer()
        {
            if ((byte)my_chessboard.CurrentMoveColor == you.color)
            {
                opponent_textblock.UnselectPlayer();
                your_textblock.SelectPlayer();
            }
            else
            {
                your_textblock.UnselectPlayer();
                opponent_textblock.SelectPlayer();
            }
        }

        void _new_move_timer_Tick(object sender, EventArgs e)
        {
            if (opponent != null && (byte)my_chessboard.CurrentMoveColor != you.color)
            {
                new_move_timer.Stop();
                proxy.BeginGetLastMove(_last_move.move_id, new AsyncCallback(LastMoveGotten), null);
            }
        }

        public void LastMoveGotten(IAsyncResult iar)
        {
            CChessProxy.CChessMove last_move = proxy.EndGetLastMove(iar);
            if (last_move != null && _last_move != null && last_move.move_id != _last_move.move_id)
            {
                _last_move = last_move;

                CChessPiece the_piece = my_chessboard.Pieces[last_move.piece_id - 1];
                CChessSquare the_square = my_chessboard.Squares[last_move.destination_ring - 1, last_move.destination_square - 1];

                SetPieceOnTop(the_piece);

                the_piece.Square.AnimatePieceToSquare(the_square);
            }
            else
            {
                new_move_timer.Start();
            }
        }

        void piece_storyboard_Completed(object sender, EventArgs e)
        {
            SetPieceOnBottom(my_chessboard.Pieces[_last_move.piece_id - 1]);

            my_chessboard.MovePiece(_last_move.piece_id, _last_move.destination_ring, _last_move.destination_square);
            SelectCurrentPlayer();
            new_move_timer.Start();
        }

        void opponent_timer_Tick(object sender, EventArgs e)
        {
            proxy.BeginGetOpponent(new AsyncCallback(OpponentGotten), null);
            opponent_get_timer.Stop();
        }

        public void OpponentGotten(IAsyncResult iar)
        {
            CChessProxy.CChessGamesPlayers p = proxy.EndGetOpponent(iar);
            if (p == null)
            {
                if (opponent == null)
                {
                    opponent_textblock.Text = "Waiting for someone to join.";
                }
                else
                {
                    opponent_textblock.Text = opponent.player_nick + " has left.";
                }
            }
            else
            {
                opponent = p;
                opponent_textblock.Text = opponent.player_nick;
            }

            opponent_get_timer.Start();
        }

        /// <summary>
        /// Sets a high z-index on the piece
        /// </summary>
        void SetPieceOnTop(CChessPiece piece)
        {
            CChessSquare square = piece.Square;
            // Keeps the piece on top while dragging it.
            square.SetValue<int>(Canvas.ZIndexProperty, 1);
        }

        /// <summary>
        /// Sets a low z-index on the piece
        /// </summary>
        void SetPieceOnBottom(CChessPiece piece)
        {
            CChessSquare square = piece.Square;
            square.SetValue<int>(Canvas.ZIndexProperty, 0);
        }

        void LastMoveSent(IAsyncResult iar)
        {
            try
            {
                _last_move = new CChessMove() { move_id = proxy.EndMovePiece(iar) };
                SelectCurrentPlayer();
            }
            catch (WebException ex)
            {
                my_textblock.Text = ex.GetBaseException().Message;
            }
        }

        #region Drag and Drop Events Region

        void _drag_drop_CustomMouseDown(FrameworkElement sender, DragAndDropEventArgs args)
        {
            CChessPiece piece = sender as CChessPiece;
            CChessSquare square = piece.Square;
            SetPieceOnTop(piece);

            current_selected_square = square;
            current_selected_square.MarkSelected();
        }

        void _drag_drop_CustomMouseMove(FrameworkElement sender, DragAndDropEventArgs args)
        {
            Point hit_point = args.MouseArgs.GetPosition(my_chessboard);
            CChessSquare square = my_chessboard.GetSquare(hit_point);

            if (square == null)
            {
                if (current_selected_square != null)
                {
                    current_selected_square.UnmarkSelected();
                    current_selected_square = null;
                }
            }
            else
            {
                if (current_selected_square == null)
                {
                    current_selected_square = square;
                    current_selected_square.MarkSelected();
                }
                else
                {
                    if (!current_selected_square.Equals(square))
                    {
                        current_selected_square.UnmarkSelected();
                        current_selected_square = square;
                        current_selected_square.MarkSelected();
                    }
                }
            }
        }

        void _drag_drop_CustomMouseUp(FrameworkElement sender, DragAndDropEventArgs args)
        {
            CChessPiece piece = sender as CChessPiece;
            CChessSquare square = piece.Square;

            SetPieceOnBottom(piece);

            Point hit_point = args.MouseArgs.GetPosition(my_chessboard);
            CChessSquare dest_square = my_chessboard.GetSquare(hit_point);

            if (dest_square == null || opponent == null || (byte)piece.CChessColor != you.color)
            {
                CancelMovement(args);
            }
            else
            {
                try
                {
                    my_chessboard.MovePiece(piece.ID, dest_square.Ring, dest_square.Square);
                    CChessProxy.CChessMove last_move = new CChessProxy.CChessMove()
                    {
                        piece_id = piece.ID,
                        destination_ring = dest_square.Ring,
                        destination_square = dest_square.Square,
                        player_id = you.player_id,
                        game_id = you.game_id
                    };
                    proxy.BeginMovePiece(last_move, new AsyncCallback(LastMoveSent), null);
                }
                catch(Exception ex)
                {
                    my_textblock.Text = ex.Message;
                    CancelMovement(args);
                }
            }

            if (current_selected_square != null)
            {
                current_selected_square.UnmarkSelected();
                current_selected_square = null;
            }
        }

        void CancelMovement(DragAndDropEventArgs args)
        {
            args.ReturnToStartingPoint = true;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Israel Israel
My name is Julian, I was born in Argentina, but I've been living in Israel for 6 years already. I'm a high school student in my last year, I study computer science, physics and math.
Other than programming, I really enjoy watching anime and reading manga.

Comments and Discussions