Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

Enemy Inheritance


pete796
 Share

Recommended Posts

Hi everyone, 

I'm trying to create two types of enemies, the first is a robot that has 2 methods: sleep and patrol.

My second enemy is a flyingEnemy. The aim is to inherit the sleep method from the robot but amend the patrol method.

Can anyone show me how my flyingEnemy can inherit from robot whilst amending the patrol method?

Below is my code. When I create the flyingEnemy,  its patrol method overwrites the robot's patrol method and ALL enemies have the same behavior.

 

var SuperSmash = SuperSmash || {};

SuperSmash.flyingEnemy = function(game, x, y, key, velocity, tilemap, player) {
  "use strict";
  SuperSmash.Enemy.call(this, game, x, y, key);

  this.game = game;
  this.tilemap = tilemap;
  this.player = player;
 
  this.animations.add("fly", [0]);
};

SuperSmash.flyingEnemy.prototype = Object.create(SuperSmash.Enemy.prototype);
SuperSmash.flyingEnemy.prototype.constructor = SuperSmash.flyingEnemy;

SuperSmash.flyingEnemy.prototype.patrol = function() {
  "use strict";
   SuperSmash.game.physics.arcade.moveToObject(this, this.player, 200);
};


 

 

Link to comment
Share on other sites

You can use

SuperSmash.flyingEnemy.prototype.patrol = function() {
    SuperSmash.Enemy.prototype.patrol.call(this, arguments);
    // + flying stuff…
};

Your example has SuperSmash.Enemy.prototype.patrol twice, I think the 2nd is supposed to be flyingEnemy.

Also, though it's harmless, the

this.game = game;

assignments are redundant (the `game` property is already set by Phaser.Sprite). I've seen this somewhere else so I'm worried someone's putting it in tutorials or something. :D

Link to comment
Share on other sites

Glad you resolved it but I'm still curious as to how you managed to break it in the first place! Did you inadvertently apply a new function to the base prototype rather than the child prototype?

I created a couple of fiddles and struggled to break stuff,


class Base {
  constructor (name) {
    this.name = name
  }
}

class Robot extends Base {
  constructor (name)  {
    super(name || 'Robot')
  }

  sleep (time) {
    console.log(this.name, 'is sleeping...')
    setTimeout(() => {
      console.log(this.name, 'is now awake again.')
    }, time)
  }
  
  patrol () {
    console.log(this.name, 'is patrolling.')
  }
}

class Flyer extends Robot {
  constructor (name) {
    super(name || 'Flyer')
  }

  patrol () {
    console.log(this.name, 'is starting an airborne patrol.')
  }
}

var robot = new Robot()
var flyer = new Flyer()

robot.sleep(100)
robot.patrol()

flyer.sleep(100)
flyer.patrol()

ES6

ES5

1 hour ago, pete796 said:

flyingEnemy has its own patrol method

This is the bit I think that confuses me. Given your requirements, which you stated really clearly:

3 hours ago, pete796 said:

The aim is to inherit the sleep method from the robot but amend the patrol method.

Can anyone show me how my flyingEnemy can inherit from robot whilst amending the patrol method?

How else would you code that but to inherit from your base Robot whilst overriding its patrol method? You could directly call the Base.patrol method from the child, but depending on how the functions work that might not be desirable.

Part of why I ask is because you're exposing some of the vulnerability and frailty that can become evident in code that relies on inheritance, namely, your FlyingEnemy class has to intricately know the workings of the Base it is inheriting from, not just method names and call parameters, but how that code actually works so you can work out whether it is safe to call a parent (or super) function or not (it gets even trickier when you have to change requirements further down the line and change a class way up your hierarchy, note only do you have to change that class but potentially change all others that inherit from it—because they rely on its implementation—, turning a 10 minute job into an X hr job). With just 2 objects at play it isn't too much of a strain but as you extend your models it becomes intricately difficult to near impossible to accurately hold all that information in your head, which is exact antithesis of the problem inheritance attempts to resolve. Note that this is of particular difficulty to JS because it has no real language level safeguards against these sort of issues, hence why the phrase 'Favour Composition over Inheritance' is sewn into JS's underpants.

There is a great quote that sums this up:

Quote

You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

-- Joe Armstrong

The other thing is that (and maybe its just how you phrased it) it doesn't necessarily sound like a FlyingEnemy IS a Robot, more that it just wants some features that a Robot implements. There is a fundamental difference here that is at the heart of inheritance, if you're inheriting then the Child must actually BE its parent, but with some changes or additions. Even if you follow this principle using inheritance too liberally can still be a nightmare but if you don't follow this then your code will quickly become a mess of exceptions and clauses that try to paper over the cracks, and they'll either flat fail or be so time-consuming and bug-introducing that it'll be a near permanent battle. Polymorphism tries to solve this in a sledgehammer-nail kind of way (it has other uses too) but we have none of that in JS, what we can do though is pinch some stuff from more functional languages and use something like a mixin (i.e. composition) to allow our FlyingEnemies to also utilise some methods that Robot's implement.

As I say, this might be more in the way that you have phrased it, but if you haven't thought about it too much yet you might want to consider if using composition over inheritance in this instance would be beneficial as your object hierarchy grows.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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