2
\$\begingroup\$

I'm just wondering how to instantiate the same objects that all share the same variables, except their positions.

I'm basically working on the scene of my HTML5 game, and I've build a streetlamp post that turns on and off. All the lamps will have the same variables, such as Image, Size, on/off function. The only thing that will be different will be the position x and y.

I've built my lamp within a variable function (I think they're called that var = {), and within my actual game DrawFunction, I'm calling LampPost.draw();.

Is it possible to do something like this?

LampPost(0,0);
LampPost(100, 0);
LampPost(200, 0);

etc ... and then possibly place each instantiate Lamp within an array?

This is a snippet code for the lamp:

var LampPost = {

    lamp_xsprite : 0,
    lamp_ysprite : 0,

    light_xsprite : 0,
    lightysprite : 0,

    x : 440,
    y : 320,

    //Flicker effects
    lightFlicker : 0,
    seconds_Off : 0,
    seconds_On : 0,

    randomLength_Off : 500,
    randomLength_On : 150,


    draw: function(x, y) {

        this.x = x;
        this.y = y;

        ctxPropsOver.setTransform(1, 0, 0, 1, -Map.x + gameWidth/2, -Map.y + gameHeight/2);
        ctxPropsOver.rotate(Math.PI / -25);
        ctxPropsOver.clearRect(0, 0, 1000, 1000);

        ctxPropsOver.globalAlpha = this.lightFlicker;
        ctxPropsOver.drawImage(imgLights, 0, 36, 500, 463, -60 + this.x, -190 + this.y, 500, 463);
        ctxPropsOver.globalAlpha = 1;
        ctxPropsOver.drawImage(imgLights, 0, 0, 210, 36, 0 + this.x, 0 + this.y, 210, 36);

----- UPDATE -----

Okay, So I've converted it into an instance of object, this is what I have so far:

LampPost = function(lx, ly, la){

    x = lx; //500;
    y = ly; //335;

    centrex = 12;
    centrey = 17;

    rotate = la; //-8;

}

LampPost.prototype.draw = function (){

    ctxPropsOver.setTransform(1, 0, 0, 1, (-Map.x + gameWidth/2), (-Map.y + gameHeight/2) );

    ctxPropsOver.clearRect(0, 0, 1000, 1000);

    ctxPropsOver.save();
        ctxPropsOver.translate(this.x, this.y);
        ctxPropsOver.rotate(this.rotate*Math.PI/180);
        ctxPropsOver.translate(-this.centrex, -this.centrey);
        ctxPropsOver.globalAlpha = this.lightFlicker;
        ctxPropsOver.drawImage(imgLights, 0, 36, 500, 463, -60, -190, 500, 463);
        ctxPropsOver.globalAlpha = 1;
        ctxPropsOver.drawImage(imgLights, 0, 0, 210, 36, 0, 0, 210, 36);
    ctxPropsOver.restore();
};
\$\endgroup\$
1

3 Answers 3

3
\$\begingroup\$

aha I see in your posted code that you created LampPost as a literal object, and not as an object to instantiate. So you'll do something like:

LampPost = function(x,y) {
  this.x = x;
  this.y = y;
  blah blah
}

LampPost.prototype.draw = function() {
  ctxPropsOver.translate(this.x, this.y);
  blah blah
}

var post = new LampPost(100, 0);
post.draw();

I suggest looking up JavaScript OOP, possibly by doing lessons on CodeAcademy

\$\endgroup\$
4
  • \$\begingroup\$ Thanks, I've changed it so its 'object to instantiate' (see update). Few questions, in createLampPost - why do I need to return Thing? as well as define the image location? < I am already defining that in the LampPost draw? Also, what are the both 'var post' doing? Thanks \$\endgroup\$ Commented Jan 28, 2013 at 22:59
  • \$\begingroup\$ sorry if that was confusing, the original suggestion was before I noticed you were doing object literals instead of instantiating. I suppose I should remove that part, although I'll read what your question says now before I change stuff \$\endgroup\$
    – jhocking
    Commented Jan 29, 2013 at 18:28
  • \$\begingroup\$ oh and I just threw in the image location because in your original question you said to define Image for each lamp. If you don't actually need that, then you don't do that. As for 'var post' that is now the name of your object. In OOP you would use LampPost to define what all your lampposts will be like, while 'post' would be the name of one specific lamppost (ie. an instance). So then you would call post.draw() \$\endgroup\$
    – jhocking
    Commented Jan 29, 2013 at 18:31
  • \$\begingroup\$ I think in your updated code you need to type lines like 'this.x = lx;' and not just 'x = lx;' I'm not sure about that, but I think you need to do that to make sure it's a value attached to the object and not just a local variable in the constructor function. \$\endgroup\$
    – jhocking
    Commented Jan 29, 2013 at 18:36
2
\$\begingroup\$

You can use Object.create instead of new to explicitly set the object's prototype. This lets you easily implement the flyweight pattern. You can also set the prototype property of the constructor, though that's less flexible.

A more general for all languages solution is to split your objects between data and instance info. Eg your Lamppost instance just has a member referencing some LamppostData instance.

\$\endgroup\$
1
\$\begingroup\$

Create a template object with all shared functions and member data. Then, use a create function to manufacture instances.

In the example below, you can provide arbitrary properties to be specified uniquely per instance, either overriding template parameters or adding new parameters unique to an instance.

Template for LampPost objects. Create instances with LampPostTemplate.create().

LampPostTemplate = {
  create:function(instanceVariableDictionary) {
    var result = createInstance(this, instanceVariableDictionary);
    //... any initialization code needed for LampPost instances.
    result.flickerAnimationTimeOffset = Math.random();
    return result;
  },
  draw:function() { /* ... */ },

  center:{x:.5, y:.5},
  position:{x:0, y:0},
  name:"Unnamed",
  flickerAnimation: [1,1,1,1,1,0,1,1,0,1,1,1,0],
  flickerAnimationTimeOffset: 0
};

Create instances:

Lamp1 = LampPostTemplate.create({ position:{x:1, y:2} });
Lamp2 = LampPostTemplate.create({
  position:{x:11, y:22},
  flickerAnimation:[1,0,0,0,0,1,0,0],
  name:"Hill top2"});

Here is the helper function to create copies of a template object and then copy arbitrary properties based on an input dictionary.

function createInstance(templateObject, instanceVariableDictionary) {
  var result = Object.create(templateObject);
  for (var property in instanceVariableDictionary) {
    if (typeof instanceVariableDictionary[property]['slice'] === 'function') {
      // Copy an array
      result[property] = instanceVariableDictionary[property].slice();
    } else if (typeof instanceVariableDictionary[property] === 'object') {
      // Copy an object
      result[property] = Object.create(instanceVariableDictionary[property]);
    } else {
      // Copy numbers, strings, ...
      result[property] = instanceVariableDictionary[property];
    }
  }
  return result;
};
\$\endgroup\$
1
  • \$\begingroup\$ Answers that are just code are not too useful. It would be better if you were to add some explanation about why this code would be good. \$\endgroup\$
    – House
    Commented Jan 29, 2013 at 17:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .