SpriteListClass.cs :  » Game » Killer-Instinct » KillerInstinct » 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 » SpriteListClass.cs
using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.DirectX.DirectDraw;
using Global;
using Global.GlobalClass;
using KillerInstinct.DirectX;
using KillerInstinct.Sprites;

namespace KillerInstinct{
  public class LayerCompareClass : IComparer
  {
    int IComparer.Compare(Object x, Object y)
    {
      return ((new CaseInsensitiveComparer()).Compare(((SpriteClass)x).layer.ToString(), ((SpriteClass)y).layer.ToString()));
    }
  }
  public class SpriteListClass
  {
    public  const int  MAX_MESSAGES    = 10;    // maximum number of messages to allow on screen at one time
    public  const int  TEXT_SPACE      = 12;    // space to leave between text chat messages
    private const int   SORT_TIMER      = 500;    // how long to wait before sorting sprite list
    private const int  DEFAULT_DELETE_TIME  = 10000;  // default time to wait before deleting text object
    private ArrayList  List, TextList;
    public  ulong    spriteCount      = 0;    // increments on add, used to set unique playerId
    private bool    ListChanged      = false;
    private int      lastSortTime    = 0;    // how long since we last sorted (TickCount)
    private int      m_enemyEnergy    = 0;    // how much energy ALL of the current enemies have
    public  Resource[]  resourceList;
    public struct Resource
    {
      public string    file;
      public Surface    surface;      // bitmap attributes
      public SurfaceDescription description;  // bitmap attributes
      public Bitmap      bmp;        // bitmap attributes
    }
    public int EnemyEnergy
    {
      get
      { return m_enemyEnergy; }
      set
      {
        m_enemyEnergy = value;
        if (m_enemyEnergy < 0)
        {
          global.dbg.Out(Debug.WARN, "SpriteListClass.EnemyEnergy < 0 [" + m_enemyEnergy + "] val=[" + value + "]");
          m_enemyEnergy = 0;
        }
        global.dbg.Out(Debug.TRACE, "SpriteListClass.EnemyEnergy=[" + m_enemyEnergy + "]");
      }
    }
    public struct TextObject
    {
      private int      m_createTime;
      private int      m_deleteTime;
      private string    m_text;
      public  int      m_x, m_y;
      public  Color    m_color;

