Converting/undertanding object:properties to class based

Started by
3 comments, last by lmbarns 12 years, 1 month ago
I understand javascript, can do pretty much everything I want with it, but I'm now using c# and struggling to make the crossover to classes.....

I've worked on some js games with html5, and I want to implement one of the features now in C#, but I'm kinda lost when it comes to classes instead of objects with properties....

Example #1:

var lootedItem;
var maxLikelihood = 0;
var loot = {
silver : 3,
bronze : 3,
copper : 3,
platinum: 1,
iron : 5,
stone : 5,
gold : 2
};
var playerInventory = {
silver : 0,
bronze : 0,
copper : 0,
platinum: 0,
iron : 0,
stone : 0,
gold : 0
};


2 basic objects with the same properties. In Javascript, you can simply loop through an object's properties, and for each property, add it to an array.

var lootArray = []; //array to hold our properties
for (var p in loot){ //for property in objectname
if(loot.hasOwnProperty(p)){
lootArray.push(p); //add to array
maxLikelihood = Math.max(maxLikelihood, loot

);
}
}



But in C# it seems arrays are not recommended? Lists or Enumerations are? I could almost use an enumeration in place of the "loot" object, but the playerInventory changes and aren't enums constants?

I love this object:property setup because I can then make some basic functions to display/update, store, retrieve, add, subtract, or clear the playerInventory very easily like:

/*Randomly pick an item from the loot object and give it to the corresponding inventory object for the player */
function addLoot(){ //Add an item to players inventory
lootedItem = lootArray[Math.floor(Math.random() * lootArray.length)]; //pick an entry from the loot object at random
playerInventory[lootedItem] = +playerInventory[lootedItem] + loot[lootedItem]; //update the corresponding property
allLoot(); //display updated results
storeIt(); //store results for persistence
}
/*Display the players inventory in a list of key:value pairs*/
function allLoot(){
var r = ['Player Inventory\n'];
for(var i = 0; i < lootArray.length; ++i){
r.push(lootArray + (lootArray.length < 8? '\t : ' : ' : ') + playerInventory[lootArray]);
}
if(document.getElementById('allloot') != null) {
document.getElementById('allloot').firstChild.nodeValue = r.join('\n');
}
}
/* Store the players inventory values in localstorage, could be mysql or some other storage medium */
function storeIt() {
for(var i = 0; i < lootArray.length; ++i){
localStorage.setItem(lootArray, playerInventory[lootArray]);
}
}
/*Retrieve existing entries from storage from previous sessions to maintain persistence*/
function retrieveIt(){
var key;
for(var i = 0; i < localStorage.length; ++i){
key = localStorage.key(i);
if(playerInventory.hasOwnProperty(key)){
playerInventory[key] = localStorage.getItem(key);
}
}
}


That worked extremely well for me. When I need to "randomly" generate loot (player killed something or looted a chest or bought something in town) I can simply call addLoot() for each random item I want to generate. Same for skills, stats, etc etc etc I can also call individual entries, like playerInventory[2] if I want to manually manipulate the 3rd property in playerInventory, like buying/selling a non random item, or for crafting to check for/subtract ingredients and add created item....


But as far as classes I'm at a loss. Do I create 2 classes, one for playerInventory, the other for the potential loot table? I should mention in js I have a dozen of these object pairs with helper functions, for stats, skills, spells, loot, crafting, etc etc etc so that would be 2 dozen classes using that route.

Otherwise maybe an enumeration and a list, the enumeration holds the potential loot values, the list is the players inventory which is updated?

Could someone pseudo the above code for me how it would be done with a class??? Can you just have 2 objects with properties in the same class with helper "methods" to manipulate the properties?????

Is there a classical alternative to this:
for (var p in loot){
if(loot.hasOwnProperty(p)){
//yadayadayada
}
}
Advertisement

But in C# it seems arrays are not recommended? Lists or Enumerations are?


Correct. You're taking advantage of JavaScript's dynamicness. C# has a class that will do that, but it's generally considered bad form. In C#, you're more likely to use some structure that defines what the resource is and how many of them; or instead what the object is if you're unlikely to have many of them.

Here's a quick example of how to use an enum how you're kinda doing this:

[source lang='Csharp']
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace gamedev_temp_loot {
enum Loot {
Silver,
Bronze,
Copper,
Platinum,
Iron,
Stone,
Gold
}

class Program {
static void Main(string[] args) {
var lootValues = new List<Loot>(Enum.GetValues(typeof(Loot)).Cast&lt;Loot&gt;());
var rng = new Random();

// random loot
Console.WriteLine(lootValues[rng.Next(lootValues.Count)]);
}
}
}

[/source]

That said; you should not do this. This assumes an equal distribution between each thing. Having a separate loot table/function and a separate structure for inventory will serve you better.


I should mention in js I have a dozen of these object pairs with helper functions, for stats, skills, spells, loot, crafting, etc etc etc so that would be 2 dozen classes using that route.


You'll find that defining the classes only needs to be done once, and afterwards makes working with them bugfree much more reliable and speedy.
I am not sure you are going to understand this, but lets give a try:
Possible solution:
Create a class for an Item, which will consist of the properties for these items: Name, Value and whatever you want and you may need.
Then Inherit this class with all possible loot items - create a class for Silver, Gold, Bronze etc.

Then all you need is a class for the Player itself, which will have a property PlayerInventory, which for simplicity can be List<Items>.
When you have to loot a corpse for instance, it will have its own Inventory( List<Items>) and you will just loop throught the items and add them to the player inventory List<Items>

check this article: http://msdn.microsoft.com/en-us/library/ms173152%28v=vs.100%29.aspx

Then Inherit this class with all possible loot items - create a class for Silver, Gold, Bronze etc.


Please... do not do this. It is the classic overuse of inheritance. What do these things share in common? Names, that you can carry multiple of them?

No, it's better to create a structure and then encode what it is via an enum or other structure. Encoding information into the type is incorrect in a language like C# and will only cause you grief.
First, Thx Telastyn for your example.

The part I was loving with the object:property was, I could add a ton of properties, and it was just a placeholder for the number of items you had. Like a linked list. I could then use a constructor to make the item if I needed it, and subtract 1 from the property for that item. So if the player sold a gold ingot to an npc, it would deduct 1 from the playerInventory[goldIngotPropertyIndex] and increase the playerInventory[goldCoinsIndex] by 400 if a gold ingot was worth 400g.

The other way I was using it was for crafting. Say I have 3 ingredients and an item that they make when created:

var craftables = {
twigs: 1,
string: 1,
ductTape: 1,
lightsaber: 0
}


And say somewhere I have a function, if the user opens a crafting menu, and clicks the icon to craft a "lightsaber", it triggers a function makeLightSaber()

Example makeLightSaber():

function makeLightSaber(){
if(craftables[0] >0 && craftables[1] > 0 && craftables[2] > 0) {
//crudely subtract 1 of each ingredient
craftables[0] -= 1;
craftables[1] -= 1;
craftables[2] -= 1;
//give us the crafted weapon
craftables[3] += 1;
}
}


Now our object looks like:

var craftables = {
twigs: 0,
string: 0,
ductTape: 0,
lightsaber: 1
}


Then I can use a constructor to actually make and populate my lightsaber's properties damage, durability, etc. randomly, like maybe it gives a lightsaber a random damage between 7-9, random durability from 30-50, and attack speed between 0.7 - 1 so they're never quite the same.

I did this with everything, when I cast a spell, it deducts reagents and mana in this way, mana is just a property of the players object. Even shooting a fireball, I stored the frames used (num tiles / rows) in the fireball as properties for multi-line sprite sheets, if it gets to the end of a line it kicks it down to the first frame on the next row.

For my monsters, I had a huge loot table object, with 50 properties, in sections, a magic monster might randomly award something between the 1-10th properties, a ranger monster would randomly award from a pool of the 11th-20th properties on the same object, etc...god it was so damn easy to use this setup, randomly selecting from sections to award loot, like a slot machine of random prizes. Oh you opened a chest, here's randomly 5 items out of a pool of 50....

This topic is closed to new replies.

Advertisement