Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better for massive amounts of Variables

So after reading massively into JS the past few days (I'm just starting with it) I have come upon 3 viable options for my project, which is a game btw. There will be about 200 items in my game, with a total of about 30 stats/properties. But since the program has to know that a Sword doesn't give Spell damage than I have to give each item all those 30 properties even if 90% will be 0. So here is what I came up with, any advice is greatly appreciated:

var prop, obj = { Item1: "Boots", Item2: "Gloves", Item3: "Sword", Item4: "Cape" };

// Pretty sure I'd have to remake this somehow to put properties in there, this might not be as useable

function Item(hp, mp, dmg, spd, luk) {
    this.hp = hp;
    this.mp = mp;
    this.dmg = dmg;
    this.spd = spd;
    this.luk = luk;
}
var BigSword = new Item(0, 0, 50, 20, 10)

//I think this might be my best option so there are as few variables as possible? or does that not matter as much? I figured with this option whenever I update totalHp and totalMp and totalDmg etc in the updating function I can create a local variable called theItem = BigSword and then just do theItem.hp, theItem.mp and that way it doesn't have to search much for the variable and should run relatively faster? Sorry for the newbie question but does JS even have local variables in functions? As in if I do var theItem = whatever, then theItem will be null outside the function?

itemNames = [ "Boots", "Gloves", "Sword", "Cape" ];
itemHp = [ 0, 0, 0, 50 ];
itemMp = [ 0, 30, 0, 0 ];
itemDmg = [ 0, 0, 50, 0 ];
itemSpd = [ 50, 0, 0, 0];

//This is the other option that I came up with, a little uglier but if it's faster or better to just use arrays I don't mind that much.

But please keep in mind, like I said, 200~ish total items, each item will have around 30 properties. What do you think?

Thanks a lot for reading and for any information provided, it's greatly appreciated! Thanks in advance

like image 568
Hate Names Avatar asked Feb 16 '23 09:02

Hate Names


2 Answers

Your best bet is to have a constructor, as you have in your first example. However, I'd change a few things. First of all, for the constructor, you're simply passing in a lot of numbers. This is bad, because it's very easy to forget the order in which your numbers go. A better way to go would be to pass in an object to your constructor, so you can label each property:

function Item(props) {
    this.hp = props.hp;
    this.mp = props.mp;
    this.dmg = props.dmg;
    this.spd = props.spd;
    this.luk = props.luk;
}

var BigSword = new Item({
    hp: 0, 
    mp: 0, 5
    dmg: 0, 
    spd: 20, 
    luk: 10
});

This is nice, but still a pain, because you have all sorts of different items, and as you said, you'd have to define 30 properties for each item, which gets both messy and time-consuming. At this point you get into the realm of more complex object oriented stuff. From here you have basically two options: inheritance and construction.

Inheritance

Using object inheritance to properly define objects is one probably the more common of the two, and is fairly straightforward. In essence, you have a "class" of object, and then sub-classes of each class. So you might have Magical Items and Non-Magical Items as two classes. If you had a magic belt, perhaps, you'd want to make it inherit the properties of the Magical Item class. On the other hand, if you had a basic un-charmed sword, you'd want to make it inherit from the Non-Magical Item class.

But say you have magical scrolls and magical potions. Those are both magical items, right? So you'd want to make a class called Potions and a class called Scrolls, which both inherit from the Magical Item class. Then you might have certain types of potions. Healing potions, maybe--"Magical Potion of Heal Allies" and "Magical Potion Of Heal Self". So you'd need different classes for those--and so on and so forth.

Inheritance in Javascript can be done a number of different ways and it's possible to get very in-depth, so I'm not going to discuss it in my post. Here are a few useful links to get you started with inheritance, though, if you want to go that route:

  • David Crockford on Inheritance
  • MDN on Inheritance and MDN Inheritance Revisted
  • Alex Sexton on Inheritance

Composition

Composition is a concept that borrows heavily from other loosely-typed languages, such as Python, which employs it quite extensively. The basic idea behind composition is that you have a base object class, and whenever you need a certain specific type of object, you add behaviors, or members, to that base class. This isn't quite as well-known as inheritance, but it's definitely the one I prefer.

In Javascript, it works by having a base constructor, Item, and then having other constructors which add the necessary behaviors to your Item. Let's take a look at the example I used for composition--creating a Magical Potion of Heal Allies. You have several distinct properties here: Magical Item, Potion, Healing. With inheritance you'd do something like Item -> Magical -> Potion -> Healing Potions -> Allies. However, with composition, you can add several behaviors to a base Item class, without having to set up a huge prototype chain: Affect Allies, Potion, Healing.

Since composition is a bit simpler than inheritance (and, I'll admit it, I'm biased) I'll set up a quick example in psuedo-code:

// base item class
function Item(props) {
    this.someProperty = props.someProperty;
    this.someOtherProperty = props.someOtherProperty;
}

// potion behavior
function Potion(props) {
    this.amount = props.amount; // IDK what amount means, just some random potion property
    this.color = "green";
}

// healing behavior
function Healing(props) {
    this.amountToHeal = props.amountToHeal;
    this.cooldown = props.cooldown;
}

// behavior to affect allies
function AffectAllies(props) {
    this.allies = props.allies;
    for(ally in this.allies) {
        this.allies[ally].affect(props.affact);
    }
}

// at this point we have the various behaviors set up and we can create the Magical Potion of Heal Allies constructor:

function MassHealingPotion(props) {
    var self = this;

    this.amount = props.amount;
    this.potion = new Potion(props);
    this.effect = new Healing(props);
    this.AffectAllies = new AffectAllies({
        affect: function(ally) {
            self.potion.affect;
        },

        allies: player.allies;
    });
}

// you can now create a mass healing potion:
var potion = new MassHealingPotion({
    weight: 50,
    someProp: "someValue",
    someOtherProp: "someOtherValue"
    // and so on and so forth with whatever properties you want the potion to have
});

Well, that turned out a bit longer than I expected and probably contains proportionally more errors than I'd like, but I hope that conveys the basic idea of composition.

Now, simpler object creation isn't even the best part of composition, which is that you can re-use different behaviors. Consider you have a magical sword that whenever you make an attack it heals your allies. All you have to do is give it the Healing member and the AffectAllies member and boom--magical sword of heal buddies. With inheritance, you'd have to create a Swords class in the Magical Items class (and then you'd have two different Swords classes-one for Non Magical Swords and the other for Magical Swords! Ew!), then extend that with Healing Swords, and so on and so forth.

You can go either way, inheritance or object composition. Both are equally effective for what you want to achieve.

But what about performance?

200 items with 30 properties a piece? Not a problem. Stick them all in one giant array/object, boil 'em, mash 'em, stick 'em in a stew. The browser don't care. Your best bet is probably an object, though:

var itemList = {
    bigSword: new BigSword(...);
    smallSword: new SmallSword(...);
}
like image 86
Elliot Bonneville Avatar answered Feb 18 '23 22:02

Elliot Bonneville


I would prefer Objects. I would start with a simple, generic "Item" and then build specific items by "inherit" from the generic one with prototyping.

That probably may reduce code redundancy and increase maintainability dramatically.

Speedwise I don't have a clue but I think iterating through 200*30 array values isn't also that fast.

like image 41
Axel Amthor Avatar answered Feb 18 '23 21:02

Axel Amthor