[JS] Writing a good class system

4

Features on these Courses

Stats

2,423 visits, 3,284 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 3 Aug, 2019. Last updated 24 Feb, 2020

In C3 we now have the option to subclass objects. This essentially means writing a class that extends an object class and will allow us to add custom code to the already present object's code.

What this can be used for is pretty straightforward: If you want to replace the code you have in your events with JS, you need a way to access stuff like object position right?

Anyway there is one issue with that system being that it only allows us to add one class to our object, which might be bad in case we want to have a family like system where objects can be added to many different groups that all have a defined behavior.

SpriteBase.js

In order to make that possible the first class you want to write should be one that acts as a middleman between your behavior classes and your object. Something like that should work:

class SpriteBase extends ISpriteInstance {
	constructor(){
		super()
	}
	
	addBehavior(name, behavior){
		if(!this.hasOwnProperty(name))
			this[name] = behavior
	}
}

This is a super simple code that just allows further subclasses to link other classes to the object, basically acting like a behavior system

Behaviors

Now let's say I have a battle system and I want some objects to have access to battle system features but I also want them to be able to do other things.

I'll start by writing a BattleEntity class:

class BattleEntity {
	constructor(inst){
		this.inst = inst
		this.runtime = inst.runtime
		this.skills = []
	}
	
	execSkill(id){
		return this.runtime.startCoroutine(this.skills[id].actions(this, this.inst))
	}
}

Subclassing the subclass

Now I want to create a class that extends the SpriteBase class and adds a BattleEntity behavior to it

class Pawn extends SpriteBase {
	constructor(){
		super()
		this.addBehavior("battle", new BattleEntity(this))
	}
}

If I ever want to add other features to my Pawn, I can either add them directly in the class, or I can add them in a separate class and add it as a behavior.

Subclassing the subclass of a subclass...?

I can also decide to use that Pawn class as a base class for other battle entities

class Watcher extends Pawn {
	constructor(){
		super()
		this.battle.skills = [
			this.runtime.battleSystem.skills.watcherSkill1,
		]
	}
}

Anyway...

Now you have some code that's modular extendable and allows for a bit more organisation in your code.

  • 5 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • I can tell from your article that you have NOT read Kyle Simpson "You Don't Know JS Yet: Objects & Classes - 2nd Edition" found at github.com/getify/You-Dont-Know-JS/blob/2nd-ed/objects-classes/README.md

    You're steering people down a horrible path of super-imposing OOP on top of JavaScript Prototypes.

    • Why does your message sound like a bot wrote it? I can't tell if you're just trying to advertise your link or if you're actually being serious.

      • 14 years teaching software engineering in college. I'm trying to protect your reputation. Does that sound like a "BOT"???

        • To be fair, yes you do sound like a bot.

          To reply to your original message: This course was written when JS in C3 was a fairly new feature. While I think it still does have some merit, I would not use that paradigm anymore.

          JS in C3 is a lot more versatile than it used to be, and using the subclassing is almost never a good idea nowadays. Also, to be perfectly clear, this is specifically a suggestion on how to use JS in C3, not how to use JS in general. Having to compose with a game engine, a partially exposed runtime and a toolset makes it much different than if you were using exclusively JS.

          Now, I still don't understand why you would call using classes "super-imposing OOP on top of JavaScript Prototypes", but whatever.