TankClass.cs :  » Game » Killer-Instinct » KillerInstinct » Sprites » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Game » Killer Instinct 
Killer Instinct » KillerInstinct » Sprites » TankClass.cs
using System;
using System.Drawing;
using Microsoft.DirectX.DirectDraw;
using Global;
using Global.GlobalClass;
using KillerInstinct.DirectX;

namespace KillerInstinct.Sprites{
  public class TankClass : SpriteClass
  {
    // tank constants
    private const int SHOTDELAY      = 50;  // how often to allow a shot to be fired
    private const int ENERGYLOW_DELAY  = 200;  // how often to play "energy low" sound
    private const int ENERGYLOW_START  = 15;  // when to start warning player that energy is low
    private const int MAX_BAR_ENERGY  = 100;  // maximum energy displayed in bar
    private const int MAX_SHIELD    = 100;  // maximum allowed shields
    private const int MAX_WEAPONS    = 20;  // maximum weapons we are allowed to have
    private const int START_ENERGY    = 100;  // starting (unless handicapped?) and maximum tank energy
    // ...
    private ProgressBarClass  m_energyBar    = null;  // our energy/health meter
    private ShotClass.Weapon[]  m_weapons    = new ShotClass.Weapon[MAX_WEAPONS];  // store information about each weapon
    private ShotClass.ShotTypes  m_shotType    = ShotClass.ShotTypes.Basic;  // default to shot #1 (Shot0.bmp / Shot0.wav)
    private ShotClass.ShotTypes m_altShotType  = ShotClass.ShotTypes.AltBasic; // default to alternate shot #1 (Shot10.bmp, Shot10.wav)
    private int          m_shield    = 0;  // current shield level
    private int          m_lowDelay    = 0;
    private int          m_shotDelay    = 0;  // time till next shot allowed
    private int          m_shotAltDelay  = 0;  // time till next alternative shot allowed
    private int          m_maxShotAltDelay= 0;
    private int          m_playerTeam  = 0;
    private bool        m_readyToShoot  = true;  // flag to indicate if ready to shoot again
    private bool        m_readyToShootAlt= true;// flag to indicate if ready to shoot (alternative) again
    private bool        m_ai      = false;// if this tank is artificial intelligence
    //private SpriteListClass    m_spriteList;  // to get information about other tank sprites
    public bool AI
    {
      get
      { return m_ai; }
    }
    // returns ammunition count for current PRIMARY weapon
    public int AmmoCount
    {
      get
      { return m_weapons[(int)m_shotType].ammo; }
      set
      {
        m_weapons[(int)m_shotType].ammo = value;
        // if an unlimited "regen" weapon, reset regeneneration time
        if (m_weapons[(int)m_shotType].unlimited == true)
          m_weapons[(int)m_shotType].lastRegen = System.Environment.TickCount;
        // ensure max ammunition is not over-stepped
        if (m_weapons[(int)m_shotType].ammo > m_weapons[(int)m_shotType].maxAmmo)
          m_weapons[(int)m_shotType].ammo = m_weapons[(int)m_shotType].maxAmmo;
      }
    }
    // returns ammunition count for current SECONDARY weapon
    public int AltAmmoCount
    {
      get
      { return m_weapons[(int)m_altShotType].ammo; }
      set
      {
        m_weapons[(int)m_altShotType].ammo = value;
        // if an unlimited "regen" weapon, reset regeneneration time
        if (m_weapons[(int)m_altShotType].unlimited == true)
          m_weapons[(int)m_altShotType].lastRegen = System.Environment.TickCount;
        // ensure max ammunition is not over-stepped
        if (m_weapons[(int)m_altShotType].ammo > m_weapons[(int)m_altShotType].maxAmmo)
          m_weapons[(int)m_altShotType].ammo = m_weapons[(int)m_altShotType].maxAmmo;
      }
    }
    // returns maximum allowed ammunition for this PRIMARY weapon
    public int AmmoMax
    {
      get
      { return m_weapons[(int)m_shotType].maxAmmo; }
    }
    // returns maximum allowed ammunition for this SECONDARY weapon
    public int AltAmmoMax
    {
      get
      { return m_weapons[(int)m_altShotType].maxAmmo; }
    }
    // get or set whether we are ready to shoot
    public bool ReadyToShoot
    {
      get
      { return m_readyToShoot; }
      set
      { m_readyToShoot = value; }
    }
    // get or set whether we are ready to shoot alternative weapon
    public bool ReadyToShootAlt
    {
      get
      { return m_readyToShootAlt; }
      set
      { m_readyToShootAlt = value; }
    }
    // returns constant resource string with current shot type + ".bmp"
    public string ShotBitmap
    {
      get
      { return (CONST.BMP_SHOT + (int)m_shotType + ".bmp"); }
    }
    // returns constant resource string with current alternate shot type + ".bmp"
    public string AltShotBitmap
    {
      get
      { return (CONST.BMP_SHOT + (int)m_altShotType + ".bmp"); }
    }
    // returns constant resource string with current shot type + ".wav"
    public string ShotSound
    {
      get
      { return (SoundClass.SOUND_SHOT + (int)m_shotType + ".wav"); }
    }
    // returns constant resource string with current alternate shot type + ".wav"
    public string AltShotSound
    {
      get
      { return (SoundClass.SOUND_SHOT + (int)m_altShotType + ".wav"); }
    }
    // returns MINIMUM amount of damage the current PRIMARY shot can do
    public int MinShotDamage
    {
      get
      { return (m_weapons[(int)m_shotType].minDamage); }
    }
    // returns MINIMUM amount of damage the current SECONDARY shot can do
    public int MinAltShotDamage
    {
      get
      { return (m_weapons[(int)m_altShotType].minDamage); }
    }
    // returns MAXIMUM amount of damage the current PRIMARY shot can do
    public int MaxShotDamage
    {
      get
      { return (m_weapons[(int)m_shotType].maxDamage); }
    }
    // returns MAXIMUM amount of damage the current SECONDARY shot can do
    public int MaxAltShotDamage
    {
      get
      { return (m_weapons[(int)m_altShotType].maxDamage); }
    }
    // returns CURRENT range of currently selected PRIMARY weapon
    public int ShotRange
    {
      get
      { return m_weapons[(int)m_shotType].range; }
    }
    // returns CURRENT range of currently selected SECONDARY weapon
    public int ShotAltRange
    {
      get
      { return m_weapons[(int)m_altShotType].range; }
    }
    // sets PRIMARY shot number which is used to return resource file names, e.g. .bmp or .wav files
    public ShotClass.ShotTypes ShotType
    {
      get
      { return m_shotType; }
      set
      {
        // set weapon type only if we actually have it (i.e. ammo > -1)
        if (m_weapons[(int)value].ammo > -1)
          m_shotType = value;
      }
    }
    // sets SECONDARY shot number which is used to return resource file names, e.g. .bmp or .wav files
    public ShotClass.ShotTypes AltShotType
    {
      get
      { return m_altShotType; }
      set
      {
        // set weapon type only if we actually have it (i.e. ammo > -1)
        if (m_weapons[(int)value].ammo > -1)
          m_altShotType = value;
      }
    }
    public int Shield
    {
      get
      { return m_shield; }
      set
      {
        m_shield = value;
        // if we over-stepped max allowed energy, top off at maximum
        if (m_shield > MAX_SHIELD)
          m_shield = MAX_SHIELD;
        // or if we went negative (that's bad), set to 0
        else if (m_shield < 0)
          m_shield = 0;
        global.dbg.Out(Debug.DBG1, "TankClass.Shield set to [" + m_shield + "]");
      }
    }
    public int PlayerTeam
    {
      get
      { return m_playerTeam; }
    }
    // returns ammunition for given shot type
    public int GetAmmoCount(int shotType)
    {
      return (m_weapons[shotType].ammo);
    }
    // returns maximum ammunition for given shot type
    public int GetAmmoMax(int shotType)
    {
      return (m_weapons[shotType].maxAmmo);
    }
    // returns weapon color
    public Color GetWeaponColor(int shotType)
    {
      return (m_weapons[shotType].color);
    }
    // handles changing an AI's weapon
    private void ChangeAIWeapon()
    {/*
      ShotClass.ShotTypes lastIdx = ShotClass.ShotTypes.Basic;
      int  lastAmmoCount = 0;
      for(int i=0; i < m_weapons.Length; ++i)
      {
        if (m_weapons[i].ammo > lastAmmoCount)
        {
          lastAmmoCount = m_weapons[i].ammo;
          lastIdx = (ShotClass.ShotTypes)i;
        }
      }
      // don't change weapons if weapon is already selected
      if (ShotType != lastIdx)
        ShotType = lastIdx;*/
      ShotType = ShotClass.ShotTypes.Basic;
    }
    public int GetMinDamage(int shotType)
    {
      return (m_weapons[shotType].minDamage);
    }
    public int GetMaxDamage(int shotType)
    {
      return (m_weapons[shotType].maxDamage);
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    // TANK ///////////////////////////////////////////////////////////////////////////////////////////////
    public TankClass(string file, float x, float y, int playerId, string name, bool useAI, int playerTeam, int skill)
    {
      global.dbg.Out(Debug.DBG2, "TankClass called, file=[" + file + "] x=[" + x + "] y=[" + y + "] id=[" + playerId + "] name=[" + name + "] useAI=[" + useAI + "] team=[" + playerTeam + "] skill=[" + skill + "]");
      // set our parent ID to ourself (to avoid our own shots colliding with ourself!)
      this.parentId  = (ulong)playerId;
      this.globalId  = (ulong)playerId;
      // sprite attributes
      frame.Width    = 64;
      frame.Height  = 64;
      framesCount    = 40;
      framesPerRow  = 10;
      layer           = LAYER_TANK;
      // starting direction
      whichFrame    = global.random(0, framesCount-1);
      // vehicle attributes
      maxSpeed    = 1.5f;
      maxSpeedBack  = 0.75f;
      acceleration  = 0.25f;
      // starting Speed
      Speed      = 0;
      // type of collision
      collisionType = CollisionType.Pixel;
      // player identity for DirectPlay
      playerId    = playerId;
      playerName    = name;
      m_ai      = useAI;
      m_playerTeam  = playerTeam;
      Energy      = 100;
      Skill      = skill;
      m_maxShotAltDelay = 50;
      // initialize ammunition for all weapon types
      // weapon #1 REGENERATE (slow, low damage, middle range)
      m_weapons[(int)ShotClass.ShotTypes.Basic].shotType    = ShotClass.ShotTypes.Basic;
      m_weapons[(int)ShotClass.ShotTypes.Basic].ammo      = 5;
      m_weapons[(int)ShotClass.ShotTypes.Basic].maxAmmo    = 5;
      m_weapons[(int)ShotClass.ShotTypes.Basic].unlimited    = true;
      m_weapons[(int)ShotClass.ShotTypes.Basic].regenRate    = 3000;
      m_weapons[(int)ShotClass.ShotTypes.Basic].minDamage    = 15;
      m_weapons[(int)ShotClass.ShotTypes.Basic].maxDamage    = 25;
      m_weapons[(int)ShotClass.ShotTypes.Basic].range      = 300;
      m_weapons[(int)ShotClass.ShotTypes.Basic].maxRange    = 300;
      m_weapons[(int)ShotClass.ShotTypes.Basic].speed      = 3.0f;
      m_weapons[(int)ShotClass.ShotTypes.Basic].color      = Color.DarkGreen;

      // weapon #2 NORMAL (fast, middle damage, middle range)
      m_weapons[(int)ShotClass.ShotTypes.L2].shotType      = ShotClass.ShotTypes.L2;
      m_weapons[(int)ShotClass.ShotTypes.L2].ammo        = 10;
      m_weapons[(int)ShotClass.ShotTypes.L2].maxAmmo      = 25;
      m_weapons[(int)ShotClass.ShotTypes.L2].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.L2].minDamage    = 5;
      m_weapons[(int)ShotClass.ShotTypes.L2].maxDamage    = 20;
      m_weapons[(int)ShotClass.ShotTypes.L2].range      = 300;
      m_weapons[(int)ShotClass.ShotTypes.L2].maxRange      = 300;
      m_weapons[(int)ShotClass.ShotTypes.L2].speed      = 4.0f;
      m_weapons[(int)ShotClass.ShotTypes.L2].color      = Color.OrangeRed;
      
      // weapon #3 DAMAGE (slow, hard damage, short range)
      m_weapons[(int)ShotClass.ShotTypes.L3].shotType      = ShotClass.ShotTypes.L3;
      m_weapons[(int)ShotClass.ShotTypes.L3].ammo        = 10;
      m_weapons[(int)ShotClass.ShotTypes.L3].maxAmmo      = 25;
      m_weapons[(int)ShotClass.ShotTypes.L3].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.L3].minDamage    = 35;
      m_weapons[(int)ShotClass.ShotTypes.L3].maxDamage    = 55;
      m_weapons[(int)ShotClass.ShotTypes.L3].range      = 250;
      m_weapons[(int)ShotClass.ShotTypes.L3].maxRange      = 250;
      m_weapons[(int)ShotClass.ShotTypes.L3].speed      = 3.5f;
      m_weapons[(int)ShotClass.ShotTypes.L3].color      = Color.PowderBlue;

