Click here to Skip to main content
15,892,643 members
Articles / Desktop Programming / WPF

WPF Grand Prix

Rate me:
Please Sign up or sign in to vote.
4.97/5 (110 votes)
14 Dec 2010CPOL10 min read 384.9K   6.3K   176  
An article showing how to create a race game using the powerful WPF capabilities
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
//using System.Windows.Media.Effects;
using GrandPrix.TrackSegments;

namespace GrandPrix
{
    /// <summary>
    /// Interaction logic for Kart.xaml
    /// </summary>
    public partial class Kart : UserControl
    {
        #region attributes
        public static DependencyProperty WheelAngleProperty = DependencyProperty.Register("WheelAngle", typeof(double), typeof(Kart), new PropertyMetadata(new PropertyChangedCallback(WheelAngleChanged)));
        public static DependencyProperty BodyColor1Property = DependencyProperty.Register("BodyColor1", typeof(Color), typeof(Kart), new PropertyMetadata(new PropertyChangedCallback(BodyColor1Changed)));
        public static DependencyProperty BodyColor2Property = DependencyProperty.Register("BodyColor2", typeof(Color), typeof(Kart), new PropertyMetadata(new PropertyChangedCallback(BodyColor2Changed)));
        public static DependencyProperty BodyColor3Property = DependencyProperty.Register("BodyColor3", typeof(Color), typeof(Kart), new PropertyMetadata(new PropertyChangedCallback(BodyColor3Changed)));
        public static DependencyProperty MaxSpeedProperty = DependencyProperty.Register("MaxSpeed", typeof(double), typeof(Kart), new PropertyMetadata(new PropertyChangedCallback(MaxSpeedChanged)));
        double maxSpeed = 10.0;

        #endregion attributes

        #region ctor
        public Kart()
        {
            InitializeComponent();

            CarToTrackDistanceList = new List<double>();
            ShortestDistance = 10000.0;
            LastDistance = 10000.0;
            CarGroundType = GroundType.Asphalt;
            RangeEllipseList = new List<Ellipse>();

            //ShadowEffect = new DropShadowBitmapEffect()
            //{
            //    Color = Colors.Black,
            //    Direction = 0,
            //    ShadowDepth = 25,
            //    Softness = 2,
            //    Opacity = 0.5
            //};

            //this.BitmapEffect = ShadowEffect;

            CurrentSegmentOffset = 0.0;

            Speed = 0.0;
            Velocity2D = new Vector(0.0, 0.0);
            Laps = 0;
        }
        #endregion ctor

        #region properties
        public double WheelAngle
        {
            get { return (double)GetValue(WheelAngleProperty); }
            set { SetValue(WheelAngleProperty, value); }
        }

        public double MaxSpeed
        {
            get { return (double)GetValue(MaxSpeedProperty); }
            set { SetValue(MaxSpeedProperty, value); }
        }

        public Color BodyColor1
        {
            get { return (Color)GetValue(BodyColor1Property); }
            set { SetValue(BodyColor1Property, value); }
        }

        public Color BodyColor2
        {
            get { return (Color)GetValue(BodyColor2Property); }
            set { SetValue(BodyColor2Property, value); }
        }

        public Color BodyColor3
        {
            get { return (Color)GetValue(BodyColor3Property); }
            set { SetValue(BodyColor3Property, value); }
        }

        public ScaleTransform CarScaleTransform { get; set; }
        public TranslateTransform CarTranslateTransform { get; set; }
        public RotateTransform CarRotateTransform { get; set; }
        public double Acceleration { get; set; }
        public double Speed { get; set; }
        public Vector Velocity2D { get; set; }
        //public DropShadowBitmapEffect ShadowEffect { get; set; }
        public List<double> CarToTrackDistanceList { get; set; }
        public List<Ellipse> RangeEllipseList { get; set; }
        public TrackLineSegment LastNearestTrackLineSegment { get; set; }
        public TrackLineSegment NearestTrackLineSegment { get; set; }
        public double ShortestDistance { get; set; }
        public double LastDistance { get; set; }
        public GroundType CarGroundType { get; set; }

        public double CircuitOffset { get; set; }
        public int CurrentSegmentIndex { get; set; }
        public double CurrentSegmentOffset { get; set; }

