我在Flash(玩家10)中编写游戏,需要想出一个很好的方法来管理游戏中的对象/实体/演员列表(玩家角色,障碍物,敌人等)。它有这些要求:
我该如何实现?
我正在考虑内存数据库表,其中包含:
删除实体会使相应的记录为空。偶尔需要压缩数组(删除空格)或者它会变得太大。这需要重建hashmap以指向正确的记录(但这可以有效地完成)。
思考?它会表现良好吗?以及如何在迭代零件时进行可排序和添加/删除?
答案 0 :(得分:2)
听起来我想要一个链接列表。
答案 1 :(得分:1)
听起来这就是你要找的东西:
http://gamedev.michaeljameswilliams.com/2008/09/20/actionscript-3-collection-class/
它是AS3的Collection类,它扩展了Array并添加了add()和remove()等函数,以及一些非常有用的排序函数。我已经习惯了,它表现很好,没有任何抱怨。希望这是你正在寻找的东西,它对你有用。
答案 2 :(得分:1)
如果您正在寻找AS3的一些不同(和高性能)数据结构,我发现这些数据结构在过去非常舒适:
答案 3 :(得分:1)
我使用我创建的Manager类来管理一堆可以根据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即可访问Zombie。因此,对于遍历所有对象的循环,它将是:
var li:Array = AvGlyphManager.getGlyphs("enemies");
var i:AvGlyph;
for each(i in li)
{
trace(i.attachment);
}
一旦您快速浏览AvGlyphManager,删除可能很简单。还有一个:
AvGlyphManager.fullyDetach(glyph);
当您想要完全删除对象时,这非常有用。
答案 4 :(得分:0)
考虑一下:数组或字典是否符合您的需求?是的,它们并不快速,但它们易于使用(并且符合您的要求)。
如果根据它们采用的代码路径(即静态对象,实体,射弹)正确地隔离对象,通常会得到相当小的动态对象列表和大型静态对象列表。
静态对象不需要花哨的数据结构,因为你可以对它们做很多假设(或者在加载时做繁重的工作),动态对象不需要花哨的数据结构,因为没有许多人。不要优化这种事情,除非:你有重大的架构问题,或者你有一个实际的瓶颈。
因为最终,重要的是:花时间制作游戏,而不是数据结构。 :)
或许我误解了这种情况?
答案 5 :(得分: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();
}
}
我建议为您的实体管理器创建一个界面,实现可行的功能,如果您发现需要提高性能或添加功能,请稍后再修复它。