InsaneHero Posted May 21, 2014 Share Posted May 21, 2014 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: this.onTextureUpdate(); 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 More sharing options...
rich Posted May 21, 2014 Share Posted May 21, 2014 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 More sharing options...
InsaneHero Posted May 21, 2014 Author Share Posted May 21, 2014 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 More sharing options...
InsaneHero Posted May 21, 2014 Author Share Posted May 21, 2014 Could it be because it's a spritesheet animation and not an image? this.game.load.spritesheet('person', 'img/waver.png', 16, 16); Link to comment Share on other sites More sharing options...
XekeDeath Posted May 22, 2014 Share Posted May 22, 2014 Where is the execution up to in your code when it stops? Link to comment Share on other sites More sharing options...
InsaneHero Posted May 22, 2014 Author Share Posted May 22, 2014 In my code it's at line 6 of the Person constructor: Phaser.Sprite.call(this, game, 0, 0, 'person'); Link to comment Share on other sites More sharing options...
XekeDeath Posted May 22, 2014 Share Posted May 22, 2014 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 More sharing options...
InsaneHero Posted May 22, 2014 Author Share Posted May 22, 2014 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 hereI'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 More sharing options...
rich Posted May 22, 2014 Share Posted May 22, 2014 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. XekeDeath and InsaneHero 2 Link to comment Share on other sites More sharing options...
XekeDeath Posted May 22, 2014 Share Posted May 22, 2014 Person.prototype = {See, I didn't even look there. Everything is fine here:Phaser.Sprite.call(this, game, 0, 0, 'person');so the problem is somewhere else, somewhere like exactly where Rich said... Have I saved enough face yet.....? InsaneHero 1 Link to comment Share on other sites More sharing options...
InsaneHero Posted May 22, 2014 Author Share Posted May 22, 2014 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 More sharing options...
rich Posted May 22, 2014 Share Posted May 22, 2014 Yes it's still a var but an object level one, there's no such thing as a real const in JS yet, so you still have to be careful not to modify it. Link to comment Share on other sites More sharing options...
Recommended Posts