Click here to Skip to main content
15,892,809 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;
using Sprite;

namespace Night_Stalker
{
    public class classJessica
    {
        public classSprite Sprite;
        public Point ptLoc;
        public classCollisionDetection.udtCDInfo udrCDInfo;
        public enum enuJessica_Rabbit_Configurations
        {
            Walk_new,
            Shoot_Straight,
            Shoot_High,
            Shoot_Low,
            Shoot_Up,
            Shoot_Down,
            standStill,
            Stand_flick_far_hair,
            Stand_hold_gun_up,
            Stand_flick_near_hair_with_gun,
            Stand_fix_far_shoe,
            Stand_fix_near_shoe,
            Stand_scratch_far_calf_with_gun,
            stand_scratch_head,
            stand_swipe_near_arm_with_far_hand,
            go_to_sleep,
            wake_up,
            _numCon
        }

        public struct udtRunAfterFireGun
        {
            public bool flag;
            public enuDir dir;
        }

        public udtRunAfterFireGun udrRunAfterFireGun;
        public int intNumStandConfigurations = -1; // set in CountNumStandConfigurations()

        classCollisionDetection cLibCD;
        classHelperFunctions cLibHelper;
        public enuJessica_Rabbit_Configurations configID;
        public int intConfigStep;
        public int intStepSize = 15;
        Random rnd = new Random();

        Night_Stalker.enuDir dir;

        public Point ptJessicaStartLoc = new Point(500, 280);
        public bool bolMyBulletIsStillFlying = false;
        bool bolGoToSleep = false;
        public Point ptLocBeforeSleepShift = new Point();

        public int intLives = 3;
        public int intBullets = 0;
        public int intScore = 0;

        Microsoft.DirectX.AudioVideoPlayback.Audio DXGun;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXDieScream;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXEmptyChamber;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXReload;
        Microsoft.DirectX.AudioVideoPlayback.Audio DXFreeLife;

        public System.Windows.Forms.PictureBox[] picBullets;
        classGun gun;
        public enuMirror mirror = enuMirror.none;
        int intDrowsyCounter = 0;
        public classBullet myBullet;
            
