Jump to content

Inheriting Sprite causes error (repost)


Recommended Posts

Apologies for the repost, the other thread is very old and marked as 'answered' so I think my question is not being seen by the people who know...


Is Sprite inheritance broken in the current Main branch?  I'm getting "error: undefined is not a function" on line 1719 of Phaser.js:




from this code:


Person = function(game) {
Phaser.Sprite.call(this, game, 0, 0, 'person');

Person.prototype = Object.create(Phaser.Sprite.prototype);
Person.prototype.constructor = Person;


invoked by:


var person = new Person(game);


The reason I want to do this is to make a Group of type Person (to simplify collisions) and it needs to be a display object to work with Group.  Other good solutions welcomed!


Link to comment
Share on other sites

I was literally just coding an extended sprite example, but I can't see anything wrong in your code. The following full sample works fine here (no texture errors):

MonsterBunny = function (game, x, y) {    Phaser.Sprite.call(this, game, x, y, 'bunny');};MonsterBunny.prototype = Object.create(Phaser.Sprite.prototype);MonsterBunny.prototype.constructor = MonsterBunny;var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });function preload() {    game.load.image('bunny', 'assets/sprites/bunny.png');}function create() {    var wabbit = new MonsterBunny(game, 200, 300);    game.add.existing(wabbit);}
Link to comment
Share on other sites

That's weird.  I refactored yesterday to avoid the issue (abandoned Group for the collisions and just double looped it), but here's the entire Class from before the refactor:

Person = function(game) {    this.game = game;    Phaser.Sprite.call(this, game, 0, 0, 'person');};Person.prototype = Object.create(Phaser.Sprite.prototype);Person.prototype.constructor = Person;// constantsvar rescueRange = 15;// variablesPerson.prototype.game = null;Person.prototype.alive = false;Person.prototype = {    /// @param: validRanges = list of left/right edge pairs for valid creation locations    create: function(validRanges, y)    {        this.y = y;        var tries = 100;        do{            this.x = game.world.randomX;        }while(!this.inValidRange(this.x, validRanges) && --tries > 0);        this.animations.add('person');        this.animations.play('person', 7 + Math.random() * 5, true);        this.animations.getAnimation('person').frame = Math.floor(Math.random() * 10);        this.game.physics.enable(this, Phaser.Physics.ARCADE);        this.enableBody = true;        this.anchor.setTo(.5, 1.0);        this.body.bounce.setTo(.1, .1);        this.body.gravity.y = 400;        this.body.drag.x = 1000;        this.body.drag.y = 0;        this.body.collideWorldBounds = true;        this.alive = true;    },    update: function(chopper)    {        if (this.game.physics.arcade.distanceBetween(this, chopper.sprite) < rescueRange)        {            this.alive = false;            this.kill();        }    },    inValidRange: function(x, validRanges)    {        for(var i = 0; i < validRanges.length; i++)        {            if (x >= validRanges[i * 2 + 0])                if (x <= validRanges[i * 2 + 1])                    return true;        }        return false;    }};
Link to comment
Share on other sites

I am doing the same thing in my code, except I am loading a texture atlas instead of a spritesheet, and I get no problems.


At what point are you trying to create this Person object?

Everything looks okay here, the problem must be coming from somewhere else.

Link to comment
Share on other sites

I try to create a bunch of Person objects as the game level starts up, I don't think there's any problem with the call location as I'm also creating the chopper and buildings at the same time and they work fine.


Is your texture atlas loaded with the "game.load.spritesheet" command?

Given that everyone says my Person class is ok, my graphic loading is ok, and that what I'm trying to do should work... I'm tempted to believe it's just a minor bug when handling spritesheet only.


If you have dropbox and are willing, the full project is here

I'm still in the 30 day free trial of WebStorm editor and those project files are there too.

Link to comment
Share on other sites

The Person class above isn't correct, sorry. What you're doing is this:


1) Copying the Phaser.Sprite prototype into Person. This bit is fine.


2) You're then replacing the prototype entirely with the line:

Person.prototype = {

This actually overwrites the entire prototype with whatever you define in this new object. What you want to do is add new functions onto the existing prototype, like this:

Person.prototype.create = function() { ... }

This will add create onto the existing prototype, rather than replace it.


Also a couple of other things:

Person = function(game) {    this.game = game;    Phaser.Sprite.call(this, game, 0, 0, 'person');};

You shouldn't have this.game = game here. It won't hurt, but it's pointless as it's set by the Phaser.Sprite.call anyway.


Also don't set game to null on the Person prototype (for similar reasons). Let the Object inheritance take care of it. I would put this.alive = false inside the Person constructor too if I were you.


Is rescueRange meant to be a Person level const? If so define it like this:

Person.rescueRange = 15;

Do this after the Person constructor (not within it).


If you need rescueRange to change on a per Person basis then define it locally within the constructor. But if every Person has the exact same range, the above is a better approach.


Edit: To explain why, if you just do var rescueRange you've created a global level var, not an object level one, which is what you need.

Link to comment
Share on other sites

Thanks Rich, I'm sure you've nailed it.  I've moved ahead with a non-inherited class version of the project now but I'll apply those changes to the branch to make sure they fix it.  Next time I want to inherit it'll be great to have an example to follow.

I was aware that my 'const' were not actually const, but I read that the const keyword is only partially supported in JS right now so I didn't want to risk it.  I didn't know I could define stuff straight onto the class name like that.

Person.rescueRange = 15; is presumably still a variable but is local to the class scope and unitary?

Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...