parkm / oldbpm

A JavaScript game where you shoot at bubbles.
0 stars 1 forks source link

Constructors #19

Closed parkm closed 10 years ago

parkm commented 10 years ago

Turns out we're going to need constructors. So this solution works:

function GameObject() {
    this.x=0; this.y=0; //created with each new instance
}

function GameObjectProto() {
    this.update = function(); //prototype stuff
}

GameObject.prototype = new GameObjectProto();

inherit(Bubble, GameObject); // This would use Object.create(Base.prototype)
function Bubble() {
    GameObject.call(this);
}

Bubble's chain would look like this:

Bubble
    GameObject
        GameObjectProto

But i'm wondering if you can come up with any other solutions. I was thinking of just having another type of init function called construct, but that would have to be called every time like: new Bubble().construct() you would also have to pass the arguments twice.

dgpt commented 10 years ago

Why would we need to do that? We definitely need specific constructors, though. Just like how we had to have an init function in States, and how we had to put all of the constructor setup in the onAdd function in objects.

I want to figure out a way to set the constructor of an object to a function within said object... I wonder if that's possible? That way, it'll get called on new and we won't have to worry about this nonsense.

Also, if we did new Bubble(x,y,z).construct(), we only need to pass the params in one spot because closures. The x, y, z params will be available in construct().

dgpt commented 10 years ago

Also, why are you using Object.create()? I don't get the benefit of using it.

dgpt commented 10 years ago

I also want to avoid this

function Bubble() {
    GameObject.call(this); // <-- == :(
}
parkm commented 10 years ago

I guess we could just do new Base.prototype() But MDN's classical inheritance example uses Object.create.

I'm not sure how to avoid GameObject.call, but maybe we could if it was passed into the inherit function. inherit(Bubble, GameObject, function() {}) then it could use that function and automatically call it or something.

Okay if we can use construct without passing the arguments again then that seems like the best option. We wouldn't have to use GameObject.call and nothing else would change, except for actually instantiating the objects.

Oh but it would get messy once we have multiple sub classes. Then we'd have to call the super class's function.

parkm commented 10 years ago

So yeah I'm thinking either construct or using a separate function for the prototype, unless you can come up with something else.

dgpt commented 10 years ago

Let me see if I can come up with something. I'll let you know how it goes

dgpt commented 10 years ago

I'm not seeing an issue with the way we're doing it now. I was trying to set the constructor as another function, but it doesn't appear to work that way - I have no idea how it works and can't find much info on it. Also tried to do make Sub.prototype._super = Sub.prototype in inherit.js, but it was giving me some strange bugs. I then tried to bind all of them to the prototype, but it doesn't work that way. Can't figure out how to implement it without wrapping over everything, so I think we should just stick to the way it is on master. It's not bad.

parkm commented 10 years ago

We need constructors though. It doesn't execute init until it has been added to the state. I need to get some values from an object before it gets added. The simplest way of doing this would be the construct method since it would fit nicely with the current inheritance.

dgpt commented 10 years ago

Is this for objects? Just add an init function to them. They don't even have one. On May 8, 2014 11:47 PM, "Parker Miller" notifications@github.com wrote:

We need constructors though. It doesn't execute init until it has been added to the state. I need to get some values from an object before it gets added. The simplest way of doing this would be the construct method since it would fit nicely with the current inheritance.

— Reply to this email directly or view it on GitHubhttps://github.com/despondentdonkey/bpm/issues/19#issuecomment-42635375 .

parkm commented 10 years ago

I renamed onAdd to init for consistency. There is no constructor for objects, so yeah that's what I need. So I'm going to add a construct method and we'll have to instantiate objects like:

new TestObject(x,y,z).construct()

dgpt commented 10 years ago

Wait, why don't you revert init back to onAdd, then make init instead of construct? That'd make more sense. On May 9, 2014 12:06 AM, "Parker Miller" notifications@github.com wrote:

I renamed onAdd to init for consistency. There is no constructor for objects, so yeah that's what I need. So I'm going to add a construct method and we'll have to instantiate objects like:

new TestObject(x,y,z).construct()

— Reply to this email directly or view it on GitHubhttps://github.com/despondentdonkey/bpm/issues/19#issuecomment-42636219 .

parkm commented 10 years ago

Yeah I was thinking that but it would be inconsistent. It should be labeled as a constructor. init in states is not a constructor.

dgpt commented 10 years ago

Eh, I guess so. It might as well be, though. See if you can get prototype.constructor to work On May 9, 2014 12:09 AM, "Parker Miller" notifications@github.com wrote:

Yeah I was thinking that but it would be inconsistent. It should be labeled as a constructor. init in states is not a constructor.

— Reply to this email directly or view it on GitHubhttps://github.com/despondentdonkey/bpm/issues/19#issuecomment-42636348 .

parkm commented 10 years ago

Well it's really important to know the difference between the two. It's useful to know that when a state is being created it will definitely have the constructor values. This is much more important for objects though since init wouldn't get called until it has been added and that is not automated.

Alright I'll play around with it, if all fails then I'll just use the construct method.

parkm commented 10 years ago

Okay I really dislike where this has headed. I think we should go back to something more simple.

So instead of having to go GameObject.prototype.myFunc for every function in the prototype, can we not just do:

GameObject() { this.x=0 };
GameObject.prototype = {
    myFunc: function() {}
};

I made a small test doing this and it seems to work fine with values and arrays. Was there anything wrong with this method? We would still have to do GameObject.call(this) but I think it's a small price to pay for it to act properly.

dgpt commented 10 years ago

Apparently, defining stuff on the prototype is more memory efficient since methods are only created once instead of with every instance. So yeah, I'd prefer defining the prototype as an object like your previous example.

However, it shouldn't be necessary to do GameObject.call(), should it? If you look at the current state of master, it's not necessary.

parkm commented 10 years ago

If we want a constructor with inheritance then yes it is necessary. We need this function to execute when it has been instantiated so we can either use construct on every instance or State.call(this) on every new class.

We don't have a constructor on master. We're just initializing variables in the init function, which is not the constructor. In objects _init is called in the state once the object has been added. The reason why you don't have to go Foo.prototype.init.call(this) is because the _init function calls init for you. If we were to have a sub class of foo then every overridden function would need to use call.