我应该使用构造函数/原型吗?

时间:2016-01-20 21:44:50

标签: javascript constructor prototype

function setupMapObjects() {
    lootChest = new PIXI.Sprite(frame("images/chest.png", 0, 0, 50, 50));
    lootChest.x = 200;
    lootChest.y = 200;
    lootChest.anchor.x = 0.5;
    lootChest.anchor.y = 0.7;
    lootChest.closed = true;
    lootChest.opening;
    lootChest.frameCycle = 0;
    lootChest.interactive = true;
    lootChest.hitArea = new PIXI.Circle(lootChest.x, lootChest.y, 10);
    lootChest.on('click', openChest);
    Map.addChild(lootChest);    



    lootChest2 = new PIXI.Sprite(frame("images/chest.png", 0, 0, 50, 50));
    lootChest2.x = 400;
    lootChest2.y = 400;
    lootChest2.anchor.x = 0.5;
    lootChest2.anchor.y = 0.7;
    lootChest2.closed = true;
    lootChest2.opening;
    lootChest2.frameCycle = 0;
    lootChest2.interactive = true;
    lootChest2.hitArea = new PIXI.Circle(lootChest2.x, lootChest2.y, 10);
    lootChest2.on('click', openChest);
    Map.addChild(lootChest2);
};


function openingChest() {
    this.texture.frame = new PIXI.Rectangle(this.frameCycle*50, 0, 50, 50);
    if (this.frameCycle === 3) {
        clearInterval(this.opening); 
    } else {
        this.frameCycle++;    
    };
};


function openChest() {
    if (distance(Player.sprite.x, Player.sprite.y, this.x, this.y) < 50) {
        if (this.closed) {
            this.opening = setInterval(openingChest.bind(this), 100);
            this.frameCycle = 1;
            this.closed = false; 
        };
    };
};

我有2个宝箱精灵在点击时打开并且玩家在附近。现在我想找出一种有效的方法来创建50个。如我所知,继续制作它们有多糟糕?有什么选择?

3 个答案:

答案 0 :(得分:1)

构造函数似乎是正确的想法。毕竟,您不需要为每个胸部命名(lootChest1 .. lootChest50)。更不用说,你确保你的所有箱子都是平等的。所以这样的事情应该运作良好。

function Chest(x, y) {
  this.x = x;
  this.y = y;
  this.anchor.x = 0.5;
  this.anchor.y = 0.7;
  this.closed = true;
  this.opening;
  this.frameCycle = 0;
  this.interactive = true;
  this.hitArea = new PIXI.Circle(lootChest.x, lootChest.y, 10);
  this.on('click', openChest);
}

// Have them "inherit" from PIXI.Sprite
Chest.prototype = new PIXI.Sprite(frame("images/chest.png", 0, 0, 50, 50));

// How to use it
var lootChest = new Chest(200, 200);

自从我使用PIXI以来已经有一段时间了,所以我不记得这种继承方式是否适用于它们的渲染系统。如果它没有,你可以使它成为一个工厂功能。工厂功能看起来就像你是如何创建你的第一个胸部(除了你想要将它分配给一个局部变量)然后从该功能返回那个胸部。

编辑:工厂方法如下所示:

function createChest(x, y) {
  var chest = new PIXI.Sprite(frame("images/chest.png", 0, 0, 50, 50));
  chest.x = x;
  chest.y = y;
  chest.anchor.x = 0.5;
  chest.anchor.y = 0.7;
  chest.closed = true;
  chest.opening;
  chest.frameCycle = 0;
  chest.interactive = true;
  chest.hitArea = new PIXI.Circle(lootChest.x, lootChest.y, 10);
  chest.on('click', openChest);
  return chest;
}

// How to use it
var lootChest = createChest(200, 200);

我有一个example of how to inherit from PIXI.Sprite,但它有点复杂。在那里完成的方式是允许可配置性,因为它在游戏引擎中,但如果你确切地知道你希望你的对象看起来像什么,上述任何一种方法都应该没问题。

答案 1 :(得分:0)

为此必须使用OOP(面向对象编程)。您可以创建一个Chest个对象的数组,然后只需修改构造函数和原型方法,而不是仔细检查每个单独的胸部。

Shomz说得对。

然后,如果您想要为所有胸部设置动画,只需使用for循环来遍历Chest的数组,并轻松地对所有这些进行操作。

答案 2 :(得分:0)

Mike C给出了一个很好的例子,但是我想进一步扩展一些与JavaScript原型相关的陷阱。

Mozilla在原型继承和构造函数here

上有一个很好的例子

但是在利用原型时要记住一些重要的陷阱,我在this Codepen中已经证明了这一点。

请注意,在相同对象上调用的相同方法在第二次调用时的行为实际上与第一次相同。这是因为对象不存储对move函数的给定实现的引用,而是使用当前在其原型上调用它的原型。

在代码运行时,可以修改Shape.prototype.move。很可能这种情况永远不会发生,但如果确实如此(就像团队中的另一位开发人员在运行时重新定义了原型上的函数而不知道已存在同名的那个),它最终会导致一个错误很难追查。

JavaScript中的原型可以是有用的工具,但我个人更喜欢使用工厂模式来避免与原型相关的难以捉摸的错误。

示例:

function CreateShape(newX, newY) {
  return {
    x = newX,
    y = newY,
    move = function(addX, addY){
      this.x += addX;
      this.y += addY;
      console.info('Shape moved.');
    }
  }
}

通过使用此模式,您每次都创建一个新对象,它不与任何其他对象共享原型,这意味着它将始终表现相同,无论对其他Shape对象或其他任何对象进行何种修改原型。

只是您可以考虑的替代方案。我希望这有帮助!