        public bool IsTurningLeft { get; set; }
        public bool IsTurningRight { get; set; }
        public bool IsSpeedingUp { get; set; }
        public bool IsSlowingDown { get; set; }

        public int Index { get; set; }
        public int Laps { get; set; }
        public string PilotName { get; set; }

        #endregion properties

        #region methods
        public bool IsColliding(Kart other)
        {
            bool ret = false;

            var dX = other.CarTranslateTransform.X - this.CarTranslateTransform.X;
            var dY = other.CarTranslateTransform.Y - this.CarTranslateTransform.Y;
            var h = Math.Sqrt(dX * dX + dY * dY);

            ret = (h < 40);

            return ret;
        }

        public void ResolveCollision(Kart other)
        {
            Vector position = new Vector(this.CarTranslateTransform.X, this.CarTranslateTransform.Y);
            Vector otherPosition = new Vector(other.CarTranslateTransform.X, other.CarTranslateTransform.Y);

            // get the mtd
            Vector delta = (position - otherPosition);
            double d = delta.Length;
            // minimum translation distance to push balls apart after intersecting
            var radius = 40.0;

            Vector mtd = delta * ((float)(((radius + 1.0 + radius + 1.0) - d) / d));

            // resolve intersection --
            // inverse mass quantities
            float im1 = 0.1f;
            float im2 = 0.1f;

            // push-pull them apart based off their mass
            position = position + ((mtd * (im1 / (im1 + im2))));
            otherPosition = otherPosition - (mtd * (im2 / (im1 + im2)));

            // impact speed
            var rad = (this.CarRotateTransform.Angle % 360.0) / (2.0 * Math.PI);
            var translateVelocity = new Vector(this.Speed * Math.Cos(rad) + this.Velocity2D.X, this.Speed * Math.Sin(rad) + this.Velocity2D.Y);
            var otherTranslateVelocity = new Vector(other.Speed * Math.Cos(rad) + other.Velocity2D.X, other.Speed * Math.Sin(rad) + other.Velocity2D.Y);
            Vector v = (translateVelocity - (otherTranslateVelocity));
            Vector mtdNormalize = new Vector(mtd.X, mtd.Y);
            mtdNormalize.Normalize();
            double vn = Vector.CrossProduct(v, mtdNormalize);

            // collision impulse
            Vector impulse = mtd * (0.05);

            // change in momentum
            translateVelocity = translateVelocity + (impulse * (im1));
            otherTranslateVelocity = otherTranslateVelocity - (impulse * (im2));


            this.CarTranslateTransform.X = position.X;
            this.CarTranslateTransform.Y = position.Y;
            other.CarTranslateTransform.X = otherPosition.X;
            other.CarTranslateTransform.Y = otherPosition.Y;

            this.Velocity2D = translateVelocity;
            other.Velocity2D = otherTranslateVelocity;

            var angleDiff = this.CarRotateTransform.Angle - other.CarRotateTransform.Angle;

            this.CarRotateTransform.Angle += angleDiff;
            other.CarRotateTransform.Angle += angleDiff;
        }

        #endregion methods

        #region events
        public static void WheelAngleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Kart kart = d as Kart;
            kart.LeftWheelRotation.Angle =
            kart.RightWheelRotation.Angle = (double)e.NewValue;
        }
        public static void MaxSpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Kart kart = d as Kart;
            kart.MaxSpeed = (double)e.NewValue;
        }
                
        public static void BodyColor1Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Kart kart = d as Kart;
            kart.bodyColorGradient1.Color = (Color)e.NewValue;
            kart.bodyColorGradient5.Color = (Color)e.NewValue;
        }

        public static void BodyColor2Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Kart kart = d as Kart; 
            kart.bodyColorGradient2.Color = (Color)e.NewValue;
            kart.bodyColorGradient4.Color = (Color)e.NewValue;
        }

        public static void BodyColor3Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Kart kart = d as Kart;
            kart.bodyColorGradient3.Color = (Color)e.NewValue;
            kart.mirrors.Fill = new SolidColorBrush((Color)e.NewValue);
        }
        #endregion events
    }
}

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
Instructor / Trainer Alura Cursos Online
Brazil Brazil

Comments and Discussions