如何创建共享某些属性的对象

How to create objects that share some properties

我正在 HTML5 canvas 中制作一个 2D 游戏,其中会有很多对象。一些对象彼此共享一些属性。某些属性将仅适用于一个对象。对象可能有空值 属性.

我想创建一个具有所有对象属性的主对象。如果有一个对象只有主对象的3个属性,其他属性将为空。

例如,假设游戏中任何对象的所有可能属性都是 {a,b,c,d,e,f,g},我们在游戏中有 2 个对象 ob0 & ob1.

ob0的属性是a,c,d所以我只填充它们,其他属性{b,e,f}将是空白。

ob1的属性是b,e,f所以我只填充它们,其他属性{a,c,d}将是空白。

我想到这个演示文稿是因为两件事。首先是我不太擅长 OOP 和继承以及其他 OOP 方面的东西。第二件事是大约两年前,在一个叫Red Alert2的游戏里,有一个.INI的文件,里面就是游戏中的所有物品。数据是这样表示的

[obj1]
color=red
width=100px
cankill=yes
[obj2]
weapontype:4
canswim=yes
weapontype=4
speed=20

例如属性 cankill不在obj2中,obj2无法在游戏中击杀。但是如果你给了 obj2 这个 属性 并且给了它 weapontype=10 它会在游戏中使用游戏中的第 10 把武器杀死它。这告诉我,如果 属性 没有值,则意味着在游戏中它的值将为零或 ??

我的问题来了。

  1. 在 JS 中如何实现?我的意思是我真的可以将 .INI 文件与 JS 连接起来吗?

  2. 有没有更有效的保存对象属性的方法?我不是要求用两页来描述这种方式。我只想知道那一点的主要思想。

  3. 我认为我对这个问题的解决方案会遇到大小过载的问题。如果游戏有1000个属性,每个对象将由1000个属性组成,当对象只需要4或5个属性时,这将对内存造成严重影响。那怎么解决呢?

如果我理解的很好

  • 您有多个对象
  • 这些对象共享它们的 属性 名称,但不一定共享值

然后我认为最简单的方法是使用普通对象,忽略它们共享 属性 个名称的事实。

因此,

[obj1]
color=red
width=100px
cankill=yes
[obj2]
weapontype:4
canswim=yes
weapontype=4
speed=20

会变成

var obj1 = {
    color: "red",
    width: "100px",
    cankill: true
}, obj2 = {
    weapontype: 4,
    canswim: true,
    weapontype: 4,
    speed: 20
};

您可以使用 jQuery 或 Underscore 的扩展/默认方法,可能还有一些其他框架。

但我认为扩展对象的最佳/最快方法是使用 vanilla javascript。

请查看此 SO question 以了解扩展方法。

在下面的演示和这个 jsFiddle 中,我添加了 jQuery、下划线和纯 js。 (jQuery 和下划线代码被注释掉。)

您可以找到这些方法的基准 here。 (我希望我已经正确创建了 jsperf 测试,因为这是我的第一个测试用例。)

针对您的问题:

  1. 我建议将您的配置存储在 JSON 文件中,因为这样更容易为您的 javascript.
  2. 加载
  3. 是的,我认为最好是为您的属性使用原型。因为原型只存储一次,而不是每个实例。
  4. 使用原型应该没问题。因为对象实例只得到较低的 属性 计数。

var GameObject = {
    // init and other methods can be defined here
};

GameObject.prototype = {
    color: undefined, // undefined properties will be removed by jQuery.extend
    canKill: undefined,
    width: undefined,
    speed: undefined,
    weaponType: undefined
};

// pure javascript extending
Object.prototype.extend = function (obj) {
    // source from this SO question: 
    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            this[i] = obj[i];
        }
    }
};

var ob1 = Object.create(GameObject);
ob1.extend({
    color: 'red',
    canKill: 'yes'
});

var ob2 = Object.create(GameObject);
ob2.extend({
    color: 'green',
    canKill: 'no',
    speed: 10
});

/*
// with underscore.defaults
var ob1 = _.defaults(Object.create(GameObject), {
    color: 'red',
    canKill: 'yes'
});

var ob2 = _.defaults(Object.create(GameObject), {
    color: 'green',
    canKill: 'no',
    speed: 10
});
*/

/*
// with jQuery.extend(...)
var ob1 = $.extend(true, Object.create(GameObject), { 
    // true = deep copy, new GameObject = target, source object
    color: 'red',
    canKill: 'yes'
});

var ob2 = $.extend(true, Object.create(GameObject), {
    color: 'green',
    canKill: 'no',
    speed: 10
});
*/

//console.log(ob1.prototype);
console.log(ob1, ob1.color, ob1.canKill);
console.log(ob2, ob2.color, ob2.canKill, ob2.speed);
//console.log(GameObject, GameObject.prototype);