        public classJessica(ref classHelperFunctions Helper,
                            ref classCollisionDetection CollisionLibrary)
        {
            cLibHelper = Helper;
            cLibCD = CollisionLibrary;
            gun = new classGun(ref cLibHelper);

            classSpriteMaker cLibMaker = new classSpriteMaker();
            Sprite = cLibMaker.loadSprite(cLibHelper.getResourceDirectoryString() + "Jessica Rabbit Small.spr");
            countNumStandConfigurations();

            string strDir = cLibHelper.getResourceDirectoryString();
            DXGun = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_Colt45);
            DXDieScream = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_dieScream);
            DXEmptyChamber = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_EmptyChamber);
            DXReload = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_Reload);
            DXFreeLife = new Microsoft.DirectX.AudioVideoPlayback.Audio(strDir + cLibHelper.strDX_FreeLife);
            setCDInfo();
        }

        public void init()
        {
            configID = enuJessica_Rabbit_Configurations.standStill;
            setCDInfo();
            ptLoc = ptJessicaStartLoc;
            cLibCD.setJessicaLocation();
            bolMyBulletIsStillFlying = false;
            udrRunAfterFireGun.flag = false;
            intBullets = 0; showBullets();
            intDrowsyCounter = 0;
            intConfigStep = 0;
            placeGun();
        }

        /// <summary>
        /// any number of Jessica configurations can be added to the sprite and as long as they are in sequence
        /// this function will use them in the stand animation alternating between 'standstill' and any of the others at random intervals
        /// </summary>
        void countNumStandConfigurations()
        {
            intNumStandConfigurations = 0;
            for (enuJessica_Rabbit_Configurations conCounter = 0; conCounter < enuJessica_Rabbit_Configurations._numCon; conCounter++)
            {
                string strConCounter = conCounter.ToString().ToUpper().Trim();
                if (strConCounter.Substring(0, "stand".Length).CompareTo("STAND") == 0
                    && strConCounter.CompareTo("STANDSTILL") != 0)
                    intNumStandConfigurations++;
            }
        }

        /// <summary>
        /// allows the robots & bullets to give Jessica a score when they are killed
        /// </summary>
        /// <param name="intPoints">number of points earned by Jessica</param>
        public void Score(int intPoints)
        {
            int intNewScore = intScore + intPoints;
            bool bolFreelife = false;
            if (intScore <= 10000 && intNewScore > 10000)
                bolFreelife = true;
            else
            {
                int intStepValue = 50000;

                int intModStep_Old = intScore % intStepValue;
                int intModStep_New = intNewScore % intStepValue;

                bolFreelife = (intModStep_New < intModStep_Old);
            }

            if (bolFreelife)
            {
                intLives++;
                cLibHelper.playSound(DXFreeLife);
            }
            intScore += intPoints;
        }

        /// <summary>
        /// Animate Jessica's Action
        /// </summary>
        public void animate(ref Bitmap bmp) { animate(ref bmp, configID, dir); }
        /// <summary>
        /// Animate Jessica's Action
        /// </summary>
        /// <param name="config">set the action Jessica is to do</param>
        /// <param name="direction">set the direction in which Jessica is to perform this action</param>
        /// <param name="bmp">reference bitmap variable onto which Jessica's action will be drawn</param>
        public void animate(ref Bitmap bmp, enuJessica_Rabbit_Configurations config, Night_Stalker.enuDir direction)
        {
            if (bolGoToSleep)
            {
                bolGoToSleep = false;
                ptLocBeforeSleepShift = ptLoc;
                configID = enuJessica_Rabbit_Configurations.go_to_sleep;
                intConfigStep = 0;
            }

            double dblSleepYShiftMax = 80;
                        
            switch (configID)
            {
                case enuJessica_Rabbit_Configurations.Shoot_Up:
                case enuJessica_Rabbit_Configurations.Shoot_High:
                case enuJessica_Rabbit_Configurations.Shoot_Straight:
                case enuJessica_Rabbit_Configurations.Shoot_Low:
                case enuJessica_Rabbit_Configurations.Shoot_Down:
                    if (intConfigStep == 0)
                        FireGun();
                    break;
            }
         
            dir = direction;
         
            if ( configID == enuJessica_Rabbit_Configurations.Walk_new)
            {
                Point ptNewLoc = new Point(ptLoc.X +(int)(  intStepSize * cLibHelper.ptDirMoveSigns[(int)dir].X ),
                                           ptLoc.Y + intStepSize * cLibHelper.ptDirMoveSigns[(int)dir].Y);
                cLibCD.move(ptLoc, ref ptNewLoc, udrCDInfo, true, false);
                ptLoc = ptNewLoc;
                testPickUpGun();
            }
            
            if (Action == enuJessica_Rabbit_Configurations.Walk_new
                && (ActionDirection == enuDir.N_ || ActionDirection == enuDir.S_))
                ;
            else if (dir >= Night_Stalker.enuDir.N_ && dir < Night_Stalker.enuDir.S_)
                mirror = enuMirror.horizontal;
            else
                mirror = enuMirror.none;

            string configName = configID.ToString().ToUpper();
            if (configName.Length > "stand".Length && configName.Substring(0, "stand".Length).CompareTo("STAND") == 0)
            {
                Sprite.putConfigurationOnScreen(ref bmp, (int)configID, intConfigStep, ptLoc, 0, 1.0, mirror, false);
                classConfiguration thisConfiguration = Sprite.Configurations[(int)configID];
                intConfigStep = (intConfigStep + 1) % thisConfiguration.steps.Length;
                // when end of this 'stand' routine choose to standstill or animate
                if (intConfigStep == 0)
                    if (((int)(rnd.NextDouble() * 1000)) % 3 == 0) // 1:2 chance of animation
                        configID = (enuJessica_Rabbit_Configurations)((int)enuJessica_Rabbit_Configurations.standStill + (int)(rnd.NextDouble() * 1000) % (intNumStandConfigurations + 1));  // randomly pick one of the six stand-animations
                    else
                        configID = enuJessica_Rabbit_Configurations.standStill;
            }
            else            
                switch (configID)
                {
                    case enuJessica_Rabbit_Configurations.Walk_new:
                        Sprite.putConfigurationOnScreen(ref bmp, (int)configID, intConfigStep, ptLoc, 0, 1.0, mirror, false);
                        intConfigStep = (intConfigStep + 1) % Sprite.Configurations[(int)configID].steps.Length;
                        break;

                    case enuJessica_Rabbit_Configurations.go_to_sleep:
                        double[] dblYShift_GoToSleep = { 1.0, 1.0, 0.9, .8, .7, .7, .6, .6, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5 ,.5};
                        ptLoc = new Point(ptLocBeforeSleepShift.X, (int)(ptLocBeforeSleepShift.Y + dblSleepYShiftMax * (1.0 - dblYShift_GoToSleep[intConfigStep])));
                        setCDInfo();
                        cLibCD.stretchJessicaAwayFromWall();
                        ptLoc = new Point(ptLocBeforeSleepShift.X, (int)(ptLocBeforeSleepShift.Y + dblSleepYShiftMax * (1.0 - dblYShift_GoToSleep[intConfigStep])));

                        Sprite.putConfigurationOnScreen(ref bmp, (int)configID, intConfigStep, ptLoc, 0, 1.0, mirror, false);
                        
                        intConfigStep = (intConfigStep + 1) % Sprite.Configurations[(int)configID].steps.Length;
                        if (intConfigStep == 0)
                        {
                            configID = enuJessica_Rabbit_Configurations.wake_up;
                            intDrowsyCounter = 50;
                        }
                        break;

                    case enuJessica_Rabbit_Configurations.wake_up:
                        double[] dblYShift_WakeUp = { .5, .5, .5, .5, .5, .5, .6, .8, .9, 1.0, 1.0 };
                        ptLoc = new Point(ptLocBeforeSleepShift.X, (int)(ptLocBeforeSleepShift.Y + dblSleepYShiftMax * (1.0 - dblYShift_WakeUp[intConfigStep])));
                        setCDInfo();
                        cLibCD.stretchJessicaAwayFromWall();
                        ptLoc = new Point(ptLocBeforeSleepShift.X, (int)(ptLocBeforeSleepShift.Y + dblSleepYShiftMax * (1.0 - dblYShift_WakeUp[intConfigStep])));

                        Sprite.putConfigurationOnScreen(ref bmp, (int)configID, intConfigStep, ptLoc, 0, 1.0, mirror, false);
                        
                        intConfigStep = (intConfigStep + 1) % Sprite.Configurations[(int)configID].steps.Length;
                        if (intConfigStep == 0)
                        {
                            configID = enuJessica_Rabbit_Configurations.standStill;
                            setCDInfo();
                        }
                        break;

                    default:
                        Sprite.putConfigurationOnScreen(ref bmp, (int)configID, intConfigStep, ptLoc, 0, 1.0, mirror, false);
                        intConfigStep = (intConfigStep + 1) % Sprite.Configurations[(int)configID].steps.Length;
                        if (intConfigStep == 0)
                        {
                            if (udrRunAfterFireGun.flag)
                            {
                                configID = enuJessica_Rabbit_Configurations.Walk_new;
                                dir = udrRunAfterFireGun.dir;
                                udrRunAfterFireGun.flag = false;
                            }
                            else
                                configID = enuJessica_Rabbit_Configurations.standStill;
                            intConfigStep = 0;
                        }
                        break;
                }

            if (cLibCD.bolDrawCDInfo)
                cLibCD.drawCDInfo(ref bmp, udrCDInfo, ptLoc);

            if (intDrowsyCounter > 0)
            {
                intDrowsyCounter--;
                cLibCD.bolEnableSnares = true;
            }
            else
                cLibCD.bolEnableSnares = false;

            if (intBullets < 1)
                gun.animate(ref bmp);
        }
        
        public void setCDInfo()
        {            
            switch (configID)
            {
                case enuJessica_Rabbit_Configurations.wake_up:
                    switch (intConfigStep)
                    {
                        case 0:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(12, 2);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 2);
                            udrCDInfo.sz = new Size(16, 4);
                            break;

                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(9, 3);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 3);
                            udrCDInfo.sz = new Size(14, 9);
                            break;

                        case 6:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(6, 3);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 3);
                            udrCDInfo.sz = new Size(10, 9);
                            break;

                        case 7:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(3, 4);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(7, 11);
                            break;

                        case 8:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(4, 4);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(7, 14);
                            break;

                        default:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(4, 4);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(7, 15);
                            break;
                    }
                    break;

                case enuJessica_Rabbit_Configurations.go_to_sleep:
                    switch (intConfigStep)
                    {
                        case 0:
                        case 1:
                            udrCDInfo.ptRelPos = new Point(4, 4);
                            udrCDInfo.sz = new Size(7, 15);
                            break;

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

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

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

                        case 6:
                        case 7:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(7, 3);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 3);
                            udrCDInfo.sz = new Size(10, 9);
                            break;

                        case 8:
                            if (mirror == enuMirror.none)
                                udrCDInfo.ptRelPos = new Point(9, 3);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 3);
                            udrCDInfo.sz = new Size(14, 7);
                            break;

                        default:
                            if (mirror == enuMirror.none) 
                            udrCDInfo.ptRelPos = new Point(12, 2);
                            else
                                udrCDInfo.ptRelPos = new Point(4, 2);
                            udrCDInfo.sz = new Size(16, 4);
                            break;
                    }
                    break;

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

        public void gotosleep() 
        {
            if (configID == enuJessica_Rabbit_Configurations.go_to_sleep
                || configID == enuJessica_Rabbit_Configurations.wake_up)
                return;
            bolGoToSleep = true; 
        }

        void testPickUpGun()
        {
            if (intBullets < 1)
            {
                int intLimit = 40;
                int intDistance =(int)Math.Ceiling( Math.Sqrt(Math.Pow(ptLoc.X - gun.pt.X, 2) + Math.Pow(ptLoc.Y - gun.pt.Y, 2)));
                if (intDistance < intLimit)
                {
                    cLibHelper.playSound(DXReload);
                    intBullets = 6;
                    showBullets();
                }
            }
        }

        /// <summary>
        /// Jessica shoots a bullet from her gun in the ActionDirection
        /// </summary>
        void FireGun()
        {
            if (bolMyBulletIsStillFlying || intBullets < 1)
            {
                cLibHelper.playSound(DXEmptyChamber);
                return;
            }
            double dblAngle = -(double)dir * Math.PI / 4.0;

            Point ptGunHand = Sprite.conCurrent.getLimbPos("gunhand(near)", mirror, intConfigStep, 0);
            Point ptBulletLoc = new Point(ptLoc.X + ptGunHand.X, ptLoc.Y + ptGunHand.Y);
            classBullet myBullet = new classBullet(classBullet.bulletType.colt, ptBulletLoc, dblAngle, true, ref cLibHelper);

            cLibCD.enQBullet(ref myBullet);

            cLibHelper.playSound(DXGun);
            bolMyBulletIsStillFlying = true;
            intBullets--;
            showBullets();
            if (intBullets < 1)
                placeGun();
        }

        public void showBullets()
        {
            for (int intBulletCounter = 0; intBulletCounter < 6; intBulletCounter++)
                picBullets[intBulletCounter].Visible = (intBullets > intBulletCounter);
        }

        public void placeGun()
        {
            // pick a location away from some central point near the right of the screen
            double dblXShift = 0.7;
            Point ptCenterRnd = new Point((int)(cLibHelper.cLibWPs.bmpWPs.Width * dblXShift), cLibHelper.cLibWPs.bmpWPs.Height / 2);
            udtShortestPathToWayPoint udrSPtoWP = new udtShortestPathToWayPoint();
            udrSPtoWP.wp = null;

            while (udrSPtoWP.wp == null)
            {
                Point ptRnd = new Point(-1, -1);
                double dblAngle = cLibHelper.rnd.NextDouble() * 2.0 * Math.PI;
                int intRadius = cLibHelper.getRnd((int)(cLibHelper.cLibWPs.bmpWPs.Width * dblXShift));

                while (!cLibHelper.isValidLocOnWPMap(ptRnd))
                {
                    intRadius -= 5;
                    ptRnd = new Point((int)(ptCenterRnd.X + intRadius * Math.Cos(dblAngle)),
                                      (int)(ptCenterRnd.Y + intRadius * Math.Sin(dblAngle)));
                }

                udrSPtoWP = cLibHelper.cLibWPs.findNearestWayPoint(ptRnd);
            }
            gun.pt = udrSPtoWP.wp.pt;
        }
        /// <summary>
        /// 
        /// </summary>
        public void Die()
        {
            intLives--;
            cLibHelper.newCorpse(ptLoc, classCorpse.enuCorpseType.human);
            init();
            cLibHelper.playSound(DXDieScream);
        }

        /// <summary>
        /// get/set Jessica's action direction
        /// </summary>
        public Night_Stalker.enuDir ActionDirection
        {
            get { return dir; }
            set
            { dir = value; }
        }

        /// <summary>
        /// get/set jessica's move (e.g. walkright, shoot straight)
        /// </summary>
        public enuJessica_Rabbit_Configurations Action
        {
            get { return configID; }
            set
            {
                switch (configID)
                {
                    case enuJessica_Rabbit_Configurations.wake_up:
                    case enuJessica_Rabbit_Configurations.go_to_sleep:
                        break;

                    default:
                        configID = value;
                        break;
                }
            }
        }
    }

    public class classGun
    {
        public Point pt;
        public classSprite sprite;
        int intConfigStep = 0;
        classHelperFunctions cLibHelper;

        public classGun(ref classHelperFunctions Helper)
        {
            cLibHelper = Helper;
            classSpriteMaker cLibMaker = new classSpriteMaker();
            sprite = cLibMaker.loadSprite(cLibHelper.getResourceDirectoryString() + "gun.spr");
        }

        public void animate(ref Bitmap bmp)
        {
            intConfigStep = (intConfigStep + 1) % sprite.Configurations[0].steps.Length;
            sprite.putConfigurationOnScreen(ref bmp, 0, intConfigStep, pt, 0,1.0, enuMirror.none, false);
        }
    }

   
}

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