2010-03-02 7 views
1

Я пишу игру в Flash (игрок 10) и должен придумать хороший способ управлять списком объектов/сущностей/актеров в игре (персонаж игрока , препятствия, враги и т. д.). Она имеет следующие требования:Как создать структуру данных пользовательских данных игры

  • Iterable
  • Объекты addable и съемные, а итерация.
    • Аргумент для удаления() функции будет объектом для удаления, а не индексом.
  • [необязательно] Объектам может быть присвоено имя и получено с помощью этого.
  • [необязательно] Сортировка, поэтому некоторые объекты обновляются раньше других.

Как бы это реализовать?


Я думал вдоль линий таблицы базы данных в оперативной памяти, которая будет содержать:

  • массив с помощью объектов (записей).
  • Хешмап (индекс), который связывает имена с индексами массива.
  • Другой hashmap, чтобы связать объекты с их индексами (для удаления путем передачи объекта для удаления).

Удаление объекта приведет к тому, что соответствующая запись будет нулевой. Время от времени массив должен быть уплотнен (пустые пространства удалены), или он будет слишком большим. Это требует восстановления хэш-карты, чтобы указать на правильные записи (но это можно сделать эффективно).

Мысли? Будет ли это работать хорошо? И как сделать сортировку и добавить/удалить во время итерации частей?

ответ

2

Это звучит так, как будто вы хотите связанный список.

  • Вы можете перечислить список от начала до конца, или закончить, чтобы начать
  • Чтобы добавить в коллекцию, просто добавить в начало или конец (просто изменив 2 указатели, очень быстро!)
  • Если сами объекты действуют как связанный список узлов, то вы можете удалить объект непосредственно (путем простой замены четырех указателей, очень быстро!)
  • связанный список может быть отсортирован в O (nlongn) с использованием merge sort
1

Похоже, это то, что вы ищете:

http://gamedev.michaeljameswilliams.com/2008/09/20/actionscript-3-collection-class/

Это коллекция класса для AS3, который расширяет массив и добавляет функции, как добавить() и удалить(), а также некоторые действительно полезные функции сортировки. Я использовал его, и он работает хорошо, не было никаких проблем. Надеюсь, это то, что вы ищете, и это полезно для вас.

0

Рассмотрите это: будет ли массив или словарь соответствовать вашим потребностям? Да, они не пылают быстро, но они просты в использовании (и соответствуют вашим требованиям).

Если вы правильно разделяете свои объекты в соответствии с путями кода, которые они берут (например, статические объекты, сущности, снаряды), вы обычно получаете довольно небольшие списки динамических объектов и большие списки статических объектов.

Статические объекты не нуждаются в причудливых структурах данных, поскольку вы можете сделать много предположений о них (или сделать тяжелую работу при загрузке), а динамическим объектам не нужны причудливые структуры данных, многие из них. Не оптимизируйте такие вещи, если: у вас нет существенных проблем с архитектурой, или у вас есть настоящее узкое место здесь.

Потому что в конечном счете это важно: Проведите свое время, создавая игру, а не структуру данных. :)

Возможно, я неверно истолковал ситуацию?

1

Если вы ищете для некоторых различных (и производительный) datastructures для AS3, я нашел эти те вполне комфортно в прошлом:

DataStructures by polygonal

0

Мое текущее решение заключается в использовании класса EntityManager, что поддерживает словарь всех объектов, а также массив активов. Первый используется для извлечения объектов по id. Последний используется для цикла обновления, который выглядит следующим образом:

var len:int = actives.length; 
for(var i:int = 0; i < len; i++) 
{ 
    var entity:Entity = actives[i]; 
    if(!entity.isActive) 
    { 
     actives.splice(i,1); 
     --len; 
    } 
    else 
    { 
     entity.update();  
    } 
} 

Я хотел бы предложить создать интерфейс для вашего менеджера сущности, реализации то, что работает, а затем вернуться назад и исправить это позже, если вы обнаружите, что нужно повысить производительность или добавить функции.

1

Я использую класс Manager I, созданный для управления связкой объектов, которые могут быть назначены любому типу «списка» на основе String. т.е. вы можете назначить его «врагам» и «ALL_OBJECTS». Класс использует pop() для почти мгновенного удаления (и использует объект, а не индекс, который нужно удалить, как вы хотели).