      // weapon #4 RANGE (very fast, low damage, wide range)
      m_weapons[(int)ShotClass.ShotTypes.L4].shotType      = ShotClass.ShotTypes.L4;
      m_weapons[(int)ShotClass.ShotTypes.L4].ammo        = 10;
      m_weapons[(int)ShotClass.ShotTypes.L4].maxAmmo      = 25;
      m_weapons[(int)ShotClass.ShotTypes.L4].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.L4].minDamage    = 15;
      m_weapons[(int)ShotClass.ShotTypes.L4].maxDamage    = 25;
      m_weapons[(int)ShotClass.ShotTypes.L4].range      = 400;
      m_weapons[(int)ShotClass.ShotTypes.L4].maxRange      = 400;
      m_weapons[(int)ShotClass.ShotTypes.L4].speed      = 6.0f;
      m_weapons[(int)ShotClass.ShotTypes.L4].color      = Color.RoyalBlue;

      // alternate basic weapon (NORMAL)
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].shotType  = ShotClass.ShotTypes.AltBasic;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].ammo    = 10;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].maxAmmo  = 10;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].unlimited  = true;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].regenRate  = 500;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].minDamage  = 1;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].maxDamage  = 5;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].range    = 175;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].maxRange  = 175;
      m_weapons[(int)ShotClass.ShotTypes.AltBasic].speed    = 3.0f;

      // alternate weapon level 2 (COUNT)
      m_weapons[(int)ShotClass.ShotTypes.AltL2].shotType    = ShotClass.ShotTypes.AltL2;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].ammo      = 50;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].maxAmmo    = 100;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].minDamage    = 5;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].maxDamage    = 10;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].range      = 200;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].maxRange    = 200;
      m_weapons[(int)ShotClass.ShotTypes.AltL2].speed      = 4.0f;

      // alternate basic level 3 (DAMAGE)
      m_weapons[(int)ShotClass.ShotTypes.AltL3].shotType    = ShotClass.ShotTypes.AltL3;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].ammo      = 25;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].maxAmmo    = 100;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].minDamage    = 7;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].maxDamage    = 15;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].range      = 250;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].maxRange    = 250;
      m_weapons[(int)ShotClass.ShotTypes.AltL3].speed      = 5.0f;

      // alternate basic level 4 (FLAME)
      m_weapons[(int)ShotClass.ShotTypes.AltL4].shotType    = ShotClass.ShotTypes.AltL4;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].ammo      = 25;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].maxAmmo    = 100;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].unlimited    = false;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].minDamage    = 1;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].maxDamage    = 25;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].range      = 350;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].maxRange    = 350;
      m_weapons[(int)ShotClass.ShotTypes.AltL4].speed      = 2.5f;

      // add a health status bar above our tank
      m_energyBar = new ProgressBarClass(56, 4, START_ENERGY, START_ENERGY, Color.Black, Color.Red, Color.Black);
      // draw our tank
      Init(file, CONST.COLORKEY_WHITE, x, y);
      // set again in case SpriteClass.Init() over-wrote it with a debug name
      playerName = name;
    }
    // this gets called every frame
    public override void Update()
    {
      // calculate our new coordinates
      posX = posX + (Speed * (float)Math.Sin(((180-whichFrame*frameAngle)*Math.PI)/180));
      posY = posY - (Speed * (float)Math.Cos(((180-whichFrame*frameAngle)*Math.PI)/180));
      // if our new coordinates are out of the playing field, stop the tank!
      if ((posX<=0) || (posX>=global.options.SCR_WIDTH-frame.Width) || 
        (posY<=0) || (posY>=global.options.SCR_HEIGHT-frame.Height))
        Speed = 0;
      // bounce off a wall?
      BounceScreenEdge();
      // ready for next shot?
      if (m_shotDelay < SHOTDELAY)
      {
        m_shotDelay++;
      }
      else
      {
        m_shotDelay = 0;
        m_readyToShoot = true;
      }
      // don't allow alternative shot #4 to shoot too often
      if (AltShotType == ShotClass.ShotTypes.AltL4)
      {
        // ready for next shot?
        if (m_shotAltDelay < m_maxShotAltDelay)
        {
          m_shotAltDelay++;
        }
        else
        {
          m_shotAltDelay = 0;
          m_readyToShootAlt = true;
        }
      }
      else
      {
        m_readyToShootAlt = true;
      }
      // if this is a bot (aritificial intelligence) then handle their next move
      if (m_ai)
      {
        DoAI();
      }
      // regenerates any weapons with "unlimited" ammo according to their 'regenRate'
      for(int i=0; i < m_weapons.Length; ++i)
      {
        // if this weapon is unlimited...
        if (m_weapons[i].unlimited == true)
        {
          // ...AND the weapon is NOT already full...
          if (m_weapons[i].ammo < m_weapons[i].maxAmmo)
          {
            // if current TickCount (1000) - last regen TickCount (990) > regen Rate (10)...
            if ((System.Environment.TickCount - m_weapons[i].lastRegen) > m_weapons[i].regenRate)
            {
              // ...regenerate ammo...
              ++m_weapons[i].ammo;
              // ...and remember our last regeneration time for next time
              m_weapons[i].lastRegen = System.Environment.TickCount;
            }
          }
        }
      }
    }
    // 1. draw tank's energy bar
    // 2. draw tank's shields
    // 3. draw tank's name
    // 4. call base-class SpriteClass.Draw()
    public new void Draw()
    {
      // redraw remaining energy/health bar
      // health bar only displays 100, if over 100, draw 2nd, brighter bar over 1st bar
      if (Energy > MAX_BAR_ENERGY)
      {
        if (global.options.showEnergyBar)
        {
          m_energyBar.Draw((int)posX+1, (int)posY-3, MAX_BAR_ENERGY);
          m_energyBar.Draw((int)posX+1, (int)posY-3, Energy-MAX_BAR_ENERGY, Color.Gold);
        }
      }
      else
      {
        if (global.options.showEnergyBar)
          m_energyBar.Draw((int)posX+1, (int)posY-3, Energy);
      }
      // shield color
      int colorRed = 55;
      int colorGreen = 85;
      int colorBlue = 185;
      int radius = 22;
      // draw multiple levels of shields (if we have any)
      for(int level=0; level <= MAX_SHIELD; level += 20)
      {
        if (Shield > level)
        {
          // draw a shield layer
          global.DC.DrawCircle((int)posX+(frame.Width/2), (int)posY+(frame.Height/2), radius, Color.FromArgb(colorRed, colorGreen, colorBlue));
          // re-adjust color and radius for next time
          colorRed += 20;
          colorGreen += 20;
          colorBlue += 15;
          radius += 1;
        }
        else
          break;
      }
      // display name of sprite
      if ((playerName.Length>0) && (global.options.showNames))
      {
        global.DC.DrawText((int)posX, (int)(posY), playerName, Color.Black);
      }
      // draw the sprite
      base.Draw();
    }
    // determines if tank's Energy is low and plays a warning sound occasionally if it is
    public void IsEnergyLow()
    {
      // if we are still alive...
      if (active)
      {
        // play low-energy sound if tank's energy is "low" (and is NOT '0')
        if ((Energy<=ENERGYLOW_START) && (Energy>0)) 
        {
          // only play the sound every "ENERGYLOW_DELAY" game ticks
          if (m_lowDelay < ENERGYLOW_DELAY)
          {
            m_lowDelay++;
          }
          else
          {
            m_lowDelay = 0;
            global.SC.Play(SoundClass.SOUND_LOWENERGY, false);
          }
        }
      }
    }
    // primary shot (e.g. left-click)
    public void Shoot()
    {
      global.dbg.Out(Debug.DBG2, "TankClass.Shoot: " + playerName);
      // if we are still alive...
      if (active)
      {
        if (ReadyToShoot) 
        {
          ReadyToShoot = false;
          // if there is still some ammo left...
          if (AmmoCount > 0)
          {
            // fire a shot!
            ShotClass shot = new ShotClass(  m_weapons[(int)m_shotType],
              posX+(frame.Width/2-9/2)+ 25*(float)Math.Sin(((180-whichFrame*frameAngle)*Math.PI)/180),
              posY+(frame.Height/2-9/2)-25*(float)Math.Cos(((180-whichFrame*frameAngle)*Math.PI)/180),
              this.globalId);
            if (shot != null)
            {
              // draw proper shot sprite based on tank direction
              shot.direction = whichFrame;
              // send shot packet
              if (global.options.multiplayer)
                global.PC.Shoot(shot);
              global.SC.Play(ShotSound, false);
              // add new sprite to the global sprite list
              global.spriteList.Add(shot);
              // decrement amount of ammo we have left
              --AmmoCount;
            }
          }
            // play out of ammo sound
          else
          {
            //TODO: play different out of ammo sound per weapon???
            global.SC.Play(SoundClass.SOUND_SHOTEMPTY, false);
          }
        }
      }
    }
    // secondary shot (e.g. right-click)
    public void ShootAlternativ(Point p)
    {
      global.dbg.Out(Debug.DBG2, "TankClass.ShootAlternativ: " + playerName);
      if (active)
      {
        if (ReadyToShootAlt)
        {
          ReadyToShootAlt = false;
          // if there is still some ammo left...
          if (AltAmmoCount > 0)
          {
            ShotClass shot = new ShotClass(  m_weapons[(int)m_altShotType], 
              posX+frame.Width/2-2,
              posY+frame.Height/2-2,
              this.globalId);
            if (shot != null)
            {
              shot.frameAngle = 1;

              if ((p.X>=(posX+frame.Height/2)) && (p.Y>=(posY+frame.Width/2)))
                shot.direction = (float)(Math.Atan2((p.Y-posY-frame.Height/2),(p.X-posX-frame.Width/2))*180/Math.PI);
              else if ((p.X>=(posX+frame.Height/2)) && (p.Y<=(posY+frame.Width/2)))
                shot.direction = (float)(Math.Atan2((p.Y-posY-frame.Height/2),(p.X-posX-frame.Width/2))*180/Math.PI);
              else if ((p.X<=(posX+frame.Height/2)) && (p.Y<=(posY+frame.Width/2)))
                shot.direction = (float)(Math.Atan2((p.Y-posY-frame.Height/2),(p.X-posX-frame.Width/2))*180/Math.PI);
              else if ((p.X<=(posX+frame.Height/2)) && (p.Y>=(posY+frame.Width/2)))
                shot.direction = (float)(Math.Atan2((p.Y-posY-frame.Height/2),(p.X-posX-frame.Width/2))*180/Math.PI);
              // send shot packet
              if (global.options.multiplayer)
                global.PC.Shoot(shot);
              // play a sound
              global.SC.Play(AltShotSound, false);
              global.spriteList.Add(shot);
              // decrement amount of ammo we have left
              --AltAmmoCount;
            }
          }
            // play out of ammo sound
          else
          {
            //TODO: play different out of ammo sound per weapon???
            global.SC.Play(SoundClass.SOUND_SHOTEMPTY, false);
          }
        }
      }
      else
      {
        global.dbg.Out(Debug.DBG2, "TankClass.ShootAlternativ: couldn't add alternativ shot for " + playerName + ", cause not active");
      }
    }
    // if we were hit by something, calculate shield/energy losses/gains
    public override void ReactToCollision(SpriteClass s)
    {
      // if we are still alive...
      if (active)
      {
        // hit by a shot of something
        if (s.GetType() == typeof(ShotClass))
        {
          global.dbg.Out(Debug.DBG2, "TankClass.ReactToCollision: player=[" + this.playerName + "] shot [" + s.file + "]");
          // "calculate" damage
          int damage = global.random(GetMinDamage((int)((ShotClass)s).ShotType), GetMaxDamage((int)((ShotClass)s).ShotType));
          // if the calculated shield damage wasn't enough, take away some energy as well
          if (Shield < damage)
          {
            Energy -= (damage - Shield);
            Shield -= 0;
          }
          // otherwise just remove shields
          else
          {
            Shield -= damage;
          }
          global.dbg.Out(Debug.DBG3, "          -- damage [" + damage + "]");
          // handle further specifics based on each shot type
          switch (((ShotClass)s).ShotType)
          {
            case ShotClass.ShotTypes.Basic:
              Speed -= 1.0f;
              break;
            case ShotClass.ShotTypes.L2:
              Speed -= 0.5f;
              break;
            case ShotClass.ShotTypes.L3:
              Speed = 0.0f;
              break;
            case ShotClass.ShotTypes.L4:
              Speed = 0.0f;
              break;
            case ShotClass.ShotTypes.AltBasic:
            case ShotClass.ShotTypes.AltL2:
              Speed -= 0.1f;
              break;
            case ShotClass.ShotTypes.AltL3:
              Speed -= 0.15f;
              break;
            case ShotClass.ShotTypes.AltL4:
              Speed -= 0.35f;
              break;
            default:
              global.dbg.Out(Debug.ERR, "TankClass.ReactToCollision: player=[" + this.playerName + "] unknown shot type [" + ((ShotClass)s).ShotType + "]");
              break;
          }
        }
        // crashed into a tank
        else if (s.GetType() == typeof(TankClass))
        {
          global.dbg.Out(Debug.DBG2, "TankClass.ReactToCollision: player=[" + this.playerName + "] tank [" + s + "]");
          //global.dbg.Out(Debug.TRACE, "TankClass.ReactToCollision: Speed=[" + Speed + "] maxS=[" + maxSpeed + "]");
          // bounce off the other tank
          BounceObject(s);
          // stop tank
          Speed = 0;
        }
        // crashed into a tree
        else if (s.GetType() == typeof(TreeClass))
        {
          global.dbg.Out(Debug.DBG2, "TankClass.ReactToCollision: player=[" + this.playerName + "] tank [" + s + "]");
          // bounce off the other tank
          BounceObject(s);
          // stop tank
          Speed = 0;
        }
        // picked up a power-up
        else if (s.GetType() == typeof(PowerupClass))
        {
          global.dbg.Out(Debug.DBG2, "TankClass.ReactToCollision: player=[" + this.playerName + "] powerup [" + s + "]");
          switch (((PowerupClass)s).Powerup)
          {
            //TODO: handle secondary weapon pick-ups...
            case PowerupClass.PowerupType.Energy:
              global.dbg.Out(Debug.DBG2, "TankClass picked up energy powerup, amount=[" + ((PowerupClass)s).Amount + "]");
              Energy += ((PowerupClass)s).Amount;
              break;
            case PowerupClass.PowerupType.Shield:
              global.dbg.Out(Debug.DBG2, "TankClass picked up shield powerup, amount=[" + ((PowerupClass)s).Amount + "]");
              Shield += ((PowerupClass)s).Amount;
              break;
            case PowerupClass.PowerupType.Weapon:
              global.dbg.Out(Debug.DBG2, "TankClass picked up weapon powerup, weapon=[" + ((PowerupClass)s).Weapon + "]");
              break;
            case PowerupClass.PowerupType.Ammo:
              global.dbg.Out(Debug.DBG2, "TankClass picked up ammo powerup, weapon=[" + ((PowerupClass)s).Weapon + "] amount=[" + ((PowerupClass)s).Amount + "]");
              AmmoCount += ((PowerupClass)s).Amount;
              break;
            default:
              global.dbg.Out(Debug.ERR, "TankClass picked up unknown powerup, powerup=[" + ((PowerupClass)s).Powerup + "] amount=[" + ((PowerupClass)s).Amount + "] weapon=[" + ((PowerupClass)s).Weapon + "]");
              break;
          }
        }
        else
        {
          global.dbg.Out(Debug.WARN, "TankClass.ReactToCollision: player=[" + this.playerName + "] SOMETHING ELSE?? [" + s + "]");
        }
        // picked up a power-down!
        //else if (s.GetType() == typeof(PowerdownClass))
        //{
        //}
        // are we dead?
        //if (Energy < 1)
          
      }
    }
    private void DoAI()
    {
      // set speed
      speed = ((float)Skill)*0.25f;
      TankClass enemy = global.spriteList.GetNearestEnemy(this);
      // if a tank was found...
      if (enemy != null)
      {
        global.dbg.Out(Debug.DBG3, "Nearest enemy tank, name=[" + enemy.playerName + "] x=[" + enemy.posX + "/" + posX + "] y=[" + enemy.posY + "/" + posY + "]");
        //
        //enemy.whichFrame
        //
        // which direction to turn
        if (posX>enemy.posX && posY>enemy.posY)
        {
          global.dbg.Out(Debug.DBG3, "Tank.AIMove(1)");
          if (whichFrame>=0 && whichFrame<9)
          {
            global.dbg.Out(Debug.DBG3, "Tank.AIMove(1.1)");
            if (global.random(0,1) == 0)
              TurnLeft();
            else
              TurnRight();
          }
          else if (whichFrame>=9 && whichFrame<19)
          {
            global.dbg.Out(Debug.DBG3, "Tank.AIMove(1.2)");
            TurnLeft();
          }
          else if (whichFrame>=19 && whichFrame<29)
          {
            global.dbg.Out(Debug.DBG3, "Tank.AIMove(1.3)");
            // TODO: more exactly decision for turning
          }
          else if (whichFrame>=29 && whichFrame<39)
          {
            global.dbg.Out(Debug.DBG3, "Tank.AIMove(1.4)");
            TurnRight();
          }
        }
        else if (posX>enemy.posX && posY<enemy.posY)
        {
          global.dbg.Out(Debug.DBG3, "Tank.AIMove(2)");
          if (whichFrame>=0 && whichFrame<9)
          {
            TurnRight();
          }
          else if (whichFrame>=9 && whichFrame<19)
          {
            if (global.random(0,1) == 0)
              TurnLeft();
            else
              TurnRight();
          }
          else if (whichFrame>=19 && whichFrame<29)
          {
            TurnLeft();
          }
          else if (whichFrame>=29 && whichFrame<39)
          {
            // TODO: more exactly decision for turning
          }
        }
        else if (posX<enemy.posX && posY<enemy.posY)
        {
          global.dbg.Out(Debug.DBG3, "Tank.AIMove(3)");
          if (whichFrame>=0 && whichFrame<9)
          {
            // TODO: more exactly decision for turning
          }
          else if (whichFrame>=9 && whichFrame<19)
          {
            TurnRight();
          }
          else if (whichFrame>=19 && whichFrame<29)
          {
            if (global.random(0,1) == 0)
              TurnLeft();
            else
              TurnRight();
          }
          else if (whichFrame>=29 && whichFrame<39)
          {
            TurnLeft();
          }
        }
        else if (posX<enemy.posX && posY>enemy.posY)
        {
          global.dbg.Out(Debug.DBG3, "Tank.AIMove(4)");
          if (whichFrame>=0 && whichFrame<9)
          {
            TurnLeft();
          }
          else if (whichFrame>=9 && whichFrame<19)
          {
            // TODO: more exactly decision for turning
          }
          else if (whichFrame>=19 && whichFrame<29)
          {
            if (global.random(0,1) == 0)
              TurnLeft();
            else
              TurnRight();
          }
          else if (whichFrame>=29 && whichFrame<39)
          {
            TurnRight();
          }
        }
      }

      // turn if we are too close to the LEFT-...
      if (posX < 100)
      {
        if (posY < 100)                // ...UPPER corner
          TurnLeft();
        else if (posY > global.options.SCR_HEIGHT-200)  // ...BOTTOM corner
          TurnRight();
        else                    // ...wall...
          TurnRight();
      }
      // turn if we are too close to the RIGHT-...
      else if (posX > global.options.SCR_WIDTH-100)
      {
        if (posY < 150)                // ...UPPER corner
          TurnLeft();
        else if (posY > global.options.SCR_HEIGHT-150)  // ...BOTTOM corner
          TurnLeft();
        else                    // ...wall...
          TurnRight();
      }
      // turn if we are too close to the TOP
      else if (posY < 150)
      {
        TurnLeft();
      }
      // turn if we are too close to the BOTTOM
      else if (posY > global.options.SCR_HEIGHT-150)
      {
        TurnRight();
      }
      // if we are not near a wall, use this speed
      else
      {
        // turn randomly left or right
        int dir = global.random(0, 100);
        if (dir == 0 || dir == 1)
          TurnLeft();
        if (dir == 2)
          TurnRight();
      }
      // if command-line parameter '-noAIShoot' was NOT used...
      if (global.options.noAIShoot == false)
      {
        // choose weapon with the most ammunition
        if (global.random(0, 50) == 0)
          ChangeAIWeapon();
        // choose secondary weapon with the most ammunition
        //else if (global.random(0, 30) == 0)
        //ChangeAIWeapon();
        // fire a PRIMARY shot every once in a while
        if ((global.random(0, 100)==0))
          Shoot();
        // fire a SECONDARY shot every once in a while
        int enemyDistance = global.spriteList.GetDistance(this, enemy);
        if (enemyDistance<ShotAltRange)
        {
          if (enemyDistance<ShotAltRange/2)
          {
            if ((global.random(0, 3)==0))
              ShootAlternativ(new Point((int)enemy.posX, (int)enemy.posY));
          }
          else
          {
            if ((global.random(0, 10)==0))
              ShootAlternativ(new Point((int)enemy.posX, (int)enemy.posY));
          }
        }
      }
    }
    private void BounceObject(SpriteClass s)
    {
      Rectangle rIntersect = new Rectangle((int)posX, (int)posY, CollisionBox.Width, CollisionBox.Height);
      Rectangle r2 = new Rectangle((int)s.posX, (int)s.posY, s.CollisionBox.Width, s.CollisionBox.Height);
      // get intersecting rectangle
      rIntersect.Intersect(r2);
      // if object is on top-left, bounce down-right
      if (rIntersect.X < posX && rIntersect.Y < posY)
      {
        //global.dbg.Out(Debug.TRACE, "BounceObject: bouncing down-right (xy=" + posX + "," + posY + "  s.xy=" + s.posX + "," + s.posY + ")");
        posX += 0.5f;
        posY += 0.5f;
      }
      // if object is on top-right, bounce down-left
      if (rIntersect.X >= posX && rIntersect.Y < posY)
      {
        //global.dbg.Out(Debug.TRACE, "BounceObject: bouncing down-left (xy=" + posX + "," + posY + "  s.xy=" + s.posX + "," + s.posY + ")");
        posX -= 0.5f;
        posY += 0.5f;
      }
      // if object is on bottom-left, bounce up-right
      if (rIntersect.X < posX && rIntersect.Y >= posY)
      {
        //global.dbg.Out(Debug.TRACE, "BounceObject: bouncing up-right (xy=" + posX + "," + posY + "  s.xy=" + s.posX + "," + s.posY + ")");
        posX += 0.5f;
        posY -= 0.5f;
      }
      // if object is on bottom-right, bounce up-left
      if (rIntersect.X >= posX && rIntersect.Y >= posY)
      {
        //global.dbg.Out(Debug.TRACE, "BounceObject: bouncing up-left (xy=" + posX + "," + posY + "  s.xy=" + s.posX + "," + s.posY + ")");
        posX -= 0.5f;
        posY -= 0.5f;
      }
    }
    private void BounceScreenEdge()
    {
      // Top
      if (posY <= InfoBarClass.BAR_HEIGHT)
      {
        posY = InfoBarClass.BAR_HEIGHT;
        // head into right direction
        if (whichFrame>0 && whichFrame<20) 
          if (posX+frame.Width < global.options.SCR_WIDTH-1) 
            posX += 0.25f; 
        // head into left direction
        else if (whichFrame>20)
          if (posX>1)
            posX -= 0.25f;
      }
      // Bottom
      else if (posY+frame.Height >= global.options.SCR_HEIGHT-1)
      {
        posY = global.options.SCR_HEIGHT-frame.Height-1;
        // head into right direction
        if (whichFrame>0 && whichFrame<20) 
          if (posX+frame.Width < global.options.SCR_WIDTH-1) 
            posX += 0.25f; 
        // head into left direction
        else if (whichFrame>20)
          if (posX>1)
            posX -= 0.25f;
      }
      // Left
      else if (posX <= 1)
      {
        posX = 1;
        // head up
        if (whichFrame<10 || whichFrame>30) 
          if (posY+frame.Width < global.options.SCR_WIDTH-1)
            posY += 0.25f; 
        // head down
        else if (whichFrame>20 && whichFrame<30)
          if (posY > InfoBarClass.BAR_HEIGHT)
            posY -= 0.25f;
      }
      // Right
      else if (posX+frame.Width >= global.options.SCR_WIDTH-1)
      {
        posX = global.options.SCR_WIDTH-frame.Width-1;
        // head up
        if (whichFrame<10 || whichFrame>30) 
          if (posY+frame.Width < global.options.SCR_WIDTH-1)
            posY += 0.25f; 
          // head down
        else if (whichFrame>20 && whichFrame<30)
          posY -= 0.25f;
      }
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.