Uriel Bertoche
Uriel Bertoche

Reputation: 883

Javascript class structure for game component

I am here today with a more design/conceptual doubt on how to approach a certain class scenario I'm planning to code.

Here's the deal, I am to implement a class Monster, which will hold most of the data related to kinds of monster existent in my game, but it will not hold effective data, in fact, what I want to store here are range of possible values, so when I actually create a monster object, it will have it's attributes within the range for the race/kind of the monster encountered.

Exemplifying: I will have different types of monster, Rat, Spider, Snake, Wolf. Each of this species will roll attributes within certain ranges:

Rat: Attack [5,9], Defense [3,5]
Spider: Attack [6,11], Defense [4,5]
...

I would like to have these data on a JSON object in my js file, from which I would then load its data and prepare to create the monster object on encounter taking this values into consideration.

What is troubling me is the design I should make for this to happen. I would say that a good way to make reference to the types of monsters would be something like, Monster.Rat, Monster.Spider, and call their constructor when the encounter happens: Monster.Spider() -> Would give me a monster object with random attributes within a spider range.

Also some point in time I would like to create specific areas for finding specific types of monsters, and I fail to see clearly how I would do that in a simple way, without making the code hard to read.

I did something like this a couple months ago, using Swift, and the approach I made was having a class method on monster for every type of monster I wanted, but this was hard to maintain, since if I wanted to change the way monsters were created I would have to change all the methods, also add a new method for every new type of monster desired.

What do you think would be the best way to handle the design of a game like that? I know I don't want to create new classes extending Monster for every new type of monster I have, as that feels terribly wrong and bad design to me.

Thanks for your time, I'll keep this post updated with whatever interesting piece of information I find.

Upvotes: 0

Views: 286

Answers (1)

thephpdev
thephpdev

Reputation: 1117

EDIT: I've made a couple of improvements to this script for you, too - just to highlight what can be done:

var Monster = {
    monsters: {
        rat: {
            attack: [5, 9],
            defense: [3, 5],
            health: [5, 10],
            title: "Rat"
        },

        spider: {
            attack: [6, 11],
            defense: [4, 5],
            health: [4, 6],
            title: "Spider"
        }
    },

    create: function(type) {
        // choose type at random if not specified
        if(typeof type !== "string") {
            var keys = [ ];
            for(var key in this.monsters) {
                if(this.monsters.hasOwnProperty(key)) {
                    keys.push(key);
                }
            }

            type = keys[Math.floor(Math.random() * keys.length)];
        }

        // check if given monster type exists
        if(typeof this.monsters[type] === "undefined") {
            throw new TypeError('invalid monster type "' + type + '"');
        }

        var monster = { };

        /*
         * This allows you to add new attributes and not have to change any
         * of this code, except the attributes object for each monster.
         */
        for(var attribute in this.monsters[type]) {
            if(this.monsters[type].hasOwnProperty(attribute)) {
                var a = this.monsters[type][attribute];

                if(typeof a == "object") {
                    a = Math.floor(Math.random() * (a[1] - a[0] + 1) + a[0]);
                }

                monster[attribute] = a;
            }
        }

        return monster;
    }
};

console.log(Monster.create('rat'));
console.log(Monster.create('spider'));
console.log(Monster.create());

This is what I'd do, this is nice and simple, and allows easy adding of monsters and attributes in future:

var Monster = {
    monsters: {
        rat: {
            attack: [5, 9],
            defense: [3, 5],
        },

        spider: {
            attack: [6, 11],
            defense: [4, 5]
        }
    },

    create: function(type) {
        // check if given monster type exists
        if(typeof this.monsters[type] === "undefined") {
            throw new TypeError('invalid monster type "' + type + '"');
        }

        var monster = { };

        /*
         * This allows you to add new attributes and not have to change any
         * of this code, except the attributes object for each monster.
         */
        for(var attribute in this.monsters[type]) {
            if(this.monsters[type].hasOwnProperty(attribute)) {
                var a = this.monsters[type][attribute];
                monster[attribute] = Math.floor(Math.random() * (a[1] - a[0] + 1) + a[0]);
            }
        }

        return monster;
    }
};

console.log(Monster.create('rat'));
console.log(Monster.create('spider'));

Upvotes: 3

Related Questions