Click here to Skip to main content
15,892,059 members
Articles / Multimedia / DirectX

Night Stalker

Rate me:
Please Sign up or sign in to vote.
4.26/5 (10 votes)
27 Jan 2010CPOL15 min read 47.8K   693   36  
A C# game using Sprite-Editor graphics, way-points for AI controlled characters, and a mini-map collision detection scheme.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Night_Stalker
{
    public class classBullet
    {
        static int uniqueIDCounter;
        int myUniqueIdNumber = uniqueIDCounter++;
        public classCollisionDetection.udtCDInfo udrCDInfo = new classCollisionDetection.udtCDInfo();
        public Point pt;
        public double dblAngle;
        enuDir dir;
        public bool bolJessicafireedThisBullet = false;
        int intStepSize = 10;
        int intDamageICause = 25;
       
        public classRobot robotThatShotMe;
        public classBullet next;
        public classBullet prev;
        public bool bolDead;
        static Microsoft.DirectX.AudioVideoPlayback.Audio DXHardHit;

        public enum bulletType { colt, laser, SmurfAttack, FelixFire, bulletEater, bunkerBuster }
        public bulletType myType;
        classCollisionDetection cLibCD;
        classHelperFunctions cLibHelper;

        public static Sprite.classSprite[] sprite;
        public int intConfig, intConfigStep, intSizeStep;
        Sprite.enuMirror mirror = Sprite.enuMirror.none;

        public enum enuColt_Configurations // same as laser & Smurf-attack
        {
            fly_up,
            fly_high,
            fly_straight,
            fly_low,
            fly_down,
            _numCon
        }

        public enum enuFelix_Fire_Configurations
        {
            fly_high,
            fly_straight,
            fly_low,
            _numCon
        }

        public classBullet(bulletType type,
                           Point ptLoc,
                           double dblTravelDirection,
                           bool bolJessicaBullet,
                           ref classHelperFunctions Helper)
        {
            cLibHelper = Helper;
            cLibCD = cLibHelper.cLibCD;
            myType = type;
            pt = ptLoc;
            dblAngle = dblTravelDirection;

            dir = convertAngleToDir(dblAngle);
            
            setConfig();
            bolJessicafireedThisBullet = bolJessicaBullet;
            setCDInfo();
            setStepSize();
            bolDead = false;
            if (DXHardHit == null)
            {
                string strDirectorAndFilename = cLibHelper.getResourceDirectoryString() + cLibHelper.strDX_HitHard;
                DXHardHit = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDirectorAndFilename);
                initSprites();
            }

            if (myType == bulletType.bunkerBuster)
                cLibHelper.bulletDebug = this;

        }

        /// <summary>
        /// DO NOT USE WITH ANY THING OTHER THAN THE BULLETS!
        /// </summary>
        /// <param name="angleRad"></param>
        /// <returns></returns>
        enuDir convertAngleToDir(double angleRad)
        {
            int intAngle = (int)(cLibHelper.cleanAngle(angleRad) * 180 / Math.PI);

            int intE = 180/8;
            int intStep = 180/4;

            if (intAngle < intE)
                return enuDir.E_;
            else if (intAngle < (intE + intStep))
                return enuDir.SE;
            else if (intAngle < (intE + 2 * intStep))
                return enuDir.S_;
            else if (intAngle < (intE + 3 * intStep))
                return enuDir.SW;
            else if (intAngle < (intE + 4 * intStep))
                return enuDir.W_;
            else if (intAngle < (intE + 5 * intStep))
                return enuDir.NW;
            else if (intAngle < (intE + 6 * intStep))
                return enuDir.N_;
            else 
                return enuDir.NE;
        }

        void initSprites()
        {
            sprite = new Sprite.classSprite[6];
            Sprite.classSpriteMaker cLibSpriteMaker = new Sprite.classSpriteMaker();
            string strDir = cLibHelper.getResourceDirectoryString();
            sprite[(int)bulletType.colt] = cLibSpriteMaker.loadSprite(strDir + "colt.spr");
            sprite[(int)bulletType.laser] = cLibSpriteMaker.loadSprite(strDir + "laser.spr");
            sprite[(int)bulletType.FelixFire] = cLibSpriteMaker.loadSprite(strDir + "FelixFire.spr");
            sprite[(int)bulletType.bulletEater] = cLibSpriteMaker.loadSprite(strDir + "bulleteater.spr");
            sprite[(int)bulletType.SmurfAttack] = cLibSpriteMaker.loadSprite(strDir + "Smurf-attack.spr");
            sprite[(int)bulletType.bunkerBuster] = cLibSpriteMaker.loadSprite(strDir + "bunkerbuster.spr");
        }

        void animateNext(ref Bitmap bmpMap)
        {
            if (next != null)
                next.animate(ref bmpMap);
        }

        void die()
        {
            if (cLibCD.bulletQ == this)
                cLibCD.bulletQ = this.next;

            if (prev != null)
                prev.next = next;
            if (next != null)
                next.prev = prev;

            if (bolJessicafireedThisBullet)
                cLibCD.Jessica.bolMyBulletIsStillFlying = false;

            bolDead = true;
        }

        public void animate(ref Bitmap bmpMap)
       {
           Point ptNewLoc = new Point((int)(pt.X + (double)intStepSize * Math.Cos(dblAngle)),
                                      (int)(pt.Y + (double)intStepSize * Math.Sin(dblAngle)));
           bool bolDie = false;
           if (IHitAWall(ref ptNewLoc))
           {
               animateNext(ref bmpMap);
               bolDie = true;
           }

           if (bolJessicafireedThisBullet)
           {
               classRobot robotIHit = IHitARobot(ref ptNewLoc);
               if (robotIHit != null)
               {
                   robotIHit.Hit(intDamageICause);
                   if (robotIHit.bolDead)
                       cLibCD.Jessica.Score(robotIHit.getMyValue());
                   else
                   {
                       cLibHelper.playSound(DXHardHit);
                       bolDie = true;
                   }
               }

               if (IHitBulletEater(ref ptNewLoc))
               {
                   cLibHelper.playBulletEaten();
                   bolDie = true;
               }
           }
           else
           {
               if (IHitJessica(ref ptNewLoc))
               {
                   cLibCD.Jessica.Die();
                   bolDie = true;
               }

               classRobot PestIHit = cLibCD.HitAPest(pt, ref ptNewLoc, udrCDInfo);
               if (PestIHit != null)
               {
                   PestIHit.Hit(intDamageICause);
                   if (!PestIHit.bolDead)
                       bolDie = true;
               }

               if (myType == bulletType.bulletEater 
                   || myType == bulletType.bunkerBuster)
               {
                   if (cLibHelper.cLibCD.Jessica.myBullet != null
                       && !cLibCD.Jessica.myBullet.bolDead)
                   {
                       int intLimit = intStepSize * 2;
                       int intDistance = (int)Math.Sqrt(Math.Pow(ptNewLoc.X - robotThatShotMe.Jessica.myBullet.pt.X, 2) + Math.Pow(ptNewLoc.Y - robotThatShotMe.Jessica.myBullet.pt.Y, 2));
                       Point ptRememberLoc = ptNewLoc;
                       if (intDistance < intLimit)
                           if (cLibCD.CollisionBetweenTwoCDInfoObjects(pt, ref ptNewLoc, udrCDInfo, robotThatShotMe.Jessica.myBullet.pt, robotThatShotMe.Jessica.myBullet.udrCDInfo))
                           {
                               robotThatShotMe.Jessica.myBullet.bolDead = true;
                               cLibHelper.playBulletEaten();
                           }

                       ptNewLoc = ptRememberLoc;
                   }
               }
           }

           pt = ptNewLoc;

           switch (myType)
           {
               case bulletType.colt:
               case bulletType.laser:
               case bulletType.SmurfAttack:
               case bulletType.FelixFire:
                   sprite[(int)myType].putConfigurationOnScreen(ref bmpMap, intConfig,0 , ptNewLoc,0,1.0, mirror, false);
                   break;

               case bulletType.bulletEater:
               case bulletType.bunkerBuster:
                   intConfigStep = (intConfigStep + 1) % sprite[(int)bulletType.bulletEater].Configurations[0].steps.Length;
                   intSizeStep = (intSizeStep+1) % 8;
                   double dblSize = 1.0;
                   switch (intSizeStep)
                   {                     
                       case 0 :
                           dblSize = 0.2;
                           break;

                       case 1:
                           dblSize = 0.4;
                           break;

                       case 2 :
                           dblSize = 0.6;
                           break;

                       case 3:
                           dblSize = 0.8;
                           break;

                       case 4 :
                           dblSize = 0.9;
                           break;
                       case 5:
                           dblSize = 0.8;
                           break;

                       case 6:
                           dblSize = 0.6;
                           break;

                       case 7:
                           dblSize = 0.4;
                           break;
                   }

                   sprite[(int)myType].putConfigurationOnScreen(ref bmpMap, 0, intConfigStep, ptNewLoc, 0, dblSize, mirror,false);
                   setCDInfo();
                   break;
           }
           setCDInfo();
           if (cLibCD.bolDrawCDInfo)
               cLibCD.drawCDInfo(ref bmpMap, udrCDInfo, pt);

           if (!bolDie)
            animateNext(ref bmpMap);

           if (bolDie)
               die();
       }

        bool IHitBulletEater(ref Point ptLoc)
        {
            classBullet thisBullet = cLibCD.bulletQ;
            while (thisBullet != null)
            {
                if (thisBullet != this)
                {
                    if (thisBullet.myType == bulletType.bulletEater
                        || thisBullet.myType == bulletType.bunkerBuster)
                    {
                        int intLimit = intStepSize * 2;
                        int intDistance = (int)Math.Sqrt(Math.Pow(ptLoc.X - thisBullet.pt.X, 2) + Math.Pow(ptLoc.Y - thisBullet.pt.Y,2));
                        if (intDistance < intLimit)
                            if (cLibCD.CollisionBetweenTwoCDInfoObjects(pt, ref ptLoc, udrCDInfo, thisBullet.pt, thisBullet.udrCDInfo))
                                return true;
                    }
                }
                thisBullet = thisBullet.next;
            }
            return false;
        }

        void setConfig()
        {
            switch (myType)
            {
                case bulletType.colt:
                case bulletType.laser:
                case bulletType.SmurfAttack:
                    switch (dir)
                    {
                        case enuDir.E_:
                        case enuDir.W_:
                            intConfig = (int)enuColt_Configurations.fly_straight;
                            break;

                        case enuDir.NE:
                        case enuDir.NW:
                            intConfig = (int)enuColt_Configurations.fly_high;
                            break;

                        case enuDir.SE:
                        case enuDir.SW:
                            intConfig = (int)enuColt_Configurations.fly_low;
                            break;

                        case enuDir.N_:
                            intConfig = (int)enuColt_Configurations.fly_up;
                            break;

                        case enuDir.S_:
                            intConfig = (int)enuColt_Configurations.fly_down;
                            break;
                    }

                    mirror =Sprite. enuMirror.none;
                    if (dir >= Night_Stalker.enuDir.N_ && dir < Night_Stalker.enuDir.S_)
                        mirror = Sprite.enuMirror.horizontal;
                    break;

                case bulletType.FelixFire:
                    switch (dir)
                    {
                        case enuDir.E_:
                        case enuDir.W_:
                        case enuDir.N_:
                        case enuDir.S_:
                            intConfig = (int)enuFelix_Fire_Configurations.fly_straight;
                            break;

                        case enuDir.NE:
                        case  enuDir.SW:
                            intConfig = (int)enuFelix_Fire_Configurations.fly_high;
                            break;

                        case enuDir.NW:
                        case enuDir.SE:
                            intConfig = (int)enuFelix_Fire_Configurations.fly_low;
                            break;
                    }
                    break;

                case bulletType.bulletEater:
                case bulletType.bunkerBuster:
                    intConfig = 0;
                    break;
            }
        }

        void setDamageICause()
        {
            switch (myType)
            {
                case bulletType.bulletEater:
                case bulletType.bunkerBuster:
                case bulletType.colt:
                case bulletType.laser:
                case bulletType.SmurfAttack:
                    intDamageICause = 25;
                    break;
            }
        }

        void setStepSize()
        {
            switch (myType)
            {
                case bulletType.bulletEater:
                case bulletType.bunkerBuster:
                case bulletType.colt:
                case bulletType.laser:
                case bulletType.SmurfAttack:
                case bulletType.FelixFire:
                default:
                    intStepSize = (int)(cLibCD.Jessica.intStepSize * 2.0);
                    break;
            }
        }

        void setCDInfo()
        {
            switch (myType)
            {
                case bulletType.bulletEater:
                case bulletType.bunkerBuster:
                    switch (intSizeStep)
                    {
                        case 0:
                            udrCDInfo.ptRelPos = new Point(1, 1);
                            udrCDInfo.sz = new Size(2, 2);
                            break;

                        case 1:
                            udrCDInfo.ptRelPos = new Point(2, 2);
                            udrCDInfo.sz = new Size(4, 4);
                            break;

                        case 2:
                            udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(8, 8);
                            break;

                        case 3:
                            udrCDInfo.ptRelPos = new Point(5, 5);
                            udrCDInfo.sz = new Size(10, 10);
                            break;

                        case 4:
                            udrCDInfo.ptRelPos = new Point(5, 5);
                            udrCDInfo.sz = new Size(11, 11);
                            break;

                        case 5:
                            udrCDInfo.ptRelPos = new Point(5, 5);
                            udrCDInfo.sz = new Size(10, 10);
                            break;

                        case 6:
                            udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(8, 8);
                            break;

                        case 7:
                            udrCDInfo.ptRelPos = new Point(2, 2);
                            udrCDInfo.sz = new Size(4, 4);
                            break;
                    }
                    break;

                case bulletType.colt:
                    udrCDInfo.ptRelPos = new Point(1, 1);
                    udrCDInfo.sz = new Size(2, 2);
                    break;

                case bulletType.laser:
                case bulletType.SmurfAttack:
                    switch (dir)
                    {
                        case enuDir.N_:
                        case enuDir.S_:
                            udrCDInfo.ptRelPos = new Point(1, 1);
                            udrCDInfo.sz = new Size(1, 3);
                            break;

                        case enuDir.E_:
                        case enuDir.W_:
                            udrCDInfo.ptRelPos = new Point(1,1);
                            udrCDInfo.sz = new Size(3, 1);
                            break;

                        default:
                            udrCDInfo.ptRelPos = new Point(1, 1);
                            udrCDInfo.sz = new Size(2, 2);
                            break;
                    }
                    break;

                case bulletType.FelixFire:
                    udrCDInfo.ptRelPos = new Point(2, 2);
                    udrCDInfo.sz = new Size(4, 4);
                    break;
            }
        }

        /// <summary>
        /// tests if this bullet hits Jessica
        /// </summary>
        /// <returns>returns true if bullet hits Jessica</returns>
        public bool IHitJessica(ref Point ptNewLoc)
        {
            if (bolJessicafireedThisBullet)
                return false;

            return cLibCD.CollisionBetweenTwoCDInfoObjects(pt, ref ptNewLoc, udrCDInfo, cLibCD.Jessica.ptLoc, cLibCD.Jessica.udrCDInfo);
        }

        /// <summary>
        /// tests if this bullet hits a wall
        /// </summary>
        /// <returns>returns true if this bullet hits a wall</returns>
        public bool IHitAWall(ref Point ptNewLoc)
        {
            return !cLibCD.move(pt, ref ptNewLoc, udrCDInfo, false, (myType == bulletType.bunkerBuster));
        }

        /// <summary>
        /// tests if this bullet hits a robot only if Jessica fireed this bullet
        /// </summary>
        /// <returns>returns the robot this bullet hits only if the bullet was fired by Jessica</returns>
        public classRobot IHitARobot(ref Point ptNewLoc)
        {
            if (!bolJessicafireedThisBullet)
                return null;

            return cLibCD.HitARobot(pt, ref ptNewLoc, udrCDInfo);
        }

    }
}

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
CEO unemployable
Canada Canada
Christ Kennedy grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University. He is unemployable and currently living in Moncton, N.B. writing his next novel.

Comments and Discussions