      public Color Color
      {
        get
        { return m_color; }
      }
      public int CreateTime
      {
        get
        { return m_createTime; }
      }
      public int DeleteTime
      {
        get
        { return m_deleteTime; }
      }
      public string Text
      {
        get
        { return m_text; }
      }
      public int X
      {
        get
        { return m_x; }
      }
      public int Y
      {
        get
        { return m_y; }
      }
      // TODO: OVERLOADED: add text object using default time
      /*public TextObject(string text)
      {
        TextObject(text, DEFAULT_DELETE_TIME);
      }*/
      public TextObject(string text, int deleteTime)
      {
        m_text      = text;
        m_x        = 10;
        m_y        = global.options.SCR_HEIGHT-150;
        m_color      = Color.Black;
        // use default deletion (cleanup) time if none specified
        if (deleteTime <= 0)
          m_deleteTime = DEFAULT_DELETE_TIME;
        else
          m_deleteTime = deleteTime;
        // save our creation time so we know when to delete (based on m_delay)
        m_createTime  = System.Environment.TickCount;
      }
    }
    public SpriteListClass()
    {
      // do a one-time load of all resources (*.bmp, etc)
      if (LoadResources() == true)
      {
        List    = new ArrayList();
        TextList  = new ArrayList();
      }
    }
    private void SortList()
    {
      if (System.Environment.TickCount - lastSortTime > SORT_TIMER)
      {
        global.dbg.Out(Debug.DBG1, "Sorting sprite list.");
        // re-sort the list
        IComparer layerComparer = new LayerCompareClass();
        List.Sort(0, List.Count, layerComparer);
        // reset time since last sort
        lastSortTime = System.Environment.TickCount;
      }
    }
    // add to sprite list
    public void Add(SpriteClass s)
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.Add called [" + s.file + "]");
      if (s != null)
      {
        lock (List)
        {
          ListChanged = true;
          ++spriteCount;
          List.Add(s);
          global.dbg.Out(Debug.DBG1, "Added sprite [" + s.globalId + "] file=[" + s.file + "]");
          SortList();
        }
      }
      else
      {
        global.dbg.Out(Debug.WARN, "SpriteListClass.Add: can't add a NULL sprite");
      }
    }
    // add to sprite list
    private void Add(SpriteClass[] s)
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.Add[] called.");
      for (int i=0; i<s.Length; ++i)
      {
        lock (List)
        {
          Add(s[i]);
        }
      }
    }
    // delete list
    public void Clear()
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.Clear called.");
      // reset enemy energy
      global.spriteList.EnemyEnergy = 0;
      List.Clear();
    }
    // delete from sprite list
    public void Delete(SpriteClass s)
    {
      if (s != null)
      {
        global.dbg.Out(Debug.DBG2, "SpriteListClass.Delete called [" + s.file + "]");
        lock (List)
        {
          global.dbg.Out(Debug.DBG1, "Removed sprite [" + s.globalId + "] file=[" + s.file + "]");
          ListChanged = true;
          List.Remove(s);
          SortList();
        }
      }
      else
      {
        //TODO:avoid else tree ;)
        global.dbg.Out(Debug.DBG1, "SpriteListClass.Delete: can't remove a NULL sprite");
      }
    }
    // returns how many POWER-UP objects we have
    public int CountPowerups()
    {
      int count = 0;
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        while (Index.MoveNext())
        {
          if (Index.Current.GetType() == typeof(PowerupClass))
          {
            ++count;
          }
        }
      }
      return (count);
    }
    // returns how many MINE objects we have
    public int CountMines()
    {
      int count = 0;
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        while (Index.MoveNext())
        {
          if (Index.Current.GetType() == typeof(MineClass))
          {
            ++count;
          }
        }
      }
      return (count);
    }
    public void SetAISpeed(int speed)
    {
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        // look through all the sprites
        while (Index.MoveNext())
        {
          // only look at tank sprites
          if (Index.Current.GetType() == typeof(Sprites.TankClass))
          {
            // only look at AI tanks
            if (((Sprites.TankClass)Index.Current).AI == true)
            {
              // set speed
              global.dbg.Out(Debug.DBG2, "SetAISpeed: setting speed of [" + ((Sprites.TankClass)Index.Current).playerName + "] to [" + speed + "]");
              ((Sprites.TankClass)Index.Current).speed = speed;
            }
          }
        }
      }
    }
    // returns nearest tank to given tank
    public Sprites.TankClass GetNearestEnemy(Sprites.TankClass thisTank)
    {
      Sprites.TankClass tank = null;
      // looking for tanks CLOSER than this value
      int nearestDistance = global.options.SCR_WIDTH + global.options.SCR_HEIGHT;
      // ensure nobody screws with the sprite list while we're looking at it
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        // look through all the sprites
        while (Index.MoveNext())
        {
          // only look at tank sprites
          if (Index.Current.GetType() == typeof(Sprites.TankClass))
          {
            // only look at OTHER tanks
            if (Object.Equals((Sprites.TankClass)Index.Current, thisTank) == false)
            {
              // only look at ENEMY tanks
              if (thisTank.PlayerTeam != ((Sprites.TankClass)Index.Current).PlayerTeam)
              {
                int dist = GetDistance(((Sprites.SpriteClass)Index.Current), thisTank);
                // if closer...
                if (dist < nearestDistance)
                {
                  // ...use this tank, it's the closest (so far)...
                  tank = (Sprites.TankClass)Index.Current;
                  // ...and remember this as being the closest so far
                  nearestDistance = dist;
                }
              }
            }
          }
        }
      }
      // if no tank was found to be the closest, and there was at least one other tank found...
      if (tank == null)
      {
        global.dbg.Out(Debug.WARN, "SpriteListClass.GetNearestTank: Unable to find a nearest tank.");
      }
      return (tank);
    }
    // returns disatance in pixels between 'sprite1' and 'sprite2'
    public int GetDistance(Sprites.SpriteClass sprite1, Sprites.SpriteClass sprite2)
    {
      int xRes = (int)(sprite1.posX - sprite2.posX) * (int)(sprite1.posX - sprite2.posX);
      int yRes = (int)(sprite1.posY - sprite2.posY) * (int)(sprite1.posY - sprite2.posY);
      return ((int)Math.Sqrt( xRes + yRes ));
    }
    // draw all sprites (tanks, powerups, etc) and text objects on-screen
    public void Draw()
    {
      global.dbg.Out(Debug.DBG3, "SpriteListClass.Draw: drawing [" + List.Count + "] sprites...");
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        while (Index.MoveNext())
        {
          // if tank, use overloaded Draw()
          if (Index.Current.GetType() == typeof(TankClass))
            ((TankClass)Index.Current).Draw();
          // otherwise use normal SpriteClass.Draw()
          else
            ((SpriteClass)Index.Current).Draw();
          // if the list has been changed (add, delete)...
          if (ListChanged == true)
          {
            // ...reposition iterator to valid position
            Index = List.GetEnumerator();
            ListChanged = false;
          }
        }
      }
      // draw text objects; delete any expired if necessary
      global.dbg.Out(Debug.DBG3, "SpriteListClass.Draw: drawing [" + TextList.Count + "] text objects...");
      lock (TextList)
      {
        IEnumerator Index = TextList.GetEnumerator();
        while (Index.MoveNext())
        {
          TextObject textObj = (TextObject)Index.Current;
          // if... current time (1005) - create time (1000) > delay (4) ...delete! (maybe)
          if (System.Environment.TickCount - textObj.CreateTime > textObj.DeleteTime)
          {
            TextList.Remove(textObj);
            break;
          }
          else
            global.DC.DrawText(textObj.X, textObj.Y, textObj.Text, textObj.Color);
        }
      }
    }
    public void Restore()
    {
      IEnumerator Index = List.GetEnumerator();
      while (Index.MoveNext())
      {
        SpriteClass temp = (SpriteClass)Index.Current;
        temp.Restore();
      }
    }
    public bool Collision()
    {
      bool collision = false;
      try
      {
        lock (List)
        {
          int i=0, j=0, k;
          global.dbg.Out(Debug.DBG3, "SpriteListClass.Collision: [" + List.Count + " sprites]");
          // test collision of list objects
          IEnumerator Index = List.GetEnumerator();
          ArrayList tempList = new ArrayList();
          tempList = (ArrayList)List.Clone();
          while (Index.MoveNext())
          {
            i++;
            j=0;
            //global.dbg.Out(Debug.DBG3, "  SpriteList.DetectCollision with sprite [" + (i) + "]");
            SpriteClass temp = (SpriteClass)Index.Current;
            IEnumerator  Index2 = tempList.GetEnumerator();
            for (k=0; k<i; ++k)
            {
              j++;
              Index2.MoveNext();
            }
            while (Index2.MoveNext())
            {
              j++;
              //global.dbg.Out(Debug.DBG3, "                         and with sprite [" + (j) + "]");
              //global.dbg.Out(Debug.DBG3, "SpriteListClass.Collision: [" + i + ", " + (j)+ "]");
              SpriteClass temp2 = (SpriteClass)Index2.Current;
              //global.dbg.Out(Debug.DBG3, "  Sprite.Collision[" + temp.PlayerId + " - " + temp.PlayerName + ", " + temp2.PlayerId + " - " + temp2.PlayerName + "]");
              // if we shot and hit somebody else
              // globalId=20 != enemyParentId=1  AND  parentId=0   != enemyGlobalId=100
              // if tank hits another tank
              // globalId=0  != enemyParentId=1  AND  parentId=MAX != enemyGlobalId=100
              // globalId=0  != enemyParentId=1
              if (temp.globalId != temp2.parentId && temp.parentId != temp2.globalId)
              {
                if (temp.Collision(temp2))
                {
                  global.dbg.Out(Debug.DBG2, "SpriteListClass.Collision: reacting to collision. [" + temp.playerName + ", " + temp2.playerName + "]");
                  collision = true;
                  temp.ReactToCollision(temp2);
                  temp2.ReactToCollision(temp);
                }
              }
              // if the list has changed, break out and reset the enumerators
              if (ListChanged == true)
                break;
            }
            if (ListChanged == true)
            {
              Index = List.GetEnumerator();
              tempList = (ArrayList)List.Clone();
              ListChanged = false;
            }
          }
        }
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteListClass.Collision: Exception caught [" + e + "]");
      }
      return collision;
    }
    public int HighestScore()
    {
      int score = 0;
      IEnumerator Index = List.GetEnumerator();
      while (Index.MoveNext())
      {
        SpriteClass temp = (SpriteClass)Index.Current;
        // only count energy of OTHER players
        if (temp.m_score > score)
          score = temp.m_score;
      }
      return score;
    }
    public void AddTank(int id, string bmp, string name)
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.AddTank called.");
      try
      {
        int x = global.random(100, global.options.SCR_WIDTH-100);
        int y = global.random(100, global.options.SCR_HEIGHT-100);
        //TODO: set the player's team
        Add(new Sprites.TankClass(bmp, x, y, id, name, false, 3, 0));
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteList.AddTank: " + e);
      }
    }
    public void MoveTank(int id, float x, float y, float direction, float speed)
    {
      global.dbg.Out(Debug.DBG2, "MoveTank called");
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        while (Index.MoveNext())
        {
          SpriteClass temp = (SpriteClass)Index.Current;
          if (temp.playerId == id)
          {
            lock (List)
            {
              global.dbg.Out(Debug.DBG2, "MoveTank found tank for changes");
              temp.posX = x;
              temp.posY = y;
              temp.whichFrame = (int)direction;
              temp.Speed = speed;
              break;
            }
          }
        }
      }
    }
    // sets ALL sprites to active = true
    public void SetActive()
    {
      SetActiveState(true);
    }
    // sets ALL sprites to active = false
    public void SetInactive()
    {
      SetActiveState(false);
    }
    // sets ALL sprites to active
    private void SetActiveState(bool active)
    {
      global.dbg.Out(Debug.DBG3, "SetActiveState called");
      lock (List)
      {
        IEnumerator Index = List.GetEnumerator();
        while (Index.MoveNext())
        {
          global.dbg.Out(Debug.DBG3, "Setting sprite [" + ((SpriteClass)Index.Current).playerName + "] active = " + active);
          ((SpriteClass)Index.Current).active = active;
        }
      }
    }
    // called by PlayClass when a player leaves the game
    public void RemoveTank(int id)
    {
      global.dbg.Out(Debug.DBG2, "RemoveTank called. id=[" + id + "]");
      try
      {
        lock (List)
        {
          IEnumerator Index = List.GetEnumerator();
          while (Index.MoveNext())
          {
            SpriteClass sprite = (SpriteClass)Index.Current;
            if (sprite.playerId == id)
            {
              global.dbg.Out(Debug.DBG1, "Removed tank, id=[" + id + "]");
              List.Remove(sprite);
              break;
            }
          }
        }
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteList.RemoveTank: " + e);
      }
    }
    // called by PlayClass when a shot packet is received
    public void AddShot(ShotClass.ShotTypes shotType, float x, float y, float direction)
    {
      global.dbg.Out(Debug.DBG2, "AddSprite called. shotType=[" + shotType + "] xy=[" + x + "," + y + "] dir=[" + direction + "]");
      try
      {
        //TODO: PASS  THE  PROPER  PARENT ID!!!!
        //FIXME!!!!!!!!!!!!
        /*ShotClass shot = new ShotClass(shotType, x, y, 0);
        shot.frameAngle = 1;
        shot.direction = direction;
        Add(shot);
        // play corresponding sound
        global.SC.Play(SoundClass.SOUND_SHOT+shotType+".wav", false);*/
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteList.AddShot: " + e);
      }
    }
    // called by PlayClass when a text message is received
    public void AddText(TextObject obj)
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.AddText called.");
      try
      {
        // move all other CHAT messages up one a few pixels and if MAX_CHAT_MESSAGES
        // is reached, erase the oldest (first) message in the list
        CycleChatText(MAX_MESSAGES+1, TEXT_SPACE);
        global.dbg.Out(Debug.DBG2, "SpriteListClass.AddText: inserting new text.");
        // insert our new message at position 0
        lock (TextList)
          TextList.Insert(0, obj);
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteList.AddText: " + e);
      }
    }
    // move all other CHAT messages up one a few pixels and if MAX_CHAT_MESSAGES
    // is reached, erase the oldest (first) message in the list
    private void CycleChatText(int limit, int space)
    {
      global.dbg.Out(Debug.DBG2, "SpriteListClass.CycleText called. limit=[" + limit + "] space=[" + space + "]");
      try
      {
        lock (TextList)
        {
          // if we have too many messages...
          if (TextList.Count > limit)
          {
            global.dbg.Out(Debug.DBG2, "SpriteListClass.CycleText erasing first element.");
            // ...erase the oldest (last) to make room for new messages
            TextList.RemoveAt(TextList.Count-1);
          }
          // cycle through all messages and update y coordinate so messages scroll
          for (int i=0; i < TextList.Count; ++i)
          {
            TextObject obj = (TextObject) TextList[i];
            obj.m_y += space;
            TextList[i] = obj;
            global.dbg.Out(Debug.DBG2, "SpriteListClass.CycleText set obj #" + i + " y=[" + obj.m_y + "]");
          }
        }
      }
      catch (Exception e)
      {
        global.dbg.Out(Debug.ERR, "SpriteList.CycleChatText: " + e);
      }
    }
    public int GetResourceIdx(string file)
    {
      int foundIdx = -1;
      for (int i=0; i<resourceList.Length; ++i)
      {
        // if matching file, return position (idx)
        if (resourceList[i].file == file)
        {
          // if file actually exists...
          if (File.Exists(file))
          {
            foundIdx = i;
            break;
          }
          else
          {
            global.dbg.Out(Debug.ERR, "GetResourceIdx:: Cannot load sprite [" + file + "]. Exiting...");
            MessageBox.Show("GetResourceIdx:: Cannot load sprite [" + file + "]. Exiting...");
            global.options.initialized = false;
            break;
          }
        }
      }
      return (foundIdx);
    }
    // call this ONETIME to load all possible resources into memory
    public bool LoadResources()
    {
      // get array of *.bmp files
      string[] files = Directory.GetFiles(CONST.DIR_BITMAP, "*.bmp");
      if (files.Length > 0)
      {
        // create our static list of resources
        resourceList = new Resource[files.Length];
        for (int i=0; i<files.Length; ++i)
        {
          resourceList[i].file    = files[i];
          resourceList[i].bmp      = new Bitmap(resourceList[i].file);
          resourceList[i].description  = new SurfaceDescription();
          resourceList[i].surface    = new Surface(resourceList[i].file, resourceList[i].description, global.DC.Draw);
        }
        return true;
      }
      // nothing found
      return false;
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.