Вот объект, который вы создали бы и ссылку на менеджер:

public class AvGlyph extends Object 
    { 
     // vars 
     internal var signatures:Array = []; 
     private var _attachment:Object; 

     /** 
     * Constructor 
     * @param attachTo An Object to set as the attachment for this 
     */ 
     public function AvGlyph(attachTo:Object) 
     { 
      _attachment = attachTo; 
     } 

     /** 
     * Dissolves this, destroying reference to _attachment and fully detaching itself 
     */ 
     public function dissolve():void 
     { 
      _attachment = null; 
      AvGlyphManager.fullyDetach(this); 
     } 

     /** 
     * Basic getters 
     */ 
     public function get attachment():Object{ return _attachment; } 

     /** 
     * Returns an Array containing all signatures applied to this 
     */ 
     public function get allSignatures():Array 
     { 
      var a:Array = []; 

      var i:String; 
      for(i in signatures) a.push(i); 

      return a; 
     } 
    } 

И это менеджер для них:

public class AvGlyphManager 
    { 
     // properties 
     private static var _glyphs:Array = []; 

     /** 
     * Attaches an AvGlyph to a specified list 
     * @param glyph The AvGlyph to attach 
     * @param signatures Signature Strings used to represent categories 
     */ 
     public static function attach(glyph:AvGlyph, ...signatures):void 
     { 
      var i:String; 
      for each(i in signatures) 
      { 
       if(!_glyphs[i]) _glyphs[i] = []; 

       if(!glyph.signatures[i]) 
       { 
        glyph.signatures[i] = _glyphs[i].length; 
        _glyphs[i].push(glyph); 
       } 
      } 
     } 

     /** 
     * Detach an AvGlyph from a specified list 
     * @param glyph The AvGlyph to detach 
     * @param signature Signature Strings used to represent categories 
     */ 
     public static function detach(glyph:AvGlyph, ...signatures):void 
     { 
      var i:String; 
      for each(i in signatures) 
      { 
       var n:uint = glyph.signatures[i]; 

       if(n == _glyphs[i].length - 1) _glyphs[i].pop(); 
       else 
       { 
        _glyphs[i][n] = _glyphs[i].pop(); 
        _glyphs[i][n].signatures[i] = n; 
       } 

       if(_glyphs[i].length < 1) delete _glyphs[i]; 
      } 
     } 

     /** 
     * Detach an AvGlyph from all previously specified listings 
     * @param glyph The AvGlyph to detach 
     */ 
     public static function fullyDetach(glyph:AvGlyph):void 
     { 
      var i:String; 
      for(i in glyph.signatures) detach(glyph, i); 
     } 

     /** 
     * Returns a Array of all AvGlyphs that have been attached with a specified signature 
     * @param signature A signature String used to represent a category 
     */ 
     public static function getGlyphs(signature:String):Array 
     { 
      if(!_glyphs[signature])return []; 
      return _glyphs[signature].slice(); 
     } 

     /** 
     * Trace a tree of signatures and their children 
     */ 
     public static function traceTree():void 
     { 
      trace('a'); 
     } 
    } 

Использования просто:

В ваш класс, скажем, Zombie.as, вы могли бы иметь.

public class Zombie extends Sprite 
{ 
    private var _glyph:AvGlyph; 

    /** 
    * Constructor 
    */ 
    public function Zombie() 
    { 
      _glyph = new AvGlyph(this); 
     AvGlyphManager.attach(_glyph, "enemies"); 
    } 
} 

Отсюда, вы можете в любом месте в использовании приложение/игра:

AvGlyphManager.getGlyphs("enemies"); 

который вернет массив глифов, перечисленных в разделе «врагов». Для доступа к самому Зомби выполняется просто с помощью glyph.attachment. Так, в цикле через все ваши объекты было бы что-то вдоль линий:

var li:Array = AvGlyphManager.getGlyphs("enemies"); 

var i:AvGlyph; 
for each(i in li) 
{ 
    trace(i.attachment); 
} 

удаления, вероятно просто, если вы берете быстрый взгляд через AvGlyphManager, а также.Есть также:

AvGlyphManager.fullyDetach(glyph); 

Это очень полезно, когда вы хотите полностью удалить объект.

Смежные вопросы